diff --git a/DEPS b/DEPS index e0c2cb5..1d84e7b 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': '7e7cae79f10ab3daecb713b73346e4b7bb914ea8', + 'skia_revision': 'd7b09c4c3acf69a3fea49f5baaa8b5bed954a6fc', # 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': '347e854b713ba7e4d782ae008fa116ceb8ba3687', + 'v8_revision': '75a11031417f6373146adf109048a99f67f82956', # 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': 'd667ad2f0127117e6a30057b09810dc0cce261e9', + 'angle_revision': '5276639d27894f3f35c43af5f038bf84e3aafe9f', # 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': '13f04d59c7278ac87191465bc16e2c7d145ae851', + 'swiftshader_revision': 'b65408064b1fd0f6d6f7ef1e4da7445c67ae166f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -258,7 +258,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': 'd56f379356d9fdbafd64e4f8545ac89e37485fab', + 'catapult_revision': '9f3ce85bab94e6c5f89c7615e0cc1bdcbe5c95e5', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # 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': '0377420e4c7146b701b34ed2dfdf361c262f868a', + 'devtools_frontend_revision': '51d97b104f7998cfec009f4de3376f613a4b1e4b', # 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. @@ -318,7 +318,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '37f547456cc61ba30bb27a60a18cbbdf1cd0d7e5', + 'dawn_revision': '1aff02d444786a451f72a9b3bb5d064f0b26e0f4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # 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' + '@' + '5245bcfaf6a900bad9c74f4b59b02d3281c32cb5', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'bca9dcdf05aaccf4e0c2dea6bd4cddced50f0c88', 'condition': 'checkout_chromeos', }, @@ -895,7 +895,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '65eb98d6ed3a80086d31a54f3c0165c7b466a967', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0e99b9be0afe1cf0aa824cf7fd919bbef66ba5d8', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1248,7 +1248,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'c4451adcce85638c2c52dbcc8606c04144500aa8', + Var('android_git') + '/platform/external/perfetto.git' + '@' + 'dfa133b7b48c5ef14f5040d3a735e5d350de06bd', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3', @@ -1470,7 +1470,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'c2cfd18ab8cabb29fe0866d467588d22b8c5e501', + Var('webrtc_git') + '/src.git' + '@' + '67615460bea48f58bdfeea04692bc7c93b8d5cbf', '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@2c4fc0c3259838594c5666c4a5691c5095c90e3f', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f7f46a7432a97842a94d75b0f9c2d677161dfc7c', 'condition': 'checkout_src_internal', },
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index be1c69e..6f1eeba 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -7,7 +7,7 @@ See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts for more details about the presubmit API built into depot_tools. """ - +PRESUBMIT_VERSION = '2.0.0' _EXCLUDED_PATHS = ( # Generated file. @@ -1458,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 @@ -1501,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. """ @@ -1547,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>', @@ -1590,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(): @@ -1606,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 @@ -1660,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(?!\(\))', @@ -1698,7 +1698,7 @@ return histogram_name in chunk -def _CheckUmaHistogramChanges(input_api, output_api): +def CheckUmaHistogramChangesOnUpload(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.""" @@ -1784,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 = [] @@ -1800,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(): @@ -1829,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()): @@ -1843,7 +1843,7 @@ return [] -def _CheckValidHostsInDEPS(input_api, output_api): +def CheckValidHostsInDEPSOnUpload(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()): @@ -1892,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 = [] @@ -1993,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 = [] @@ -2031,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', @@ -2051,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)') @@ -2070,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. @@ -2109,6 +2109,7 @@ 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()) @@ -2158,7 +2159,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 [] @@ -2183,7 +2184,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. """ @@ -2216,7 +2217,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(): @@ -2229,7 +2230,7 @@ return results -def _CheckGoogleSupportAnswerUrl(input_api, output_api): +def CheckGoogleSupportAnswerUrlOnUpload(input_api, output_api): pattern = input_api.re.compile('support\.google\.com\/chrome.*/answer') errors = [] for f in input_api.AffectedFiles(): @@ -2245,7 +2246,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 @@ -2279,7 +2280,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.""" @@ -2320,7 +2321,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. @@ -2414,7 +2415,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 @@ -2493,7 +2494,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 + @@ -2572,7 +2573,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).""" @@ -2628,7 +2629,7 @@ return [] -def _CheckUniquePtr(input_api, output_api): +def CheckUniquePtrOnUpload(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): @@ -2726,7 +2727,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()): @@ -2798,7 +2799,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, @@ -2852,7 +2853,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 @@ -2869,7 +2870,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\(') @@ -3068,7 +3069,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) @@ -3158,7 +3159,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. """ @@ -3194,7 +3195,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) @@ -3259,7 +3260,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. @@ -3730,7 +3731,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 @@ -3792,7 +3793,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<|. @@ -3852,7 +3853,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 @@ -3880,7 +3881,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 @@ -3918,7 +3919,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 @@ -4058,7 +4059,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') @@ -4087,7 +4088,7 @@ return [] -def _CheckNewHeaderWithoutGnChange(input_api, output_api): +def CheckNewHeaderWithoutGnChangeOnUpload(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. @@ -4127,7 +4128,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 @@ -4171,7 +4172,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 @@ -4211,7 +4212,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 @@ -4243,7 +4244,7 @@ return [] -def _CheckFuzzTargets(input_api, output_api): +def CheckFuzzTargetsOnUpload(input_api, output_api): """Checks specific for fuzz target sources.""" EXPORTED_SYMBOLS = [ 'LLVMFuzzerInitialize', @@ -4324,7 +4325,7 @@ return errors -def _AndroidSpecificOnUploadChecks(input_api, output_api): +def ChecksAndroidSpecificOnUpload(input_api, output_api): """Groups upload checks that target android code.""" results = [] results.extend(_CheckAndroidCrLogUsage(input_api, output_api)) @@ -4340,7 +4341,7 @@ results.extend(_CheckAndroidNoBannedImports(input_api, output_api)) return results -def _AndroidSpecificOnCommitChecks(input_api, output_api): +def ChecksAndroidSpecificOnCommit(input_api, output_api): """Groups commit checks that target android code.""" results = [] results.extend(_CheckAndroidXmlStyle(input_api, output_api, False)) @@ -4361,7 +4362,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): @@ -4395,7 +4396,7 @@ return [output_api.PresubmitNotifyResult(message)] -def _CommonChecks(input_api, output_api): +def ChecksCommon(input_api, output_api): """Checks common to both upload and commit.""" results = [] results.extend(input_api.canned_checks.PanProjectChecks( @@ -4407,67 +4408,13 @@ 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') @@ -4493,7 +4440,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: @@ -4503,7 +4450,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_)[^)]*)') @@ -4585,7 +4532,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): @@ -4632,7 +4579,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/'] @@ -4651,7 +4598,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 """ @@ -4676,7 +4623,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. """ @@ -4694,7 +4641,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". @@ -4806,7 +4753,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. """ @@ -4836,10 +4783,10 @@ return [] -def _CheckSyslogUseWarning(input_api, output_api, source_file_filter=None): +def CheckSyslogUseWarningOnUpload(input_api, output_api, src_file_filter=None): """Checks that all source files use SYSLOG properly.""" syslog_files = [] - for f in input_api.AffectedSourceFiles(source_file_filter): + for f in input_api.AffectedSourceFiles(src_file_filter): for line_number, line in f.ChangedContents(): if 'SYSLOG' in line: syslog_files.append(f.LocalPath() + ':' + str(line_number)) @@ -4852,18 +4799,13 @@ def CheckChangeOnUpload(input_api, output_api): + if input_api.version < [2, 0, 0]: + return [output_api.PresubmitError("Your depot_tools is out of date. " + "This PRESUBMIT.py requires at least presubmit_support version 2.0.0, " + "but your version is %d.%d.%d" % tuple(input_api.version))] 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 @@ -4892,9 +4834,12 @@ def CheckChangeOnCommit(input_api, output_api): + if input_api.version < [2, 0, 0]: + return [output_api.PresubmitError("Your depot_tools is out of date. " + "This PRESUBMIT.py requires at least presubmit_support version 2.0.0, " + "but your version is %d.%d.%d" % tuple(input_api.version))] + 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, @@ -4912,7 +4857,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. @@ -5223,7 +5168,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): @@ -5268,7 +5213,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 111f2b2..cb9461d 100755 --- a/PRESUBMIT_test.py +++ b/PRESUBMIT_test.py
@@ -8,6 +8,7 @@ import unittest import PRESUBMIT + from PRESUBMIT_test_mocks import MockFile, MockAffectedFile from PRESUBMIT_test_mocks import MockInputApi, MockOutputApi @@ -52,7 +53,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, + warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -65,7 +66,7 @@ MockFile('some/path/foo.cc', diff_cc), MockFile('some/path/foo.java', diff_java), ] - warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, + warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual('warning', warnings[0].type) @@ -86,7 +87,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, + warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual('warning', warnings[0].type) @@ -107,7 +108,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, + warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -124,7 +125,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, + warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -146,7 +147,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, + warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -164,7 +165,7 @@ MockFile('some/path/foo.java', diff_java), MockFile('tools/metrics/histograms/histograms.xml', diff_xml), ] - warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, + warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -177,7 +178,7 @@ MockFile('some/path/foo.cc', diff_cc), MockFile('some/path/foo.java', diff_java), ] - warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, + warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -194,7 +195,7 @@ MockFile('some/path/foo2.cc', diff_cc2), MockFile('some/path/foo.java', diff_java), ] - warnings = PRESUBMIT._CheckUmaHistogramChanges(mock_input_api, + warnings = PRESUBMIT.CheckUmaHistogramChangesOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual('warning', warnings[0].type) @@ -211,7 +212,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]) @@ -225,7 +226,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]) @@ -236,7 +237,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)) @@ -254,7 +255,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)) @@ -265,7 +266,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)) @@ -687,7 +688,7 @@ contents_with_user_action)] self.assertEqual( - [], PRESUBMIT._CheckUserActionUpdate(input_api, MockOutputApi())) + [], PRESUBMIT.CheckUserActionUpdate(input_api, MockOutputApi())) def testUserMetricsActionNotAddedToActions(self): input_api = MockInputApi() @@ -699,7 +700,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 ' @@ -743,12 +744,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 [] @@ -772,7 +773,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 [] @@ -787,7 +788,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 [] @@ -799,7 +800,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 [] @@ -817,7 +818,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 [] @@ -836,7 +837,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 [] @@ -855,7 +856,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 [] @@ -1012,7 +1013,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), @@ -1066,7 +1067,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' @@ -1083,7 +1084,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' @@ -1103,7 +1104,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' @@ -1136,7 +1137,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' @@ -1157,7 +1158,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' @@ -1174,7 +1175,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') @@ -1191,7 +1192,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' @@ -1547,7 +1548,7 @@ ' "https://support.google.com/chrome/a/answer/123456";']), ] - warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl( + warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload( input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertEqual(2, len(warnings[0].items)) @@ -1560,7 +1561,7 @@ ' "https://support.google.com/chrome/?p=cpn_crash_reports";']), ] - warnings = PRESUBMIT._CheckGoogleSupportAnswerUrl( + warnings = PRESUBMIT.CheckGoogleSupportAnswerUrlOnUpload( input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1578,7 +1579,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)) @@ -1590,7 +1591,7 @@ ['char* host = "https://www.aol.com"; // google.com']) ] - warnings = PRESUBMIT._CheckHardcodedGoogleHostsInLowerLayers( + warnings = PRESUBMIT.CheckHardcodedGoogleHostsInLowerLayers( input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1611,7 +1612,7 @@ MockFile('components/exo/file.cc', ['PrefRegistrySyncable::SYNCABLE_PREF']), ] - warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration( + warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration( input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) @@ -1621,7 +1622,7 @@ MockFile('chromeos/file.cc', ['PrefRegistrySyncable::SYNCABLE_OS_PREF']), ] - warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration( + warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration( input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1635,7 +1636,7 @@ MockFile('content/browser/file.cc', ['PrefRegistrySyncable::SYNCABLE_PREF']), ] - warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration( + warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration( input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1646,7 +1647,7 @@ ['PrefRegistrySyncable::SYNCABLE_PREF', 'PrefRegistrySyncable::SYNCABLE_PRIORITY_PREF']), ] - warnings = PRESUBMIT._CheckChromeOsSyncedPrefRegistration( + warnings = PRESUBMIT.CheckChromeOsSyncedPrefRegistration( input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) @@ -1662,7 +1663,7 @@ 'class DummyClass;' ]) ] - warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1676,7 +1677,7 @@ '};' ]) ] - warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1690,7 +1691,7 @@ 'SomeStructPtr *p2;' ]) ] - warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) @@ -1704,7 +1705,7 @@ 'std::unique_ptr<UsefulClass> p;' ]) ] - warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) @@ -1720,7 +1721,7 @@ 'struct DummyStruct;', ]) ] - warnings = PRESUBMIT._CheckUselessForwardDeclarations(mock_input_api, + warnings = PRESUBMIT.CheckUselessForwardDeclarations(mock_input_api, MockOutputApi()) self.assertEqual(4, len(warnings)) @@ -1735,7 +1736,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForRelativeIncludes( + errors = PRESUBMIT.CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1747,7 +1748,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForRelativeIncludes( + errors = PRESUBMIT.CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1760,7 +1761,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForRelativeIncludes( + errors = PRESUBMIT.CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1772,7 +1773,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForRelativeIncludes( + errors = PRESUBMIT.CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) @@ -1785,7 +1786,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForRelativeIncludes( + errors = PRESUBMIT.CheckForRelativeIncludes( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) @@ -1799,7 +1800,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForCcIncludes( + errors = PRESUBMIT.CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1811,7 +1812,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForCcIncludes( + errors = PRESUBMIT.CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1823,7 +1824,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForCcIncludes( + errors = PRESUBMIT.CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1836,7 +1837,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForCcIncludes( + errors = PRESUBMIT.CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(0, len(errors)) @@ -1848,7 +1849,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForCcIncludes( + errors = PRESUBMIT.CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) @@ -1861,7 +1862,7 @@ mock_output_api = MockOutputApi() - errors = PRESUBMIT._CheckForCcIncludes( + errors = PRESUBMIT.CheckForCcIncludes( mock_input_api, mock_output_api) self.assertEqual(1, len(errors)) @@ -1872,7 +1873,7 @@ mock_input_api.files = [ MockAffectedFile('base/stuff.h', ''), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertTrue('base/stuff.h' in warnings[0].items) @@ -1882,7 +1883,7 @@ mock_input_api.files = [ MockAffectedFile('base/stuff.h', '', action='M'), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1891,7 +1892,7 @@ mock_input_api.files = [ MockAffectedFile('base/stuff.h', '', action='D'), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1901,7 +1902,7 @@ MockAffectedFile('base/stuff.h', ''), MockAffectedFile('base/BUILD.gn', 'stuff.h'), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1911,7 +1912,7 @@ MockAffectedFile('base/stuff.h', ''), MockAffectedFile('base/files.gni', 'stuff.h'), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1921,7 +1922,7 @@ MockAffectedFile('base/stuff.h', ''), MockAffectedFile('base/stuff.cc', 'stuff.h'), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) @@ -1931,7 +1932,7 @@ MockAffectedFile('base/stuff.h', ''), MockAffectedFile('base/BUILD.gn', 'stuff_h'), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) @@ -1942,7 +1943,7 @@ MockAffectedFile('base/another.h', ''), MockAffectedFile('base/BUILD.gn', 'another.h\nstuff.h'), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -1953,7 +1954,7 @@ MockAffectedFile('base/another.h', ''), MockAffectedFile('base/BUILD.gn', 'another_h\nstuff.h'), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertFalse('base/stuff.h' in warnings[0].items) @@ -1966,7 +1967,7 @@ MockAffectedFile('base/another.h', ''), MockAffectedFile('base/BUILD.gn', 'another_h\nstuff_h'), ] - warnings = PRESUBMIT._CheckNewHeaderWithoutGnChange( + warnings = PRESUBMIT.CheckNewHeaderWithoutGnChangeOnUpload( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertTrue('base/stuff.h' in warnings[0].items) @@ -1988,7 +1989,7 @@ '</message>', ]), ] - warnings = PRESUBMIT._CheckCorrectProductNameInMessages( + warnings = PRESUBMIT.CheckCorrectProductNameInMessages( mock_input_api, MockOutputApi()) self.assertEqual(0, len(warnings)) @@ -2006,7 +2007,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]) @@ -2025,7 +2026,7 @@ '</message>', ]), ] - warnings = PRESUBMIT._CheckCorrectProductNameInMessages( + warnings = PRESUBMIT.CheckCorrectProductNameInMessages( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertTrue( @@ -2046,7 +2047,7 @@ '</message>', ]), ] - warnings = PRESUBMIT._CheckCorrectProductNameInMessages( + warnings = PRESUBMIT.CheckCorrectProductNameInMessages( mock_input_api, MockOutputApi()) self.assertEqual(1, len(warnings)) self.assertTrue( @@ -2080,7 +2081,7 @@ '</message>', ]), ] - warnings = PRESUBMIT._CheckCorrectProductNameInMessages( + warnings = PRESUBMIT.CheckCorrectProductNameInMessages( mock_input_api, MockOutputApi()) self.assertEqual(2, len(warnings)) self.assertTrue( @@ -2102,7 +2103,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( @@ -2117,7 +2118,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) @@ -2131,7 +2132,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( @@ -2146,7 +2147,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( @@ -2161,7 +2162,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( @@ -2176,7 +2177,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) @@ -2252,7 +2253,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, @@ -2271,7 +2272,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, @@ -2290,7 +2291,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): @@ -2302,7 +2303,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)) @@ -2321,7 +2322,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)) @@ -2353,7 +2354,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) @@ -2380,7 +2381,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) @@ -2405,7 +2406,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)) @@ -2510,7 +2511,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)) @@ -2542,7 +2543,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)) @@ -2560,7 +2561,7 @@ MockFile('some/path/foo.cpp', ['// foo_for_test();']), ] - results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctions( + results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctions( mock_input_api, MockOutputApi()) self.assertEqual(0, len(results)) @@ -2578,7 +2579,7 @@ ]) ] - results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava( + results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava( mock_input_api, MockOutputApi()) self.assertEqual(1, len(results)) self.assertEqual(4, len(results[0].items)) @@ -2607,7 +2608,7 @@ ]), ] - results = PRESUBMIT._CheckNoProductionCodeUsingTestOnlyFunctionsJava( + results = PRESUBMIT.CheckNoProductionCodeUsingTestOnlyFunctionsJava( mock_input_api, MockOutputApi()) self.assertEqual(0, len(results)) @@ -2652,7 +2653,7 @@ MockFile('dir/baz-p.cc', ['std::unique_ptr<T<P>>()']), ] - results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi()) + results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(1, len(results)) self.assertTrue('nullptr' in results[0].message) self.assertEqual(2, len(results[0].items)) @@ -2680,7 +2681,7 @@ 'auto p = std::unique_ptr<std::pair<T, D>>(new std::pair(T, D));']), ] - results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi()) + results = PRESUBMIT.CheckUniquePtrOnUpload(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)) @@ -2712,7 +2713,7 @@ 'auto p = std::unique_ptr<T, D>(new T(), D());']), ] - results = PRESUBMIT._CheckUniquePtr(mock_input_api, MockOutputApi()) + results = PRESUBMIT.CheckUniquePtrOnUpload(mock_input_api, MockOutputApi()) self.assertEqual(0, len(results)) class CheckNoDirectIncludesHeadersWhichRedefineStrCat(unittest.TestCase): @@ -2936,7 +2937,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)) @@ -2946,7 +2947,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) @@ -2962,7 +2963,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) @@ -2990,7 +2991,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) @@ -3027,7 +3028,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) @@ -3074,7 +3075,7 @@ 'binary', action='A'), ]) - warnings = PRESUBMIT._CheckStrings(input_api, + warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi()) self.assertEqual([], warnings) @@ -3102,7 +3103,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) @@ -3143,7 +3144,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) @@ -3183,7 +3184,7 @@ 'binary', action='D') ]) - warnings = PRESUBMIT._CheckStrings(input_api, + warnings = PRESUBMIT.CheckStrings(input_api, MockOutputApi()) self.assertEqual([], warnings) @@ -3194,7 +3195,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] @@ -3206,7 +3207,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] @@ -3218,7 +3219,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] @@ -3235,7 +3236,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] @@ -3274,7 +3275,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)) @@ -3292,7 +3293,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)) @@ -3309,7 +3310,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)) @@ -3333,7 +3334,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)) @@ -3360,7 +3361,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)) @@ -3408,7 +3409,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, @@ -3426,7 +3427,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)) @@ -3436,7 +3437,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)) @@ -3454,7 +3455,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): @@ -3491,7 +3492,7 @@ mock_input_api.files = [] for fname, contents in files.items(): mock_input_api.files.append(MockFile(fname, contents.splitlines())) - return PRESUBMIT._CheckFuzzTargets(mock_input_api, MockOutputApi()) + return PRESUBMIT.CheckFuzzTargetsOnUpload(mock_input_api, MockOutputApi()) def testLibFuzzerSourcesIgnored(self): results = self._check({ @@ -3535,7 +3536,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) @@ -3553,7 +3554,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) @@ -3562,7 +3563,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 79d9bf7..996e4d4 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1309,6 +1309,10 @@ "wm/desks/close_desk_button.h", "wm/desks/desk.cc", "wm/desks/desk.h", + "wm/desks/desk_animation_base.cc", + "wm/desks/desk_animation_base.h", + "wm/desks/desk_animation_impl.cc", + "wm/desks/desk_animation_impl.h", "wm/desks/desk_mini_view.cc", "wm/desks/desk_mini_view.h", "wm/desks/desk_mini_view_animations.cc",
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd index c0c7f945..0422608 100644 --- a/ash/ash_strings.grd +++ b/ash/ash_strings.grd
@@ -1961,6 +1961,9 @@ <message name="IDS_ASH_LOGIN_POD_PASSWORD_PIN_PLACEHOLDER" desc="Text to display as placeholder in the password field when both password and pin are allowed."> PIN or password </message> + <message name="IDS_ASH_LOGIN_POD_PASSWORD_PIN_INPUT_ACCESSIBLE_NAME" desc="The accessible name of the pin input field used for PIN Auto-submit"> + Enter your PIN + </message> <message name="IDS_ASH_LOGIN_SWITCH_TO_PASSWORD" desc="Text to display on the button that is used for switching between PIN and password authentication"> Switch to password </message>
diff --git a/ash/ash_strings_grd/IDS_ASH_LOGIN_POD_PASSWORD_PIN_INPUT_ACCESSIBLE_NAME.png.sha1 b/ash/ash_strings_grd/IDS_ASH_LOGIN_POD_PASSWORD_PIN_INPUT_ACCESSIBLE_NAME.png.sha1 new file mode 100644 index 0000000..d5e5b42d --- /dev/null +++ b/ash/ash_strings_grd/IDS_ASH_LOGIN_POD_PASSWORD_PIN_INPUT_ACCESSIBLE_NAME.png.sha1
@@ -0,0 +1 @@ +3f38905d613f3ce7c8e07d79d91bf6a7d89336f1 \ No newline at end of file
diff --git a/ash/clipboard/clipboard_history.cc b/ash/clipboard/clipboard_history.cc index 053cbab..f4a50cf 100644 --- a/ash/clipboard/clipboard_history.cc +++ b/ash/clipboard/clipboard_history.cc
@@ -5,10 +5,8 @@ #include "ash/clipboard/clipboard_history.h" #include "ash/clipboard/clipboard_history_controller.h" -#include "ash/session/session_controller_impl.h" -#include "ash/shell.h" #include "base/stl_util.h" -#include "components/account_id/account_id.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "ui/base/clipboard/clipboard_monitor.h" #include "ui/base/clipboard/clipboard_non_backed.h" @@ -18,10 +16,6 @@ constexpr size_t kMaxClipboardItemsShared = 5; -AccountId GetActiveAccountId() { - return Shell::Get()->session_controller()->GetActiveAccountId(); -} - } // namespace ClipboardHistory::ScopedPause::ScopedPause(ClipboardHistory* clipboard_history) @@ -35,8 +29,6 @@ ClipboardHistory::ClipboardHistory() { ui::ClipboardMonitor::GetInstance()->AddObserver(this); - Shell::Get()->session_controller()->AddObserver(this); - Shell::Get()->AddShellObserver(this); } ClipboardHistory::~ClipboardHistory() { @@ -44,13 +36,11 @@ } const std::list<ui::ClipboardData>& ClipboardHistory::GetItems() const { - auto it = items_by_account_id_.find(GetActiveAccountId()); - DCHECK(it != items_by_account_id_.cend()); - return it->second; + return history_list_; } void ClipboardHistory::Clear() { - items_by_account_id_[GetActiveAccountId()] = std::list<ui::ClipboardData>(); + history_list_ = std::list<ui::ClipboardData>(); } bool ClipboardHistory::IsEmpty() const { @@ -79,17 +69,15 @@ // immediately by the long form URL. commit_data_weak_factory_.InvalidateWeakPtrs(); base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&ClipboardHistory::CommitData, - commit_data_weak_factory_.GetWeakPtr(), - GetActiveAccountId(), *clipboard_data)); + FROM_HERE, + base::BindOnce(&ClipboardHistory::CommitData, + commit_data_weak_factory_.GetWeakPtr(), *clipboard_data)); } -void ClipboardHistory::CommitData(const AccountId& account_id, - ui::ClipboardData data) { - std::list<ui::ClipboardData>& items = items_by_account_id_[account_id]; - items.push_front(std::move(data)); - if (items.size() > kMaxClipboardItemsShared) - items.pop_back(); +void ClipboardHistory::CommitData(ui::ClipboardData data) { + history_list_.push_front(std::move(data)); + if (history_list_.size() > kMaxClipboardItemsShared) + history_list_.pop_back(); } void ClipboardHistory::Pause() { @@ -100,17 +88,4 @@ --num_pause_; } -void ClipboardHistory::OnActiveUserSessionChanged( - const AccountId& active_account_id) { - if (!base::Contains(items_by_account_id_, active_account_id)) - items_by_account_id_[active_account_id] = std::list<ui::ClipboardData>(); -} - -void ClipboardHistory::OnShellDestroying() { - // ClipboardHistory depends on Shell to access the classes it observes. So - // remove itself from observer lists before the Shell instance is destroyed. - Shell::Get()->session_controller()->RemoveObserver(this); - Shell::Get()->RemoveShellObserver(this); -} - } // namespace ash
diff --git a/ash/clipboard/clipboard_history.h b/ash/clipboard/clipboard_history.h index 6d6b314..bc4d2a19 100644 --- a/ash/clipboard/clipboard_history.h +++ b/ash/clipboard/clipboard_history.h
@@ -9,27 +9,19 @@ #include <map> #include "ash/ash_export.h" -#include "ash/public/cpp/session/session_observer.h" -#include "ash/shell_observer.h" #include "base/component_export.h" #include "base/memory/weak_ptr.h" #include "ui/base/clipboard/clipboard_data.h" #include "ui/base/clipboard/clipboard_observer.h" -class AccountId; - namespace ui { class ClipboardData; } // namespace ui namespace ash { -// Keeps track of the last few things saved in the clipboard. For multiprofile, -// one account's clipboard history is separated from others and indexed by the -// account id. -class ASH_EXPORT ClipboardHistory : public ui::ClipboardObserver, - public SessionObserver, - public ShellObserver { +// Keeps track of the last few things saved in the clipboard. +class ASH_EXPORT ClipboardHistory : public ui::ClipboardObserver { public: // Prevents clipboard history from being recorded within its scope. If // anything is copied within its scope, history will not be recorded. @@ -49,12 +41,11 @@ ClipboardHistory& operator=(const ClipboardHistory&) = delete; ~ClipboardHistory() override; - // Returns the list of most recent items copied by the active account. The - // returned list is sorted by recency. + // Returns the list of most recent items. The returned list is sorted by + // recency. const std::list<ui::ClipboardData>& GetItems() const; - // Deletes clipboard history of the active account. Does not modify content - // stored in the clipboard. + // Deletes clipboard history. Does not modify content stored in the clipboard. void Clear(); // Returns whether the clipboard history of the active account is empty. @@ -64,23 +55,18 @@ void OnClipboardDataChanged() override; private: - // Adds |data| to the clipboard history associated with |account_id|. - void CommitData(const AccountId& account_id, ui::ClipboardData data); + // Adds |data| to the |history_list_|. + void CommitData(ui::ClipboardData data); + void Pause(); void Resume(); - // SessionObserver: - void OnActiveUserSessionChanged(const AccountId& account_id) override; - - // ShellObserver: - void OnShellDestroying() override; - // The count of pauses. size_t num_pause_ = 0; - // Clipboard history is mapped by account ID to store different items per - // account when multiprofile is used. Lists of items are sorted by recency. - std::map<AccountId, std::list<ui::ClipboardData>> items_by_account_id_; + // The history of data copied to the Clipboard. Items of the list are sorted + // by recency. + std::list<ui::ClipboardData> history_list_; // Factory to create WeakPtrs used to debounce calls to CommitData(). base::WeakPtrFactory<ClipboardHistory> commit_data_weak_factory_{this};
diff --git a/ash/login/ui/lock_contents_view.cc b/ash/login/ui/lock_contents_view.cc index 8a2bdc0..f48b2c2 100644 --- a/ash/login/ui/lock_contents_view.cc +++ b/ash/login/ui/lock_contents_view.cc
@@ -1097,7 +1097,7 @@ tooltip_bubble_->Hide(); if (icon.autoshow_tooltip) { - tooltip_bubble_->SetAnchorView(big_user->auth_user()->password_view()); + tooltip_bubble_->SetAnchorView(big_user->auth_user()->GetAnchorView()); tooltip_bubble_->SetText(icon.tooltip); tooltip_bubble_->Show(); tooltip_bubble_->SetVisible(true); @@ -1121,7 +1121,7 @@ warning_banner_bubble_->Hide(); // Shows warning banner as a persistent error bubble. warning_banner_bubble_->SetAnchorView( - CurrentBigUserView()->auth_user()->password_view()); + CurrentBigUserView()->auth_user()->GetAnchorView()); warning_banner_bubble_->SetTextContent(message); warning_banner_bubble_->Show(); } @@ -1283,7 +1283,7 @@ detachable_base_error_bubble_->SetTextContent(error_text); detachable_base_error_bubble_->SetAnchorView( - CurrentBigUserView()->auth_user()->password_view()); + CurrentBigUserView()->auth_user()->GetAnchorView()); detachable_base_error_bubble_->Show(); // Remove the focus from the password field, to make user less likely to enter @@ -1887,7 +1887,7 @@ supervised_user_deprecation_bubble_->SetTextContent(message); supervised_user_deprecation_bubble_->SetAnchorView( - CurrentBigUserView()->auth_user()->password_view()); + CurrentBigUserView()->auth_user()->GetAnchorView()); supervised_user_deprecation_bubble_->Show(); } else if (supervised_user_deprecation_bubble_->GetVisible()) { supervised_user_deprecation_bubble_->Hide(); @@ -1997,7 +1997,7 @@ container->AddChildView(std::move(label)); container->AddChildView(std::move(learn_more_button)); - auth_error_bubble_->SetAnchorView(big_view->auth_user()->password_view()); + auth_error_bubble_->SetAnchorView(big_view->auth_user()->GetAnchorView()); auth_error_bubble_->SetContent(container.release()); auth_error_bubble_->SetAccessibleName(error_text); auth_error_bubble_->SetPersistent(false); @@ -2015,7 +2015,7 @@ DCHECK(state->easy_unlock_state); if (!state->easy_unlock_state->tooltip.empty()) { - tooltip_bubble_->SetAnchorView(big_view->auth_user()->password_view()); + tooltip_bubble_->SetAnchorView(big_view->auth_user()->GetAnchorView()); tooltip_bubble_->SetText(state->easy_unlock_state->tooltip); tooltip_bubble_->Show(); }
diff --git a/ash/login/ui/lock_debug_view.cc b/ash/login/ui/lock_debug_view.cc index 9d1ea5a5..142c3d58 100644 --- a/ash/login/ui/lock_debug_view.cc +++ b/ash/login/ui/lock_debug_view.cc
@@ -62,6 +62,7 @@ kGlobalToggleManagedSessionDisclosure, kGlobalShowParentAccess, kPerUserTogglePin, + kPerUserToggleChallengeResponse, kPerUserToggleTap, kPerUserCycleEasyUnlockState, kPerUserCycleFingerprintState, @@ -112,6 +113,7 @@ std::string display_name; bool enable_pin = false; bool enable_tap_to_unlock = false; + bool enable_challenge_response = false; // Smart Card bool enable_auth = true; user_manager::UserType type = user_manager::USER_TYPE_REGULAR; EasyUnlockIconId easy_unlock_id = EasyUnlockIconId::NONE; @@ -271,6 +273,17 @@ debug_user->enable_pin); } + // Activates or deactivates challenge response for the user at + // |user_index|. + void ToggleChallengeResponseStateForUserIndex(size_t user_index) { + DCHECK(user_index < debug_users_.size()); + UserMetadata* debug_user = &debug_users_[user_index]; + debug_user->enable_challenge_response = + !debug_user->enable_challenge_response; + debug_dispatcher_.SetChallengeResponseAuthEnabledForUser( + debug_user->account_id, debug_user->enable_challenge_response); + } + // Activates or deactivates tap unlock for the user at |user_index|. void ToggleTapStateForUserIndex(size_t user_index) { DCHECK(user_index >= 0 && user_index < debug_users_.size()); @@ -1015,6 +1028,12 @@ if (sender->GetID() == ButtonId::kPerUserTogglePin) debug_data_dispatcher_->TogglePinStateForUserIndex(sender->tag()); + // Enable or disable challenge response. (Smart Card) + if (sender->GetID() == ButtonId::kPerUserToggleChallengeResponse) { + debug_data_dispatcher_->ToggleChallengeResponseStateForUserIndex( + sender->tag()); + } + // Enable or disable tap. if (sender->GetID() == ButtonId::kPerUserToggleTap) debug_data_dispatcher_->ToggleTapStateForUserIndex(sender->tag()); @@ -1094,6 +1113,9 @@ row->AddChildView(name); AddButton("Toggle PIN", ButtonId::kPerUserTogglePin, row)->set_tag(i); + AddButton("Toggle Smart card", + ButtonId::kPerUserToggleChallengeResponse, row) + ->set_tag(i); AddButton("Toggle Tap", ButtonId::kPerUserToggleTap, row)->set_tag(i); AddButton("Cycle easy unlock", ButtonId::kPerUserCycleEasyUnlockState, row) ->set_tag(i);
diff --git a/ash/login/ui/login_auth_user_view.cc b/ash/login/ui/login_auth_user_view.cc index 742c4d2..692d41f 100644 --- a/ash/login/ui/login_auth_user_view.cc +++ b/ash/login/ui/login_auth_user_view.cc
@@ -46,6 +46,7 @@ #include "ui/compositor/layer_animator.h" #include "ui/compositor/scoped_layer_animation_settings.h" #include "ui/gfx/color_analysis.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/interpolated_transform.h" #include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/vector_icon_types.h" @@ -72,6 +73,9 @@ // Distance between the password textfield and the the pin keyboard. const int kDistanceBetweenPasswordFieldAndPinKeyboardDp = 16; +// The height of the password field. +const int kPasswordFieldHeight = 37; + // Distance from the end of pin keyboard to the bottom of the big user view. const int kDistanceFromPinKeyboardToBigUserViewBottomDp = 50; @@ -748,6 +752,8 @@ had_pinpad = view->ShouldShowPinPad(); had_password = view->ShouldShowPasswordField(); had_fingerprint = view->HasAuthMethod(LoginAuthUserView::AUTH_FINGERPRINT); + had_challenge_response = + view->HasAuthMethod(LoginAuthUserView::AUTH_CHALLENGE_RESPONSE); } int non_pin_y_start_in_screen = 0; @@ -755,6 +761,7 @@ bool had_pinpad = false; bool had_password = false; bool had_fingerprint = false; + bool had_challenge_response = false; }; LoginAuthUserView::TestApi::TestApi(LoginAuthUserView* view) : view_(view) {} @@ -838,10 +845,10 @@ auto pin_view = std::make_unique<LoginPinView>( LoginPinView::Style::kAlphanumeric, palette, - base::BindRepeating(&LoginPasswordView::InsertNumber, - base::Unretained(password_view.get())), - base::BindRepeating(&LoginPasswordView::Backspace, - base::Unretained(password_view.get()))); + base::BindRepeating(&LoginAuthUserView::OnPinPadInsertDigit, + base::Unretained(this)), + base::BindRepeating(&LoginAuthUserView::OnPinPadBackspace, + base::Unretained(this))); pin_view_ = pin_view.get(); DCHECK(pin_view_->layer()); @@ -850,6 +857,11 @@ kNonEmptyWidthDp, kDistanceBetweenPasswordFieldAndPinKeyboardDp)); padding_below_password_view_ = padding_below_password_view.get(); + auto padding_below_user_view = std::make_unique<NonAccessibleView>(); + padding_below_user_view->SetPreferredSize( + gfx::Size(kNonEmptyWidthDp, kDistanceBetweenUserViewAndPasswordDp)); + padding_below_user_view_ = padding_below_user_view.get(); + // Initialization of |password_view| is deferred because it needs the // |pin_view| pointer. password_view->Init(base::BindRepeating(&LoginAuthUserView::OnAuthSubmit, @@ -883,22 +895,9 @@ SetPaintToLayer(ui::LayerType::LAYER_NOT_DRAWN); - // Wrap the password view with a container having the fill layout, so that - // it's possible to hide the password view while continuing to consume the - // same amount of space, which prevents the user view from shrinking. In the - // cases when other controls need to be rendered in this space, the whole - // container gets hidden. - auto password_view_container = std::make_unique<NonAccessibleView>(); - password_view_container->SetLayoutManager( - std::make_unique<views::FillLayout>()); - password_view_container->AddChildView(std::move(password_view)); - password_view_container_ = password_view_container.get(); - // Build layout. - auto wrapped_password_view = std::make_unique<NonAccessibleView>(); - wrapped_password_view->SetLayoutManager( - std::make_unique<views::FlexLayout>()); - wrapped_password_view->AddChildView(std::move(password_view_container)); + auto wrapped_password_view = + login_views_utils::WrapViewForPreferredSize(std::move(password_view)); auto wrapped_online_sign_in_message_view = login_views_utils::WrapViewForPreferredSize( std::move(online_sign_in_message)); @@ -917,6 +916,9 @@ auto wrapped_padding_below_password_view = login_views_utils::WrapViewForPreferredSize( std::move(padding_below_password_view)); + auto wrapped_padding_below_user_view = + login_views_utils::WrapViewForPreferredSize( + std::move(padding_below_user_view)); // Add views in tabbing order; they are rendered in a different order below. views::View* wrapped_password_view_ptr = @@ -934,6 +936,8 @@ AddChildView(std::move(wrapped_user_view)); views::View* wrapped_padding_below_password_view_ptr = AddChildView(std::move(wrapped_padding_below_password_view)); + views::View* wrapped_padding_below_user_view_ptr = + AddChildView(std::move(wrapped_padding_below_user_view)); // Use views::GridLayout instead of views::BoxLayout because views::BoxLayout // lays out children according to the view->children order. @@ -955,7 +959,7 @@ // Add views in rendering order. add_padding(kDistanceFromTopOfBigUserViewToUserIconDp); add_view(wrapped_user_view_ptr); - add_padding(kDistanceBetweenUserViewAndPasswordDp); + add_view(wrapped_padding_below_user_view_ptr); add_view(wrapped_password_view_ptr); add_view(wrapped_online_sign_in_message_view_ptr); add_view(wrapped_disabled_auth_message_view_ptr); @@ -974,7 +978,7 @@ void LoginAuthUserView::SetAuthMethods(uint32_t auth_methods, AuthMethodsMetadata auth_metadata) { - bool had_password = HasAuthMethod(AUTH_PASSWORD); + bool had_password = ShouldShowPasswordField(); // Apply changes and determine the new state of input fields. auth_methods_ = static_cast<AuthMethods>(auth_methods); @@ -1005,7 +1009,6 @@ password_view_->SetFocusEnabledForChildViews(has_password); password_view_->SetVisible(!hide_auth && has_password); password_view_->layer()->SetOpacity(has_password ? 1 : 0); - password_view_container_->SetVisible(has_password || !has_challenge_response); if (!had_password && has_password) password_view_->RequestFocus(); @@ -1014,15 +1017,8 @@ fingerprint_view_->SetCanUsePin(HasAuthMethod(AUTH_PIN)); challenge_response_view_->SetVisible(has_challenge_response); - int padding_view_height = kDistanceBetweenPasswordFieldAndPinKeyboardDp; - if (has_fingerprint && !has_pinpad) { - padding_view_height = kDistanceBetweenPasswordFieldAndFingerprintViewDp; - } else if (has_challenge_response && !has_pinpad) { - padding_view_height = - kDistanceBetweenPasswordFieldAndChallengeResponseViewDp; - } - padding_below_password_view_->SetPreferredSize( - gfx::Size(kNonEmptyWidthDp, padding_view_height)); + padding_below_user_view_->SetPreferredSize(GetPaddingBelowUserView()); + padding_below_password_view_->SetPreferredSize(GetPaddingBelowPasswordView()); password_view_->SetPlaceholderText(GetPasswordViewPlaceholder()); const std::string& user_display_email = @@ -1034,7 +1030,7 @@ // Only the active auth user view has a password displayed. If that is the // case, then render the user view as if it was always focused, since clicking // on it will not do anything (such as swapping users). - user_view_->SetForceOpaque(HasAuthMethod(AUTH_PASSWORD) || hide_auth); + user_view_->SetForceOpaque(auth_methods_ != AUTH_NONE); user_view_->SetTapEnabled(!HasAuthMethod(AUTH_PASSWORD)); // Tapping the user view will trigger the online sign-in flow when // |force_online_sign_in| is true. @@ -1076,6 +1072,7 @@ stop_animation(password_view_); stop_animation(pin_view_); stop_animation(fingerprint_view_); + stop_animation(challenge_response_view_); DCHECK(!cached_animation_state_); cached_animation_state_ = std::make_unique<AnimationState>(this); @@ -1088,6 +1085,7 @@ bool had_password = cached_animation_state_->had_password; bool has_pinpad = ShouldShowPinPad(); bool has_fingerprint = HasAuthMethod(AUTH_FINGERPRINT); + bool has_challenge_response = HasAuthMethod(AUTH_CHALLENGE_RESPONSE); //////// // Animate the user info (ie, icon, name) up or down the screen. @@ -1124,9 +1122,6 @@ if (!has_password) std::swap(opacity_start, opacity_end); - if (had_password) - password_view_->SetVisible(true); - password_view_->layer()->SetOpacity(opacity_start); { @@ -1202,6 +1197,26 @@ } } + //////// + // Fade the challenge response (Smart Card) if it is being hidden or shown. + if (cached_animation_state_->had_challenge_response != + has_challenge_response) { + float opacity_start = 0, opacity_end = 1; + if (!has_challenge_response) + std::swap(opacity_start, opacity_end); + + challenge_response_view_->layer()->SetOpacity(opacity_start); + + { + ui::ScopedLayerAnimationSettings settings( + challenge_response_view_->layer()->GetAnimator()); + settings.SetTransitionDuration(base::TimeDelta::FromMilliseconds( + login_constants::kChangeUserAnimationDurationMs)); + settings.SetTweenType(gfx::Tween::Type::FAST_OUT_SLOW_IN); + challenge_response_view_->layer()->SetOpacity(opacity_end); + } + } + cached_animation_state_.reset(); } @@ -1237,6 +1252,10 @@ return user_view_->current_user(); } +views::View* LoginAuthUserView::GetAnchorView() { + return password_view_; +} + gfx::Size LoginAuthUserView::CalculatePreferredSize() const { gfx::Size size = views::View::CalculatePreferredSize(); // Make sure we are at least as big as the user view. If we do not do this the @@ -1326,6 +1345,16 @@ current_user().basic_user_info.account_id); } +void LoginAuthUserView::OnPinPadBackspace() { + DCHECK(password_view_); + password_view_->Backspace(); +} + +void LoginAuthUserView::OnPinPadInsertDigit(int digit) { + DCHECK(password_view_); + password_view_->InsertNumber(digit); +} + bool LoginAuthUserView::HasAuthMethod(AuthMethods auth_method) const { return (auth_methods_ & auth_method) != 0; } @@ -1342,7 +1371,9 @@ } void LoginAuthUserView::UpdateInputFieldMode() { - if (!HasAuthMethod(AUTH_PASSWORD)) { + // Currently the challenge-response authentication can't be combined + // with the password or PIN based one. + if (!HasAuthMethod(AUTH_PASSWORD) || HasAuthMethod(AUTH_CHALLENGE_RESPONSE)) { input_field_mode_ = InputFieldMode::DISABLED; return; } @@ -1373,6 +1404,28 @@ input_field_mode_ == InputFieldMode::PIN_AND_PASSWORD; } +gfx::Size LoginAuthUserView::GetPaddingBelowUserView() const { + int height = kDistanceBetweenUserViewAndPasswordDp; + + // Compensate with the height of the password field if there isn't + // an input field or smart card login (challenge response). + if (!ShouldShowPasswordField() && !HasAuthMethod(AUTH_CHALLENGE_RESPONSE)) + height += kPasswordFieldHeight; + + return gfx::Size(kNonEmptyWidthDp, height); +} + +gfx::Size LoginAuthUserView::GetPaddingBelowPasswordView() const { + int padding_view_height = kDistanceBetweenPasswordFieldAndPinKeyboardDp; + if (HasAuthMethod(AUTH_FINGERPRINT) && !ShouldShowPinPad()) { + padding_view_height = kDistanceBetweenPasswordFieldAndFingerprintViewDp; + } else if (HasAuthMethod(AUTH_CHALLENGE_RESPONSE) && !ShouldShowPinPad()) { + padding_view_height = + kDistanceBetweenPasswordFieldAndChallengeResponseViewDp; + } + return gfx::Size(kNonEmptyWidthDp, padding_view_height); +} + base::string16 LoginAuthUserView::GetPasswordViewPlaceholder() const { // Note: |AUTH_TAP| must have higher priority than |AUTH_PIN| when // determining the placeholder.
diff --git a/ash/login/ui/login_auth_user_view.h b/ash/login/ui/login_auth_user_view.h index e38ff89..e6006dfc 100644 --- a/ash/login/ui/login_auth_user_view.h +++ b/ash/login/ui/login_auth_user_view.h
@@ -158,6 +158,9 @@ const LoginUserInfo& current_user() const; + // Provides the view that should be the anchor to message bubbles. Either the + // password field, or the PIN field. + views::View* GetAnchorView(); LoginPasswordView* password_view() { return password_view_; } LoginUserView* user_view() { return user_view_; } @@ -191,8 +194,9 @@ // Called when the online sign-in message is tapped. It opens the Gaia screen. void OnOnlineSignInMessageTap(); - // Called when the user presses the back button of the PIN keyboard. - void OnPinBack(); + // Called from LoginPinView, forwards the calls to the active input field. + void OnPinPadBackspace(); + void OnPinPadInsertDigit(int digit); // Helper method to check if an auth method is enable. Use it like this: // bool has_tap = HasAuthMethod(AUTH_TAP). @@ -214,6 +218,10 @@ bool ShouldShowPinPad() const; bool ShouldShowPasswordField() const; + // Convenience methods to determine the necessary paddings. + gfx::Size GetPaddingBelowUserView() const; + gfx::Size GetPaddingBelowPasswordView() const; + // Convenience methods to determine UI text based on the InputFieldMode. base::string16 GetPasswordViewPlaceholder() const; @@ -233,6 +241,9 @@ FingerprintView* fingerprint_view_ = nullptr; ChallengeResponseView* challenge_response_view_ = nullptr; + // Padding below the user view. Grows when there isn't an input field + // or smart card login. + NonAccessibleView* padding_below_user_view_ = nullptr; // Displays padding between: // 1. Password field and pin keyboard // 2. Password field and fingerprint view, when pin is not available.
diff --git a/ash/wm/desks/desk_animation_base.cc b/ash/wm/desks/desk_animation_base.cc new file mode 100644 index 0000000..34a248d --- /dev/null +++ b/ash/wm/desks/desk_animation_base.cc
@@ -0,0 +1,132 @@ +// 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/wm/desks/desk_animation_base.h" + +#include "ash/shell.h" +#include "ash/wm/desks/desk.h" +#include "ash/wm/desks/desks_controller.h" +#include "ash/wm/window_util.h" +#include "ui/aura/window_tree_host.h" +#include "ui/compositor/compositor.h" + +namespace ash { + +namespace { + +// Selects and returns the compositor to measure the animation smoothness. +ui::Compositor* GetSelectedCompositorForAnimationSmoothness() { + // Favor the compositor associated with the active window's root window (if + // any), or that of the primary root window. + auto* active_window = window_util::GetActiveWindow(); + auto* selected_root = active_window && active_window->GetRootWindow() + ? active_window->GetRootWindow() + : Shell::GetPrimaryRootWindow(); + DCHECK(selected_root); + return selected_root->layer()->GetCompositor(); +} + +} // namespace + +// ----------------------------------------------------------------------------- +// DeskAnimationBase: + +DeskAnimationBase::DeskAnimationBase(DesksController* controller, + const Desk* ending_desk) + : controller_(controller), + ending_desk_(ending_desk), + throughput_tracker_(GetSelectedCompositorForAnimationSmoothness() + ->RequestNewThroughputTracker()) { + DCHECK(controller_); + DCHECK(ending_desk_); +} + +DeskAnimationBase::~DeskAnimationBase() = default; + +void DeskAnimationBase::Launch() { + for (auto& observer : controller_->observers_) + observer.OnDeskSwitchAnimationLaunching(); + + throughput_tracker_.Start(GetReportCallback()); + + // This step makes sure that the containers of the target desk are shown at + // the beginning of the animation (but not actually visible to the user yet, + // until the desk is actually activated at a later step of the animation). + // This is needed because a window on the target desk can be focused before + // the desk becomes active (See `DesksController::OnWindowActivating()`). + // This window must be able to accept events (See + // `aura::Window::CanAcceptEvent()`) even though its desk is still being + // activated. https://crbug.com/1008574. + const_cast<Desk*>(ending_desk_)->PrepareForActivationAnimation(); + + DCHECK(!desk_switch_animators_.empty()); + for (auto& animator : desk_switch_animators_) + animator->TakeStartingDeskScreenshot(); +} + +void DeskAnimationBase::OnStartingDeskScreenshotTaken(const Desk* ending_desk) { + DCHECK(!desk_switch_animators_.empty()); + + // Once all starting desk screenshots on all roots are taken and placed on + // the screens, do the actual desk activation logic. + for (const auto& animator : desk_switch_animators_) { + if (!animator->starting_desk_screenshot_taken()) + return; + } + + // Extend the compositors' timeouts in order to prevents any repaints until + // the desks are switched and overview mode exits. + const auto roots = Shell::GetAllRootWindows(); + for (auto* root : roots) + root->GetHost()->compositor()->SetAllowLocksToExtendTimeout(true); + + OnStartingDeskScreenshotTakenInternal(ending_desk); + + for (auto* root : roots) + root->GetHost()->compositor()->SetAllowLocksToExtendTimeout(false); + + // Continue the second phase of the animation by taking the ending desk + // screenshot and actually animating the layers. + for (auto& animator : desk_switch_animators_) + animator->TakeEndingDeskScreenshot(); +} + +void DeskAnimationBase::OnEndingDeskScreenshotTaken() { + DCHECK(!desk_switch_animators_.empty()); + + // Once all ending desk screenshots on all roots are taken, start the + // animation on all roots at the same time, so that they look synchrnoized. + for (const auto& animator : desk_switch_animators_) { + if (!animator->ending_desk_screenshot_taken()) + return; + } + + for (auto& animator : desk_switch_animators_) + animator->StartAnimation(); +} + +void DeskAnimationBase::OnDeskSwitchAnimationFinished() { + DCHECK(!desk_switch_animators_.empty()); + + // Once all desk switch animations on all roots finish, destroy all the + // animators. + for (const auto& animator : desk_switch_animators_) { + if (!animator->animation_finished()) + return; + } + + OnDeskSwitchAnimationFinishedInternal(); + + desk_switch_animators_.clear(); + + throughput_tracker_.Stop(); + + for (auto& observer : controller_->observers_) + observer.OnDeskSwitchAnimationFinished(); + + controller_->OnAnimationFinished(this); + // `this` is now deleted. +} + +} // namespace ash
diff --git a/ash/wm/desks/desk_animation_base.h b/ash/wm/desks/desk_animation_base.h new file mode 100644 index 0000000..e36fdb2 --- /dev/null +++ b/ash/wm/desks/desk_animation_base.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 ASH_WM_DESKS_DESK_ANIMATION_BASE_H_ +#define ASH_WM_DESKS_DESK_ANIMATION_BASE_H_ + +#include "ash/public/cpp/metrics_util.h" +#include "ash/wm/desks/root_window_desk_switch_animator.h" +#include "ui/compositor/throughput_tracker.h" + +namespace ash { + +class Desk; +class DesksController; + +// An abstract class that handles the shared operations need to be performed +// when doing an animation that causes a desk switch animation. Subclasses +// such as DeskActivationAnimation and DeskRemovalAnimation implement the +// abstract interface of this class to handle the unique operations specific to +// each animation type. +class DeskAnimationBase : public RootWindowDeskSwitchAnimator::Delegate { + public: + DeskAnimationBase(DesksController* controller, const Desk* ending_desk); + DeskAnimationBase(const DeskAnimationBase&) = delete; + DeskAnimationBase& operator=(const DeskAnimationBase&) = delete; + ~DeskAnimationBase() override; + + const Desk* ending_desk() const { return ending_desk_; } + + // Launches the animation. This should be done once all animators + // are created and added to `desk_switch_animators_`. This is to avoid any + // potential race conditions that might happen if one animator finished phase + // (1) of the animation while other animators are still being constructed. + void Launch(); + + // RootWindowDeskSwitchAnimator::Delegate: + void OnStartingDeskScreenshotTaken(const Desk* ending_desk) override; + void OnEndingDeskScreenshotTaken() override; + void OnDeskSwitchAnimationFinished() override; + + protected: + // Abstract functions that can be overridden by child classes to do different + // things when phase (1), and phase (3) completes. Note that + // `OnDeskSwitchAnimationFinishedInternal()` will be called before the desks + // screenshot layers, stored in `desk_switch_animators_`, are destroyed. + virtual void OnStartingDeskScreenshotTakenInternal( + const Desk* ending_desk) = 0; + virtual void OnDeskSwitchAnimationFinishedInternal() = 0; + + // Since performance here matters, we have to use the UMA histograms macros to + // report the smoothness histograms, but each macro use has to be associated + // with exactly one histogram name. This function allows subclasses to return + // a callback that reports the histogram using the macro with their desired + // name. + virtual metrics_util::ReportCallback GetReportCallback() const = 0; + + DesksController* const controller_; + + // An animator object per each root. Once all the animations are complete, + // this list is cleared. + std::vector<std::unique_ptr<RootWindowDeskSwitchAnimator>> + desk_switch_animators_; + + // The desk that will be active after this animation ends. + const Desk* const ending_desk_; + + private: + // ThroughputTracker used for measuring this animation smoothness. + ui::ThroughputTracker throughput_tracker_; +}; + +} // namespace ash + +#endif // ASH_WM_DESKS_DESK_ANIMATION_BASE_H_
diff --git a/ash/wm/desks/desk_animation_impl.cc b/ash/wm/desks/desk_animation_impl.cc new file mode 100644 index 0000000..b917708b --- /dev/null +++ b/ash/wm/desks/desk_animation_impl.cc
@@ -0,0 +1,143 @@ +// 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/wm/desks/desk_animation_impl.h" + +#include "ash/shell.h" +#include "ash/wm/desks/desk.h" +#include "ash/wm/desks/desks_controller.h" +#include "ash/wm/overview/overview_controller.h" +#include "ash/wm/splitview/split_view_utils.h" +#include "ash/wm/window_util.h" +#include "base/metrics/histogram_macros.h" + +namespace ash { + +namespace { + +constexpr char kDeskActivationSmoothnessHistogramName[] = + "Ash.Desks.AnimationSmoothness.DeskActivation"; +constexpr char kDeskRemovalSmoothnessHistogramName[] = + "Ash.Desks.AnimationSmoothness.DeskRemoval"; + +} // namespace + +// ----------------------------------------------------------------------------- +// DeskActivationAnimation: + +DeskActivationAnimation::DeskActivationAnimation(DesksController* controller, + const Desk* ending_desk, + bool move_left) + : DeskAnimationBase(controller, ending_desk) { + for (auto* root : Shell::GetAllRootWindows()) { + desk_switch_animators_.emplace_back( + std::make_unique<RootWindowDeskSwitchAnimator>(root, ending_desk, this, + move_left, + /*for_remove=*/false)); + } +} + +DeskActivationAnimation::~DeskActivationAnimation() = default; + +void DeskActivationAnimation::OnStartingDeskScreenshotTakenInternal( + const Desk* ending_desk) { + DCHECK_EQ(ending_desk_, ending_desk); + // The order here matters. Overview must end before ending tablet split view + // before switching desks. (If clamshell split view is active on one or more + // displays, then it simply will end when we end overview.) That's because + // we don't want |TabletModeWindowManager| maximizing all windows because we + // cleared the snapped ones in |SplitViewController| first. See + // |TabletModeWindowManager::OnOverviewModeEndingAnimationComplete|. + // See also test coverage for this case in + // `TabletModeDesksTest.SnappedStateRetainedOnSwitchingDesksFromOverview`. + const bool in_overview = + Shell::Get()->overview_controller()->InOverviewSession(); + if (in_overview) { + // Exit overview mode immediately without any animations before taking the + // ending desk screenshot. This makes sure that the ending desk + // screenshot will only show the windows in that desk, not overview stuff. + Shell::Get()->overview_controller()->EndOverview( + OverviewEnterExitType::kImmediateExit); + } + SplitViewController* split_view_controller = + SplitViewController::Get(Shell::GetPrimaryRootWindow()); + split_view_controller->EndSplitView( + SplitViewController::EndReason::kDesksChange); + + controller_->ActivateDeskInternal(ending_desk, + /*update_window_activation=*/true); + + MaybeRestoreSplitView(/*refresh_snapped_windows=*/true); +} + +metrics_util::ReportCallback DeskActivationAnimation::GetReportCallback() + const { + return metrics_util::ForSmoothness(base::BindRepeating([](int smoothness) { + UMA_HISTOGRAM_PERCENTAGE(kDeskActivationSmoothnessHistogramName, + smoothness); + })); +} + +// ----------------------------------------------------------------------------- +// DeskRemovalAnimation: + +DeskRemovalAnimation::DeskRemovalAnimation(DesksController* controller, + const Desk* desk_to_remove, + const Desk* desk_to_activate, + bool move_left, + DesksCreationRemovalSource source) + : DeskAnimationBase(controller, desk_to_activate), + desk_to_remove_(desk_to_remove), + request_source_(source) { + DCHECK(!Shell::Get()->overview_controller()->InOverviewSession()); + DCHECK_EQ(controller_->active_desk(), desk_to_remove_); + + for (auto* root : Shell::GetAllRootWindows()) { + desk_switch_animators_.emplace_back( + std::make_unique<RootWindowDeskSwitchAnimator>(root, desk_to_activate, + this, move_left, + /*for_remove=*/true)); + } +} + +DeskRemovalAnimation::~DeskRemovalAnimation() = default; + +void DeskRemovalAnimation::OnStartingDeskScreenshotTakenInternal( + const Desk* ending_desk) { + DCHECK_EQ(ending_desk_, ending_desk); + DCHECK_EQ(controller_->active_desk(), desk_to_remove_); + // We are removing the active desk, which may have tablet split view active. + // We will restore the split view state of the newly activated desk at the + // end of the animation. Clamshell split view is impossible because + // |DeskRemovalAnimation| is not used in overview. + SplitViewController* split_view_controller = + SplitViewController::Get(Shell::GetPrimaryRootWindow()); + split_view_controller->EndSplitView( + SplitViewController::EndReason::kDesksChange); + + // At the end of phase (1), we activate the target desk (i.e. the desk that + // will be activated after the active desk `desk_to_remove_` is removed). + // This means that phase (2) will take a screenshot of that desk before we + // move the windows of `desk_to_remove_` to that target desk. + controller_->ActivateDeskInternal(ending_desk, + /*update_window_activation=*/false); +} + +void DeskRemovalAnimation::OnDeskSwitchAnimationFinishedInternal() { + // Do the actual desk removal behind the scenes before the screenshot layers + // are destroyed. + controller_->RemoveDeskInternal(desk_to_remove_, request_source_); + + MaybeRestoreSplitView(/*refresh_snapped_windows=*/true); +} + +metrics_util::ReportCallback DeskRemovalAnimation::GetReportCallback() const { + return ash::metrics_util::ForSmoothness( + base::BindRepeating([](int smoothness) { + UMA_HISTOGRAM_PERCENTAGE(kDeskRemovalSmoothnessHistogramName, + smoothness); + })); +} + +} // namespace ash
diff --git a/ash/wm/desks/desk_animation_impl.h b/ash/wm/desks/desk_animation_impl.h new file mode 100644 index 0000000..beb7e7a --- /dev/null +++ b/ash/wm/desks/desk_animation_impl.h
@@ -0,0 +1,55 @@ +// 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_WM_DESKS_DESK_ANIMATION_IMPL_H_ +#define ASH_WM_DESKS_DESK_ANIMATION_IMPL_H_ + +#include "ash/public/cpp/metrics_util.h" +#include "ash/wm/desks/desk_animation_base.h" +#include "ash/wm/desks/desks_histogram_enums.h" + +namespace ash { + +class Desk; +class DesksController; + +class DeskActivationAnimation : public DeskAnimationBase { + public: + DeskActivationAnimation(DesksController* controller, + const Desk* ending_desk, + bool move_left); + DeskActivationAnimation(const DeskActivationAnimation&) = delete; + DeskActivationAnimation& operator=(const DeskActivationAnimation&) = delete; + ~DeskActivationAnimation() override; + + // DeskAnimationBase: + void OnStartingDeskScreenshotTakenInternal(const Desk* ending_desk) override; + void OnDeskSwitchAnimationFinishedInternal() override {} + metrics_util::ReportCallback GetReportCallback() const override; +}; + +class DeskRemovalAnimation : public DeskAnimationBase { + public: + DeskRemovalAnimation(DesksController* controller, + const Desk* desk_to_remove, + const Desk* desk_to_activate, + bool move_left, + DesksCreationRemovalSource source); + DeskRemovalAnimation(const DeskRemovalAnimation&) = delete; + DeskRemovalAnimation& operator=(const DeskRemovalAnimation&) = delete; + ~DeskRemovalAnimation() override; + + // DeskAnimationBase: + void OnStartingDeskScreenshotTakenInternal(const Desk* ending_desk) override; + void OnDeskSwitchAnimationFinishedInternal() override; + metrics_util::ReportCallback GetReportCallback() const override; + + private: + const Desk* const desk_to_remove_; + const DesksCreationRemovalSource request_source_; +}; + +} // namespace ash + +#endif // ASH_WM_DESKS_DESK_ANIMATION_IMPL_H_
diff --git a/ash/wm/desks/desks_controller.cc b/ash/wm/desks/desks_controller.cc index 441591d..0cb3cb3 100644 --- a/ash/wm/desks/desks_controller.cc +++ b/ash/wm/desks/desks_controller.cc
@@ -8,7 +8,6 @@ #include "ash/accessibility/accessibility_controller_impl.h" #include "ash/public/cpp/ash_features.h" -#include "ash/public/cpp/metrics_util.h" #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/shelf_types.h" #include "ash/public/cpp/shell_window_ids.h" @@ -17,10 +16,11 @@ #include "ash/shell.h" #include "ash/strings/grit/ash_strings.h" #include "ash/wm/desks/desk.h" +#include "ash/wm/desks/desk_animation_base.h" +#include "ash/wm/desks/desk_animation_impl.h" #include "ash/wm/desks/desks_animations.h" #include "ash/wm/desks/desks_restore_util.h" #include "ash/wm/desks/desks_util.h" -#include "ash/wm/desks/root_window_desk_switch_animator.h" #include "ash/wm/mru_window_tracker.h" #include "ash/wm/overview/overview_controller.h" #include "ash/wm/overview/overview_grid.h" @@ -35,10 +35,7 @@ #include "base/notreached.h" #include "base/numerics/ranges.h" #include "base/stl_util.h" -#include "ui/aura/window_tree_host.h" #include "ui/base/l10n/l10n_util.h" -#include "ui/compositor/compositor.h" -#include "ui/compositor/throughput_tracker.h" #include "ui/wm/public/activation_client.h" namespace ash { @@ -59,10 +56,6 @@ "Ash.Desks.NumberOfWindowsOnDesk_3"; constexpr char kNumberOfWindowsOnDesk_4_HistogramName[] = "Ash.Desks.NumberOfWindowsOnDesk_4"; -constexpr char kDeskActivationSmoothnessHistogramName[] = - "Ash.Desks.AnimationSmoothness.DeskActivation"; -constexpr char kDeskRemovalSmoothnessHistogramName[] = - "Ash.Desks.AnimationSmoothness.DeskRemoval"; // Appends the given |windows| to the end of the currently active overview mode // session such that the most-recently used window is added first. If @@ -95,18 +88,6 @@ } } -// Selects and returns the compositor to measure the animation smoothness. -ui::Compositor* GetSelectedCompositorForAnimationSmoothness() { - // Favor the compositor associated with the active window's root window (if - // any), or that of the primary root window. - auto* active_window = window_util::GetActiveWindow(); - auto* selected_root = active_window && active_window->GetRootWindow() - ? active_window->GetRootWindow() - : Shell::GetPrimaryRootWindow(); - DCHECK(selected_root); - return selected_root->layer()->GetCompositor(); -} - base::string16 GetDeskDefaultName(size_t desk_index) { DCHECK_LT(desk_index, desks_util::kMaxNumberOfDesks); constexpr int kStringIds[] = {IDS_ASH_DESKS_DESK_1_MINI_VIEW_TITLE, @@ -155,291 +136,6 @@ } // namespace -// ----------------------------------------------------------------------------- -// DesksController::AbstractDeskSwitchAnimation: - -// An abstract class that handles the shared operations need to be performed -// when doing an animation that causes a desk switch animation. Subclasses -// such as DeskActivationAnimation and DeskRemovalAnimation implement the -// abstract interface of this class to handle the unique operations specific to -// each animation type. -class DesksController::DeskAnimationBase - : public RootWindowDeskSwitchAnimator::Delegate { - public: - ~DeskAnimationBase() override = default; - - const Desk* ending_desk() const { return ending_desk_; } - - // Launches the animation. This should be done once all animators - // are created and added to `desk_switch_animators_`. This is to avoid any - // potential race conditions that might happen if one animator finished phase - // (1) of the animation while other animators are still being constructed. - void Launch() { - for (auto& observer : controller_->observers_) - observer.OnDeskSwitchAnimationLaunching(); - - throughput_tracker_.Start(GetReportCallback()); - - // This step makes sure that the containers of the target desk are shown at - // the beginning of the animation (but not actually visible to the user yet, - // until the desk is actually activated at a later step of the animation). - // This is needed because a window on the target desk can be focused before - // the desk becomes active (See `DesksController::OnWindowActivating()`). - // This window must be able to accept events (See - // `aura::Window::CanAcceptEvent()`) even though its desk is still being - // activated. https://crbug.com/1008574. - const_cast<Desk*>(ending_desk_)->PrepareForActivationAnimation(); - - DCHECK(!desk_switch_animators_.empty()); - for (auto& animator : desk_switch_animators_) - animator->TakeStartingDeskScreenshot(); - } - - // RootWindowDeskSwitchAnimator::Delegate: - void OnStartingDeskScreenshotTaken(const Desk* ending_desk) override { - DCHECK(!desk_switch_animators_.empty()); - - // Once all starting desk screenshots on all roots are taken and placed on - // the screens, do the actual desk activation logic. - for (const auto& animator : desk_switch_animators_) { - if (!animator->starting_desk_screenshot_taken()) - return; - } - - // Extend the compositors' timeouts in order to prevents any repaints until - // the desks are switched and overview mode exits. - const auto roots = Shell::GetAllRootWindows(); - for (auto* root : roots) - root->GetHost()->compositor()->SetAllowLocksToExtendTimeout(true); - - OnStartingDeskScreenshotTakenInternal(ending_desk); - - for (auto* root : roots) - root->GetHost()->compositor()->SetAllowLocksToExtendTimeout(false); - - // Continue the second phase of the animation by taking the ending desk - // screenshot and actually animating the layers. - for (auto& animator : desk_switch_animators_) - animator->TakeEndingDeskScreenshot(); - } - - void OnEndingDeskScreenshotTaken() override { - DCHECK(!desk_switch_animators_.empty()); - - // Once all ending desk screenshots on all roots are taken, start the - // animation on all roots at the same time, so that they look synchrnoized. - for (const auto& animator : desk_switch_animators_) { - if (!animator->ending_desk_screenshot_taken()) - return; - } - - for (auto& animator : desk_switch_animators_) - animator->StartAnimation(); - } - - void OnDeskSwitchAnimationFinished() override { - DCHECK(!desk_switch_animators_.empty()); - - // Once all desk switch animations on all roots finish, destroy all the - // animators. - for (const auto& animator : desk_switch_animators_) { - if (!animator->animation_finished()) - return; - } - - OnDeskSwitchAnimationFinishedInternal(); - - desk_switch_animators_.clear(); - - throughput_tracker_.Stop(); - - for (auto& observer : controller_->observers_) - observer.OnDeskSwitchAnimationFinished(); - - controller_->OnAnimationFinished(this); - // `this` is now deleted. - } - - protected: - DeskAnimationBase(DesksController* controller, const Desk* ending_desk) - : controller_(controller), ending_desk_(ending_desk) { - DCHECK(controller_); - DCHECK(ending_desk_); - } - - // Abstract functions that can be overridden by child classes to do different - // things when phase (1), and phase (3) completes. Note that - // `OnDeskSwitchAnimationFinishedInternal()` will be called before the desks - // screenshot layers, stored in `desk_switch_animators_`, are destroyed. - virtual void OnStartingDeskScreenshotTakenInternal( - const Desk* ending_desk) = 0; - virtual void OnDeskSwitchAnimationFinishedInternal() = 0; - - // Since performance here matters, we have to use the UMA histograms macros to - // report the smoothness histograms, but each macro use has to be associated - // with exactly one histogram name. This function allows subclasses to return - // a callback that reports the histogram using the macro with their desired - // name. - virtual ash::metrics_util::ReportCallback GetReportCallback() const = 0; - - DesksController* const controller_; - - // An animator object per each root. Once all the animations are complete, - // this list is cleared. - std::vector<std::unique_ptr<RootWindowDeskSwitchAnimator>> - desk_switch_animators_; - - // The desk that will be active after this animation ends. - const Desk* const ending_desk_; - - private: - // ThroughputTracker used for measuring this animation smoothness. - ui::ThroughputTracker throughput_tracker_ = - GetSelectedCompositorForAnimationSmoothness() - ->RequestNewThroughputTracker(); - - DISALLOW_COPY_AND_ASSIGN(DeskAnimationBase); -}; - -// ----------------------------------------------------------------------------- -// DesksController::DeskActivationAnimation: - -class DesksController::DeskActivationAnimation - : public DesksController::DeskAnimationBase { - public: - DeskActivationAnimation(DesksController* controller, - const Desk* ending_desk, - bool move_left) - : DeskAnimationBase(controller, ending_desk) { - for (auto* root : Shell::GetAllRootWindows()) { - desk_switch_animators_.emplace_back( - std::make_unique<RootWindowDeskSwitchAnimator>(root, ending_desk, - this, move_left, - /*for_remove=*/false)); - } - } - - ~DeskActivationAnimation() override = default; - - // DesksController::AbstractDeskSwitchAnimation: - void OnStartingDeskScreenshotTakenInternal(const Desk* ending_desk) override { - DCHECK_EQ(ending_desk_, ending_desk); - // The order here matters. Overview must end before ending tablet split view - // before switching desks. (If clamshell split view is active on one or more - // displays, then it simply will end when we end overview.) That's because - // we don't want |TabletModeWindowManager| maximizing all windows because we - // cleared the snapped ones in |SplitViewController| first. See - // |TabletModeWindowManager::OnOverviewModeEndingAnimationComplete|. - // See also test coverage for this case in - // `TabletModeDesksTest.SnappedStateRetainedOnSwitchingDesksFromOverview`. - const bool in_overview = - Shell::Get()->overview_controller()->InOverviewSession(); - if (in_overview) { - // Exit overview mode immediately without any animations before taking the - // ending desk screenshot. This makes sure that the ending desk - // screenshot will only show the windows in that desk, not overview stuff. - Shell::Get()->overview_controller()->EndOverview( - OverviewEnterExitType::kImmediateExit); - } - SplitViewController* split_view_controller = - SplitViewController::Get(Shell::GetPrimaryRootWindow()); - split_view_controller->EndSplitView( - SplitViewController::EndReason::kDesksChange); - - controller_->ActivateDeskInternal(ending_desk, - /*update_window_activation=*/true); - - MaybeRestoreSplitView(/*refresh_snapped_windows=*/true); - } - - void OnDeskSwitchAnimationFinishedInternal() override {} - - ash::metrics_util::ReportCallback GetReportCallback() const override { - return ash::metrics_util::ForSmoothness( - base::BindRepeating([](int smoothness) { - UMA_HISTOGRAM_PERCENTAGE(kDeskActivationSmoothnessHistogramName, - smoothness); - })); - } - - private: - DISALLOW_COPY_AND_ASSIGN(DeskActivationAnimation); -}; - -// ----------------------------------------------------------------------------- -// DesksController::DeskRemovalAnimation: - -class DesksController::DeskRemovalAnimation - : public DesksController::DeskAnimationBase { - public: - DeskRemovalAnimation(DesksController* controller, - const Desk* desk_to_remove, - const Desk* desk_to_activate, - bool move_left, - DesksCreationRemovalSource source) - : DeskAnimationBase(controller, desk_to_activate), - desk_to_remove_(desk_to_remove), - request_source_(source) { - DCHECK(!Shell::Get()->overview_controller()->InOverviewSession()); - DCHECK_EQ(controller_->active_desk(), desk_to_remove_); - - for (auto* root : Shell::GetAllRootWindows()) { - desk_switch_animators_.emplace_back( - std::make_unique<RootWindowDeskSwitchAnimator>(root, desk_to_activate, - this, move_left, - /*for_remove=*/true)); - } - } - - ~DeskRemovalAnimation() override = default; - - // DesksController::AbstractDeskSwitchAnimation: - void OnStartingDeskScreenshotTakenInternal(const Desk* ending_desk) override { - DCHECK_EQ(ending_desk_, ending_desk); - DCHECK_EQ(controller_->active_desk(), desk_to_remove_); - // We are removing the active desk, which may have tablet split view active. - // We will restore the split view state of the newly activated desk at the - // end of the animation. Clamshell split view is impossible because - // |DeskRemovalAnimation| is not used in overview. - SplitViewController* split_view_controller = - SplitViewController::Get(Shell::GetPrimaryRootWindow()); - split_view_controller->EndSplitView( - SplitViewController::EndReason::kDesksChange); - - // At the end of phase (1), we activate the target desk (i.e. the desk that - // will be activated after the active desk `desk_to_remove_` is removed). - // This means that phase (2) will take a screenshot of that desk before we - // move the windows of `desk_to_remove_` to that target desk. - controller_->ActivateDeskInternal(ending_desk, - /*update_window_activation=*/false); - } - - void OnDeskSwitchAnimationFinishedInternal() override { - // Do the actual desk removal behind the scenes before the screenshot layers - // are destroyed. - controller_->RemoveDeskInternal(desk_to_remove_, request_source_); - - MaybeRestoreSplitView(/*refresh_snapped_windows=*/true); - } - - ash::metrics_util::ReportCallback GetReportCallback() const override { - return ash::metrics_util::ForSmoothness( - base::BindRepeating([](int smoothness) { - UMA_HISTOGRAM_PERCENTAGE(kDeskRemovalSmoothnessHistogramName, - smoothness); - })); - } - - private: - const Desk* const desk_to_remove_; - const DesksCreationRemovalSource request_source_; - - DISALLOW_COPY_AND_ASSIGN(DeskRemovalAnimation); -}; - -// ----------------------------------------------------------------------------- -// DesksController: - DesksController::DesksController() { Shell::Get()->activation_client()->AddObserver(this); Shell::Get()->session_controller()->AddObserver(this);
diff --git a/ash/wm/desks/desks_controller.h b/ash/wm/desks/desks_controller.h index 1f588e8..b71c1db 100644 --- a/ash/wm/desks/desks_controller.h +++ b/ash/wm/desks/desks_controller.h
@@ -27,6 +27,7 @@ namespace ash { class Desk; +class DeskAnimationBase; // Defines a controller for creating, destroying and managing virtual desks and // their windows. @@ -167,9 +168,9 @@ void OnFirstSessionStarted() override; private: - class DeskAnimationBase; - class DeskActivationAnimation; - class DeskRemovalAnimation; + friend class DeskAnimationBase; + friend class DeskActivationAnimation; + friend class DeskRemovalAnimation; void OnAnimationFinished(DeskAnimationBase* animation);
diff --git a/base/logging.h b/base/logging.h index 0adda2c29..d967ecb3 100644 --- a/base/logging.h +++ b/base/logging.h
@@ -105,6 +105,10 @@ // E.g., "*/foo/bar/*=2" would change the logging level for all code // in source files under a "foo/bar" directory. // +// Note that for a Chromium binary built in release mode (is_debug = false) you +// must pass "--enable-logging=stderr" in order to see the output of VLOG +// statements. +// // There's also VLOG_IS_ON(n) "verbose level" condition macro. To be used as // // if (VLOG_IS_ON(2)) { @@ -157,6 +161,9 @@ // // Note that the visibility can be changed by setting preferences in // SetLogItems() +// +// Additional logging-related information can be found here: +// https://chromium.googlesource.com/chromium/src/+/master/docs/linux/debugging.md#Logging namespace logging {
diff --git a/base/process/kill.h b/base/process/kill.h index 9d33283b..b955870f 100644 --- a/base/process/kill.h +++ b/base/process/kill.h
@@ -84,12 +84,6 @@ int exit_code, const ProcessFilter* filter); -#if defined(OS_POSIX) -// Attempts to kill the process group identified by |process_group_id|. Returns -// true on success. -BASE_EXPORT bool KillProcessGroup(ProcessHandle process_group_id); -#endif // defined(OS_POSIX) - // Get the termination status of the process by interpreting the // circumstances of the child process' death. |exit_code| is set to // the status returned by waitpid() on POSIX, and from GetExitCodeProcess() on
diff --git a/base/process/kill_fuchsia.cc b/base/process/kill_fuchsia.cc index 1b7bbd6a..456033e5 100644 --- a/base/process/kill_fuchsia.cc +++ b/base/process/kill_fuchsia.cc
@@ -13,14 +13,6 @@ namespace base { -bool KillProcessGroup(ProcessHandle process_group_id) { - // |process_group_id| is really a job on Fuchsia. - zx_status_t status = zx_task_kill(process_group_id); - DLOG_IF(ERROR, status != ZX_OK) - << "unable to terminate job " << process_group_id; - return status == ZX_OK; -} - TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) { DCHECK(exit_code);
diff --git a/base/process/kill_posix.cc b/base/process/kill_posix.cc index 86d5096..0750d9a 100644 --- a/base/process/kill_posix.cc +++ b/base/process/kill_posix.cc
@@ -78,15 +78,6 @@ } // namespace -#if !defined(OS_NACL_NONSFI) -bool KillProcessGroup(ProcessHandle process_group_id) { - bool result = kill(-1 * process_group_id, SIGKILL) == 0; - if (!result) - DPLOG(ERROR) << "Unable to terminate process group " << process_group_id; - return result; -} -#endif // !defined(OS_NACL_NONSFI) - TerminationStatus GetTerminationStatus(ProcessHandle handle, int* exit_code) { return GetTerminationStatusImpl(handle, false /* can_block */, exit_code); }
diff --git a/base/stl_util.h b/base/stl_util.h index 8e9fab3..4d54da34 100644 --- a/base/stl_util.h +++ b/base/stl_util.h
@@ -713,6 +713,14 @@ return optional.has_value() ? &optional.value() : nullptr; } +// Helper for creating an Optional<T> from a potentially nullptr T*. +template <class T> +base::Optional<T> OptionalFromPtr(const T* value) { + if (value) + return base::Optional<T>(*value); + return base::nullopt; +} + } // namespace base #endif // BASE_STL_UTIL_H_
diff --git a/base/test/launcher/test_launcher.cc b/base/test/launcher/test_launcher.cc index 66c4c89c..1abc32d 100644 --- a/base/test/launcher/test_launcher.cc +++ b/base/test/launcher/test_launcher.cc
@@ -438,38 +438,21 @@ // Cleanup the data directory. CHECK(DeletePathRecursively(nested_data_path)); #elif defined(OS_POSIX) - -#if BUILDFLAG(CLANG_PROFILING) - // TODO(crbug.com/1094369): Remove this condition once the child process - // leaking bug is fixed. - // - // TODO(crbug.com/1095075): Make test launcher treat lingering child - // processes hard failures so that they can be detected and surfaced - // gracefully. - // - // When profiling is enabled, browser child processes take extra time to - // dump profiles, which means that lingering processes are much more likely - // to happen than non-profiling build. Therefore, on POSIX, in order to - // avoid polluting the machine state, ensure any child processes that the - // test might have created are cleaned up to avoid potential leaking even - // when tests have passed. On Windows, child processes are automatically - // cleaned up using JobObjects. - // - // On non-profiling build, when tests have passed, we don't clean up the - // lingering processes even when there are any, and the reason is that they - // usually indicate prod issues, letting them slip to the following test - // tasks and cause failures increses the chance of them being surfaced. - kill(-1 * process.Handle(), SIGKILL); -#else - if (exit_code != 0) { - // On POSIX, in case the test does not exit cleanly, either due to a crash - // or due to it timing out, we need to clean up any child processes that - // it might have created. On Windows, child processes are automatically - // cleaned up using JobObjects. - KillProcessGroup(process.Handle()); + // It is not possible to waitpid() on any leaked sub-processes of the test + // batch process, since those are not direct children of this process. + // kill()ing the process-group will return a result indicating whether the + // group was found (i.e. processes were still running in it) or not (i.e. + // sub-processes had exited already). Unfortunately many tests (e.g. browser + // tests) have processes exit asynchronously, so checking the kill() result + // will report false failures. + // Unconditionally kill the process group, regardless of the batch exit-code + // until a better solution is available. + int kill_result = kill(-1 * process.Handle(), SIGKILL); + if (kill_result < 0 && errno != ESRCH) { + PLOG(ERROR) << "kill(-" << process.Handle() << ") failed"; + exit_code = -1; } -#endif -#endif +#endif // defined(OS_POSIX) GetLiveProcesses()->erase(process.Handle()); }
diff --git a/base/test/launcher/test_launcher_unittest.cc b/base/test/launcher/test_launcher_unittest.cc index bcf7df0..dfa69e4 100644 --- a/base/test/launcher/test_launcher_unittest.cc +++ b/base/test/launcher/test_launcher_unittest.cc
@@ -15,12 +15,14 @@ #include "base/test/launcher/test_launcher.h" #include "base/test/launcher/test_launcher_test_utils.h" #include "base/test/launcher/unit_test_launcher.h" +#include "base/test/multiprocess_test.h" #include "base/test/task_environment.h" #include "base/test/test_timeouts.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "testing/multiprocess_func_list.h" #if defined(OS_WIN) #include "base/win/windows_version.h" @@ -708,12 +710,12 @@ TEST(MockUnitTests, DISABLED_CrashTest) { IMMEDIATE_CRASH(); } -// Basic test will not be reached with default batch size. +// Basic test will not be reached, due to the preceding crash in the same batch. TEST(MockUnitTests, DISABLED_NoRunTest) { ASSERT_TRUE(true); } -// Using TestLauncher to launch 3 simple unitests +// Using TestLauncher to launch 3 basic unitests // and validate the resulting json file. TEST_F(UnitTestLauncherDelegateTester, RunMockTests) { CommandLine command_line(CommandLine::ForCurrentProcess()->GetProgram());
diff --git a/base/trace_event/builtin_categories.h b/base/trace_event/builtin_categories.h index 58f3fa1d..732db68 100644 --- a/base/trace_event/builtin_categories.h +++ b/base/trace_event/builtin_categories.h
@@ -185,6 +185,7 @@ X(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler")) \ X(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.frames")) \ X(TRACE_DISABLED_BY_DEFAULT("cc.debug.scheduler.now")) \ + X(TRACE_DISABLED_BY_DEFAULT("content.verbose")) \ X(TRACE_DISABLED_BY_DEFAULT("cpu_profiler")) \ X(TRACE_DISABLED_BY_DEFAULT("cpu_profiler.debug")) \ X(TRACE_DISABLED_BY_DEFAULT("devtools.screenshot")) \
diff --git a/base/util/type_safety/token_type.h b/base/util/type_safety/token_type.h index 9ba8bfb3..0a126795 100644 --- a/base/util/type_safety/token_type.h +++ b/base/util/type_safety/token_type.h
@@ -10,12 +10,19 @@ namespace util { -// A specialization of StrongAlias for base::UnguessableToken. +// A specialization of StrongAlias for base::UnguessableToken. Unlike +// base::UnguessableToken, a TokenType<...> does not default to null and does +// not expose the concept of null tokens. If you need to indicate a null token, +// please use base::Optional<TokenType<...>>. template <typename TypeMarker> class TokenType : public StrongAlias<TypeMarker, base::UnguessableToken> { + private: + using Super = StrongAlias<TypeMarker, base::UnguessableToken>; + public: - // Inherit constructors. - using StrongAlias<TypeMarker, base::UnguessableToken>::StrongAlias; + TokenType() : Super(base::UnguessableToken::Create()) {} + explicit TokenType(const base::UnguessableToken& token) : Super(token) {} + TokenType(const TokenType& token) : Super(token.value()) {} // This object allows default assignment operators for compatibility with // STL containers. @@ -30,16 +37,7 @@ }; // Mimic the base::UnguessableToken API for ease and familiarity of use. - static TokenType Create() { - return TokenType(base::UnguessableToken::Create()); - } - static const TokenType& Null() { - static const TokenType kNull; - return kNull; - } - bool is_empty() const { return this->value().is_empty(); } std::string ToString() const { return this->value().ToString(); } - explicit constexpr operator bool() const { return !is_empty(); } }; } // namespace util
diff --git a/base/util/type_safety/token_type_unittest.cc b/base/util/type_safety/token_type_unittest.cc index ccd04bfa..ebab66c1 100644 --- a/base/util/type_safety/token_type_unittest.cc +++ b/base/util/type_safety/token_type_unittest.cc
@@ -11,38 +11,29 @@ using FooToken = TokenType<class Foo>; TEST(TokenType, TokenApi) { - // Test static builders. - EXPECT_TRUE(FooToken::Null().is_empty()); - EXPECT_FALSE(FooToken::Create().is_empty()); - // Test default initialization. FooToken token1; - EXPECT_TRUE(token1.is_empty()); + EXPECT_FALSE(token1.value().is_empty()); // Test copy construction. - FooToken token2(FooToken::Create()); - EXPECT_FALSE(token2.is_empty()); + FooToken token2(token1); + EXPECT_FALSE(token2.value().is_empty()); + EXPECT_EQ(token1.value(), token2.value()); // Test assignment. FooToken token3; - EXPECT_TRUE(token3.is_empty()); token3 = token2; - EXPECT_FALSE(token3.is_empty()); + EXPECT_FALSE(token3.value().is_empty()); + EXPECT_EQ(token2.value(), token3.value()); - // Test bool conversion. - EXPECT_FALSE(token1); - EXPECT_TRUE(token2); - EXPECT_TRUE(token3); + FooToken token4; // Test comparison operators. - EXPECT_TRUE(token1 == FooToken::Null()); - EXPECT_FALSE(token1 == token2); + EXPECT_TRUE(token1 == token2); EXPECT_TRUE(token2 == token3); - EXPECT_FALSE(token1 != FooToken::Null()); - EXPECT_TRUE(token1 != token2); - EXPECT_FALSE(token2 != token3); - EXPECT_TRUE(token1 < token2); - EXPECT_FALSE(token2 < token3); + EXPECT_TRUE((token4 < token1) ^ (token1 < token4)); + EXPECT_FALSE(token1 != token2); + EXPECT_TRUE(token1 != token4); // Test hasher. EXPECT_EQ(FooToken::Hasher()(token2),
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index ccd99db5..01bee43c 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -0.20200811.4.2 +0.20200812.1.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index ccd99db5..01bee43c 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -0.20200811.4.2 +0.20200812.1.1
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index 9f2e8ed..e56746ee 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -484,6 +484,7 @@ "javatests/src/org/chromium/chrome/browser/share/ShareDelegateImplIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/share/ShareDelegateImplTest.java", "javatests/src/org/chromium/chrome/browser/share/ShareUrlTest.java", + "javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java", "javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java", "javatests/src/org/chromium/chrome/browser/signin/AccountPickerDialogFragmentTest.java", "javatests/src/org/chromium/chrome/browser/signin/ConfirmManagedSyncDataDialogIntegrationTest.java",
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantChromeTabIntegrationTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantChromeTabIntegrationTest.java index 6a63b6a..54ecf6e9 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantChromeTabIntegrationTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantChromeTabIntegrationTest.java
@@ -17,6 +17,7 @@ import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.is; +import static org.hamcrest.Matchers.not; import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilKeyboardMatchesCondition; import static org.chromium.chrome.browser.autofill_assistant.AutofillAssistantUiTestUtil.waitUntilViewAssertionTrue; @@ -336,7 +337,7 @@ // Clicking location bar hides UI and shows the keyboard. onView(withId(org.chromium.chrome.R.id.url_bar)).perform(click()); - waitUntilViewAssertionTrue(withText("Prompt"), doesNotExist(), DEFAULT_MAX_TIME_TO_POLL); + waitUntilViewMatchesCondition(withText("Prompt"), not(isCompletelyDisplayed())); waitUntilKeyboardMatchesCondition(mTestRule, /* isShowing= */ true); // Closing keyboard brings it back.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java index 747872a..a94c44b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeBackupAgent.java
@@ -29,7 +29,6 @@ import org.chromium.chrome.browser.signin.IdentityServicesProvider; import org.chromium.components.signin.AccountManagerFacadeProvider; import org.chromium.components.signin.AccountUtils; -import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.base.CoreAccountInfo; import org.chromium.components.signin.identitymanager.ConsentLevel; import org.chromium.content_public.browser.UiThreadTaskTraits; @@ -99,6 +98,10 @@ ChromePreferenceKeys.PRIVACY_METRICS_REPORTING, }; + // Key used to store the email of the signed in account. This email is obtained from + // IdentityManager during the backup. + static final String SIGNED_IN_ACCOUNT_KEY = "google.services.username"; + // Timeout for running the background tasks, needs to be quite long since they may be doing // network access, but must be less than the 1 minute restore timeout to be useful. private static final long BACKGROUND_TASK_TIMEOUT_SECS = 20; @@ -245,8 +248,7 @@ IdentityServicesProvider.get() .getIdentityManager(Profile.getLastUsedRegularProfile()) .getPrimaryAccountInfo(ConsentLevel.SYNC); - // TODO(https://crbug.com/1046412): Inline SIGNED_IN_ACCOUNT_KEY in this class. - backupNames.add(ANDROID_DEFAULT_PREFIX + ChromeSigninController.SIGNED_IN_ACCOUNT_KEY); + backupNames.add(ANDROID_DEFAULT_PREFIX + SIGNED_IN_ACCOUNT_KEY); backupValues.add(ApiCompatibilityUtils.getBytesUtf8( accountInfo == null ? "" : accountInfo.getEmail())); @@ -303,7 +305,7 @@ int dataSize = data.getDataSize(); byte[] buffer = new byte[dataSize]; data.readEntityData(buffer, 0, dataSize); - if (key.equals(ANDROID_DEFAULT_PREFIX + ChromeSigninController.SIGNED_IN_ACCOUNT_KEY)) { + if (key.equals(ANDROID_DEFAULT_PREFIX + SIGNED_IN_ACCOUNT_KEY)) { restoredUserName = new String(buffer); } else { backupNames.add(key);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediator.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediator.java index 189b6f1..2764914c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/toolbar/TopToolbarOverlayMediator.java
@@ -111,6 +111,7 @@ @Override public void onContentChanged(Tab tab) { updateVisibility(); + updateThemeColor(tab); } };
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAState.java b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAState.java index 3b411eb..e214376 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAState.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/gsa/GSAState.java
@@ -21,10 +21,12 @@ import org.chromium.base.PackageManagerUtils; import org.chromium.base.PackageUtils; import org.chromium.chrome.browser.IntentHandler; +import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileManager; import org.chromium.chrome.browser.signin.IdentityServicesProvider; import org.chromium.components.signin.base.CoreAccountInfo; import org.chromium.components.signin.identitymanager.ConsentLevel; +import org.chromium.components.signin.identitymanager.IdentityManager; import java.util.List; @@ -102,9 +104,10 @@ */ public boolean doesGsaAccountMatchChrome() { if (!ProfileManager.isInitialized()) return false; + IdentityManager identityManager = IdentityServicesProvider.get().getIdentityManager( + Profile.getLastUsedRegularProfile()); CoreAccountInfo chromeAccountInfo = - IdentityServicesProvider.get().getIdentityManager().getPrimaryAccountInfo( - ConsentLevel.SYNC); + identityManager.getPrimaryAccountInfo(ConsentLevel.SYNC); return chromeAccountInfo != null && !TextUtils.isEmpty(mGsaAccount) && TextUtils.equals(chromeAccountInfo.getEmail(), mGsaAccount); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java index 744a825..7ea7266 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegate.java
@@ -18,9 +18,11 @@ import org.chromium.chrome.browser.signin.IdentityServicesProvider; import org.chromium.chrome.browser.signin.SigninManager; import org.chromium.chrome.browser.signin.SigninUtils; +import org.chromium.chrome.browser.signin.WebSigninBridge; import org.chromium.chrome.browser.tab.Tab; import org.chromium.components.signin.AccountManagerFacadeProvider; import org.chromium.components.signin.AccountUtils; +import org.chromium.components.signin.base.GoogleServiceAuthError; import org.chromium.components.signin.metrics.SigninAccessPoint; import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.UiThreadTaskTraits; @@ -32,12 +34,13 @@ * It is responsible for the sign-in and adding account functions needed for the * web sign-in flow. */ -public class AccountPickerDelegate { +public class AccountPickerDelegate implements WebSigninBridge.Listener { private final WindowAndroid mWindowAndroid; private final ChromeActivity mChromeActivity; private final Tab mTab; private final String mContinueUrl; private final SigninManager mSigninManager; + private WebSigninBridge mWebSigninBridge; public AccountPickerDelegate(WindowAndroid windowAndroid, String continueUrl) { mWindowAndroid = windowAndroid; @@ -52,7 +55,10 @@ * Releases resources used by this class. */ public void onDismiss() { - // TODO(https://crbug.com/1093741): Destroys WebSigninBridge in the delegate + if (mWebSigninBridge != null) { + mWebSigninBridge.destroy(); + mWebSigninBridge = null; + } } /** @@ -111,4 +117,20 @@ * Notifies when the user clicked the "Go incognito mode" button. */ public void goIncognitoMode() {} + + /** + * TODO(https://crbug.com/1092399): Redirect URL when web sign-in succeeded. + * Sign-in completed successfully and the primary account is available in the cookie jar. + */ + @Override + public void onSigninSucceded() {} + + /** + * TODO(https//crbug.com/1114589): Handle web sign-in errors. + * Sign-in process failed. + * + * @param error Details about the error that occurred in the sign-in process. + */ + @Override + public void onSigninFailed(GoogleServiceAuthError error) {} }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityLocationDelegationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityLocationDelegationTest.java index 49d443e..ca2a796 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityLocationDelegationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/browserservices/permissiondelegation/TrustedWebActivityLocationDelegationTest.java
@@ -10,6 +10,7 @@ import static org.chromium.chrome.browser.browserservices.TrustedWebActivityTestUtil.isTrustedWebActivity; import android.net.Uri; +import android.os.Build; import android.os.RemoteException; import android.support.test.filters.MediumTest; @@ -23,6 +24,7 @@ import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.DisableIf; import org.chromium.chrome.browser.browserservices.TrustedWebActivityTestUtil; import org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -107,6 +109,7 @@ @Test @MediumTest + @DisableIf.Build(sdk_is_less_than = Build.VERSION_CODES.M, message = "crbug.com/1115568") public void getLocationFromChrome_noTwaService() throws TimeoutException, Exception { String packageName = "other.package.name"; String testPage = mCustomTabActivityTestRule.getTestServer().getURLWithHostName(
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java new file mode 100644 index 0000000..2c5c0cc --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java
@@ -0,0 +1,140 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.chrome.browser.signin; + +import static androidx.test.espresso.Espresso.onView; +import static androidx.test.espresso.action.ViewActions.click; +import static androidx.test.espresso.matcher.ViewMatchers.withText; + +import static org.mockito.MockitoAnnotations.initMocks; + +import androidx.test.filters.MediumTest; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; + +import org.chromium.base.test.params.ParameterAnnotations; +import org.chromium.base.test.params.ParameterizedRunner; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeActivity; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils; +import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator; +import org.chromium.chrome.browser.signin.account_picker.AccountPickerDelegate; +import org.chromium.chrome.test.ChromeActivityTestRule; +import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; +import org.chromium.components.signin.ProfileDataSource; +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.NightModeTestUtils; +import org.chromium.ui.test.util.RenderTestRule; + +import java.io.IOException; + +/** + * Render tests of account picker bottom sheet. + */ +@RunWith(ParameterizedRunner.class) +@ParameterAnnotations.UseRunnerDelegate(ChromeJUnit4RunnerDelegate.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +@Features.EnableFeatures({ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY}) +public class AccountPickerBottomSheetRenderTest { + private static final ProfileDataSource.ProfileData PROFILE_DATA1 = + new ProfileDataSource.ProfileData( + /* accountName= */ "test.account1@gmail.com", /* avatar= */ null, + /* fullName= */ "Test Account1", /* givenName= */ "Account1"); + private static final ProfileDataSource.ProfileData PROFILE_DATA2 = + new ProfileDataSource.ProfileData( + /* accountName= */ "test.account2@gmail.com", /* avatar= */ null, + /* fullName= */ null, /* givenName= */ null); + + @Rule + public final RenderTestRule mRenderTestRule = RenderTestRule.Builder.withPublicCorpus().build(); + + @Rule + public final AccountManagerTestRule mAccountManagerTestRule = + new AccountManagerTestRule(new FakeProfileDataSource()); + + @Rule + public final ChromeActivityTestRule<ChromeActivity> mActivityTestRule = + new ChromeActivityTestRule<>(ChromeActivity.class); + + @Mock + private AccountPickerDelegate mAccountPickerDelegateMock; + + private AccountPickerBottomSheetCoordinator mCoordinator; + + @ParameterAnnotations.UseMethodParameterBefore(NightModeTestUtils.NightModeParams.class) + public void setupNightMode(boolean nightModeEnabled) { + ChromeNightModeTestUtils.setUpNightModeForChromeActivity(nightModeEnabled); + mRenderTestRule.setNightModeEnabled(nightModeEnabled); + } + + @BeforeClass + public static void setUpBeforeActivityLaunched() { + ChromeNightModeTestUtils.setUpNightModeBeforeChromeActivityLaunched(); + } + + @Before + public void setUp() { + initMocks(this); + mActivityTestRule.startMainActivityOnBlankPage(); + } + + @AfterClass + public static void tearDownAfterActivityDestroyed() { + ChromeNightModeTestUtils.tearDownNightModeAfterChromeActivityDestroyed(); + } + + @Test + @MediumTest + @Feature("RenderTest") + @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) + public void testCollapsedSheetWithAccountView(boolean nightModeEnabled) throws IOException { + mAccountManagerTestRule.addAccount(PROFILE_DATA1); + buildAndShowCollapsedBottomSheet(); + mRenderTestRule.render( + mCoordinator.getBottomSheetViewForTesting(), "collapsed_sheet_with_account"); + } + + @Test + @MediumTest + @Feature("RenderTest") + @ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class) + public void testExpandedSheetView(boolean nightModeEnabled) throws IOException { + mAccountManagerTestRule.addAccount(PROFILE_DATA1); + mAccountManagerTestRule.addAccount(PROFILE_DATA2); + buildAndShowCollapsedBottomSheet(); + onView(withText(PROFILE_DATA1.getFullName())).perform(click()); + mRenderTestRule.render(mCoordinator.getBottomSheetViewForTesting(), "expanded_sheet"); + } + + private void buildAndShowCollapsedBottomSheet() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + mCoordinator = new AccountPickerBottomSheetCoordinator(mActivityTestRule.getActivity(), + getBottomSheetController(), mAccountPickerDelegateMock); + }); + CriteriaHelper.pollUiThread(mCoordinator.getBottomSheetViewForTesting().findViewById( + R.id.account_picker_continue_as_button)::isShown); + } + + private BottomSheetController getBottomSheetController() { + return mActivityTestRule.getActivity() + .getRootUiCoordinatorForTesting() + .getBottomSheetController(); + } +}
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 c53c12f..bb7c71a 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
@@ -41,16 +41,13 @@ import org.chromium.base.Callback; import org.chromium.base.ThreadUtils; import org.chromium.base.test.util.CommandLineFlags; -import org.chromium.base.test.util.Feature; import org.chromium.chrome.R; import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; -import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils; import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator; import org.chromium.chrome.browser.signin.account_picker.AccountPickerDelegate; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -import org.chromium.chrome.test.util.ChromeRenderTestRule; import org.chromium.chrome.test.util.browser.Features; import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; @@ -62,8 +59,6 @@ import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.DisableAnimationsTestRule; -import java.io.IOException; - /** * Tests account picker bottom sheet of the web signin flow. */ @@ -91,10 +86,6 @@ public static final DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); - @Rule - public final ChromeRenderTestRule mRenderTestRule = - ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(0).build(); - @Captor public ArgumentCaptor<Callback<String>> callbackArgumentCaptor; @@ -135,28 +126,6 @@ @Test @MediumTest - @Feature("RenderTest") - public void testCollapsedSheetWithAccountView() throws IOException { - buildAndShowCollapsedBottomSheet(); - mRenderTestRule.render( - mCoordinator.getBottomSheetViewForTesting(), "collapsed_sheet_with_account"); - } - - @Test - @MediumTest - @Feature("RenderTest") - public void testCollapsedSheetWithAccountViewDarkMode() throws IOException { - TestThreadUtils.runOnUiThreadBlocking( - () -> { ChromeNightModeTestUtils.setUpNightModeForChromeActivity(true); }); - mRenderTestRule.setNightModeEnabled(true); - mActivityTestRule.startMainActivityOnBlankPage(); - buildAndShowCollapsedBottomSheet(); - mRenderTestRule.render( - mCoordinator.getBottomSheetViewForTesting(), "collapsed_sheet_with_account_dark"); - } - - @Test - @MediumTest public void testExpandedSheet() { buildAndShowExpandedBottomSheet(); onView(allOf(withText(PROFILE_DATA1.getAccountName()), withEffectiveVisibility(VISIBLE))) @@ -172,14 +141,6 @@ @Test @MediumTest - @Feature("RenderTest") - public void testExpandedSheetView() throws IOException { - buildAndShowExpandedBottomSheet(); - mRenderTestRule.render(mCoordinator.getBottomSheetViewForTesting(), "expanded_sheet"); - } - - @Test - @MediumTest public void testCollapsedSheetWithZeroAccount() { // As we have already added accounts in our current AccountManagerFacade mock // Here since we want to test a zero account case, we would like to set up
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/ChromeBackupAgentTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/ChromeBackupAgentTest.java index acf69607..154bae3 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/ChromeBackupAgentTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/ChromeBackupAgentTest.java
@@ -50,7 +50,6 @@ import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.signin.IdentityServicesProvider; -import org.chromium.components.signin.ChromeSigninController; import org.chromium.components.signin.base.CoreAccountId; import org.chromium.components.signin.base.CoreAccountInfo; import org.chromium.components.signin.identitymanager.ConsentLevel; @@ -185,7 +184,7 @@ verify(backupData).writeEntityData(new byte[] {0}, 1); byte[] unameBytes = ApiCompatibilityUtils.getBytesUtf8(mAccountInfo.getEmail()); verify(backupData) - .writeEntityHeader("AndroidDefault." + ChromeSigninController.SIGNED_IN_ACCOUNT_KEY, + .writeEntityHeader("AndroidDefault." + ChromeBackupAgent.SIGNED_IN_ACCOUNT_KEY, unameBytes.length); verify(backupData).writeEntityData(unameBytes, unameBytes.length); @@ -200,8 +199,7 @@ names, hasItem("AndroidDefault." + ChromePreferenceKeys.FIRST_RUN_FLOW_COMPLETE)); assertThat(names, hasItem("AndroidDefault." + ChromePreferenceKeys.FIRST_RUN_FLOW_SIGNIN_SETUP)); - assertThat( - names, hasItem("AndroidDefault." + ChromeSigninController.SIGNED_IN_ACCOUNT_KEY)); + assertThat(names, hasItem("AndroidDefault." + ChromeBackupAgent.SIGNED_IN_ACCOUNT_KEY)); ArrayList<byte[]> values = (ArrayList<byte[]>) newStateStream.readObject(); assertThat(values.size(), equalTo(4)); assertThat(values, hasItem(unameBytes)); @@ -385,8 +383,7 @@ final String[] keys = {"native.pref1", "native.pref2", "AndroidDefault." + ChromePreferenceKeys.FIRST_RUN_FLOW_COMPLETE, - "AndroidDefault.junk", - "AndroidDefault." + ChromeSigninController.SIGNED_IN_ACCOUNT_KEY}; + "AndroidDefault.junk", "AndroidDefault." + ChromeBackupAgent.SIGNED_IN_ACCOUNT_KEY}; byte[] unameBytes = ApiCompatibilityUtils.getBytesUtf8(mAccountInfo.getEmail()); final byte[][] values = {{0}, {1}, {1}, {23, 42}, unameBytes}; when(backupData.getKey()).thenAnswer(new Answer<String>() {
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 1ad6d5c..973fb02 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4685,6 +4685,12 @@ flag_descriptions::kNewProfilePickerDescription, kOsMac | kOsWin | kOsLinux, FEATURE_VALUE_TYPE(features::kNewProfilePicker)}, + + {"enable-sign-in-profile-creation-flow", + flag_descriptions::kSignInProfileCreationFlowName, + flag_descriptions::kSignInProfileCreationFlowDescription, + kOsMac | kOsWin | kOsLinux, + FEATURE_VALUE_TYPE(features::kSignInProfileCreationFlow)}, #endif #if defined(OS_CHROMEOS)
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 37f56d2..b4f897d 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -1829,6 +1829,8 @@ "net/delay_network_call.h", "net/dhcp_wpad_url_client.cc", "net/dhcp_wpad_url_client.h", + "net/network_diagnostics/captive_portal_routine.cc", + "net/network_diagnostics/captive_portal_routine.h", "net/network_diagnostics/dns_latency_routine.cc", "net/network_diagnostics/dns_latency_routine.h", "net/network_diagnostics/dns_resolution_routine.cc", @@ -3040,6 +3042,8 @@ "attestation/mock_tpm_challenge_key_subtle.cc", "attestation/mock_tpm_challenge_key_subtle.h", "attestation/platform_verification_flow_unittest.cc", + "attestation/tpm_challenge_key_result_unittest.cc", + "attestation/tpm_challenge_key_subtle_unittest.cc", "attestation/tpm_challenge_key_unittest.cc", "authpolicy/authpolicy_credentials_manager_unittest.cc", "authpolicy/authpolicy_helper.unittest.cc", @@ -3267,6 +3271,7 @@ "login/version_updater/version_updater_unittest.cc", "mobile/mobile_activator_unittest.cc", "net/client_cert_store_chromeos_unittest.cc", + "net/network_diagnostics/captive_portal_routine_unittest.cc", "net/network_diagnostics/dns_latency_routine_unittest.cc", "net/network_diagnostics/dns_resolution_routine_unittest.cc", "net/network_diagnostics/dns_resolver_present_routine_unittest.cc",
diff --git a/chrome/browser/chromeos/attestation/tpm_challenge_key.cc b/chrome/browser/chromeos/attestation/tpm_challenge_key.cc index 8df8974..892c34f 100644 --- a/chrome/browser/chromeos/attestation/tpm_challenge_key.cc +++ b/chrome/browser/chromeos/attestation/tpm_challenge_key.cc
@@ -4,26 +4,21 @@ #include "chrome/browser/chromeos/attestation/tpm_challenge_key.h" -#include "base/base64.h" +#include <memory> +#include <string> +#include <utility> + #include "base/bind.h" -#include "base/check_op.h" -#include "base/compiler_specific.h" -#include "base/strings/stringprintf.h" -#include "base/values.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/chromeos/attestation/attestation_ca_client.h" -#include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/extensions/chrome_extension_function_details.h" -#include "chrome/browser/profiles/profile.h" +#include "base/memory/weak_ptr.h" +#include "base/sequence_checker.h" +#include "chrome/browser/chromeos/attestation/tpm_challenge_key_result.h" +#include "chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.h" #include "chrome/common/pref_names.h" -#include "chromeos/cryptohome/async_method_caller.h" -#include "chromeos/cryptohome/cryptohome_parameters.h" -#include "chromeos/settings/cros_settings_names.h" -#include "chromeos/tpm/install_attributes.h" +#include "chromeos/dbus/constants/attestation_constants.h" #include "components/pref_registry/pref_registry_syncable.h" -#include "components/prefs/pref_service.h" + +class Profile; +class AttestationFlow; namespace chromeos { namespace attestation {
diff --git a/chrome/browser/chromeos/attestation/tpm_challenge_key_result.cc b/chrome/browser/chromeos/attestation/tpm_challenge_key_result.cc index de2b6e83..fff8b49 100644 --- a/chrome/browser/chromeos/attestation/tpm_challenge_key_result.cc +++ b/chrome/browser/chromeos/attestation/tpm_challenge_key_result.cc
@@ -6,11 +6,20 @@ #include <ostream> +#include "base/base64.h" #include "base/check_op.h" #include "base/notreached.h" +#include "base/values.h" namespace chromeos { namespace attestation { +namespace { +std::string Base64EncodeStr(const std::string& str) { + std::string result; + base::Base64Encode(str, &result); + return result; +} +} // namespace // These messages are exposed to the extensions that using // chrome.enterprise.platformKeys API. Someone can rely on exectly these @@ -139,5 +148,33 @@ return result_code == TpmChallengeKeyResultCode::kSuccess; } +bool TpmChallengeKeyResult::operator==( + const TpmChallengeKeyResult& other) const { + return ((result_code == other.result_code) && + (public_key == other.public_key) && + (challenge_response == other.challenge_response)); +} + +bool TpmChallengeKeyResult::operator!=( + const TpmChallengeKeyResult& other) const { + return !(*this == other); +} + +std::ostream& operator<<(std::ostream& os, + const TpmChallengeKeyResult& result) { + base::Value value(base::Value::Type::DICTIONARY); + + value.SetIntKey("result_code", static_cast<int>(result.result_code)); + if (!result.IsSuccess()) { + value.SetStringKey("error_message", result.GetErrorMessage()); + } + value.SetStringKey("public_key", Base64EncodeStr(result.public_key)); + value.SetStringKey("challenge_response", + Base64EncodeStr(result.challenge_response)); + + os << value; + return os; +} + } // namespace attestation } // namespace chromeos
diff --git a/chrome/browser/chromeos/attestation/tpm_challenge_key_result.h b/chrome/browser/chromeos/attestation/tpm_challenge_key_result.h index 4c8d5b9..d60b35e6 100644 --- a/chrome/browser/chromeos/attestation/tpm_challenge_key_result.h +++ b/chrome/browser/chromeos/attestation/tpm_challenge_key_result.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_CHROMEOS_ATTESTATION_TPM_CHALLENGE_KEY_RESULT_H_ #define CHROME_BROWSER_CHROMEOS_ATTESTATION_TPM_CHALLENGE_KEY_RESULT_H_ +#include <ostream> #include <string> namespace chromeos { @@ -71,11 +72,17 @@ const char* GetErrorMessage() const; bool IsSuccess() const; + bool operator==(const TpmChallengeKeyResult& other) const; + bool operator!=(const TpmChallengeKeyResult& other) const; + TpmChallengeKeyResultCode result_code = TpmChallengeKeyResultCode::kSuccess; std::string public_key; std::string challenge_response; }; +// For unit tests and debugging. +std::ostream& operator<<(std::ostream& os, const TpmChallengeKeyResult& result); + } // namespace attestation } // namespace chromeos
diff --git a/chrome/browser/chromeos/attestation/tpm_challenge_key_result_unittest.cc b/chrome/browser/chromeos/attestation/tpm_challenge_key_result_unittest.cc new file mode 100644 index 0000000..cecd5965 --- /dev/null +++ b/chrome/browser/chromeos/attestation/tpm_challenge_key_result_unittest.cc
@@ -0,0 +1,90 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/attestation/tpm_challenge_key_result.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace chromeos { +namespace attestation { +namespace { + +std::string GetChallengeResponse() { + constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'r', 'e', + 's', 'p', 0xfd, 0xfe, 0xff}; + return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); +} + +std::string GetPublicKey() { + constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'p', 'u', + 'b', 'k', 0xfd, 0xfe, 0xff}; + return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); +} + +std::string GetPublicKey2() { + constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'p', 'u', 'b', + 'k', '2', 0xfd, 0xfe, 0xff}; + return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); +} + +TEST(TpmChallengeKeyResultTest, MakeChallengeResponse) { + TpmChallengeKeyResult result = + TpmChallengeKeyResult::MakeChallengeResponse(GetChallengeResponse()); + + EXPECT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.result_code, TpmChallengeKeyResultCode::kSuccess); + EXPECT_EQ(result.challenge_response, GetChallengeResponse()); + EXPECT_EQ(result.public_key, ""); +} + +TEST(TpmChallengeKeyResultTest, MakePublicKey) { + TpmChallengeKeyResult result = + TpmChallengeKeyResult::MakePublicKey(GetPublicKey()); + + EXPECT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.result_code, TpmChallengeKeyResultCode::kSuccess); + EXPECT_EQ(result.challenge_response, ""); + EXPECT_EQ(result.public_key, GetPublicKey()); +} + +TEST(TpmChallengeKeyResultTest, MakeSuccess) { + TpmChallengeKeyResult result = TpmChallengeKeyResult::MakeSuccess(); + + EXPECT_TRUE(result.IsSuccess()); + EXPECT_EQ(result.result_code, TpmChallengeKeyResultCode::kSuccess); + EXPECT_EQ(result.challenge_response, ""); + EXPECT_EQ(result.public_key, ""); +} + +TEST(TpmChallengeKeyResultTest, MakeError) { + TpmChallengeKeyResult result = TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kGetPublicKeyFailedError); + + EXPECT_FALSE(result.IsSuccess()); + EXPECT_EQ(result.result_code, + TpmChallengeKeyResultCode::kGetPublicKeyFailedError); + EXPECT_EQ(result.challenge_response, ""); + EXPECT_EQ(result.public_key, ""); + EXPECT_EQ(result.GetErrorMessage(), + TpmChallengeKeyResult::kGetPublicKeyFailedErrorMsg); +} + +TEST(TpmChallengeKeyResultTest, OperatorEqual) { + TpmChallengeKeyResult result1 = + TpmChallengeKeyResult::MakeError(TpmChallengeKeyResultCode::kDbusError); + TpmChallengeKeyResult result2 = + TpmChallengeKeyResult::MakePublicKey(GetPublicKey()); + TpmChallengeKeyResult result3 = + TpmChallengeKeyResult::MakePublicKey(GetPublicKey2()); + + EXPECT_TRUE(result1 == result1); + EXPECT_EQ(result1, TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kDbusError)); + EXPECT_TRUE(result1 != result2); + EXPECT_TRUE(result2 != result3); +} + +} // namespace +} // namespace attestation +} // namespace chromeos
diff --git a/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.cc b/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.cc index 1aeaa05c..6ec6b15 100644 --- a/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.cc +++ b/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.cc
@@ -559,15 +559,5 @@ std::move(callback_).Run(Result::MakeSuccess()); } -void TpmChallengeKeySubtleImpl::RunCallback( - const TpmChallengeKeyResult& result) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!callback_.is_null()); - TpmChallengeKeyCallback local_callback = std::move(callback_); - callback_.Reset(); - std::move(local_callback).Run(result); - // |this| may be destructed after |callback_| is run. -} - } // namespace attestation } // namespace chromeos
diff --git a/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle_unittest.cc b/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle_unittest.cc new file mode 100644 index 0000000..0e1fdbd --- /dev/null +++ b/chrome/browser/chromeos/attestation/tpm_challenge_key_subtle_unittest.cc
@@ -0,0 +1,626 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.h" + +#include "base/bind.h" +#include "base/optional.h" +#include "base/run_loop.h" +#include "base/test/gmock_callback_support.h" +#include "chrome/browser/chromeos/attestation/tpm_challenge_key_result.h" +#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" +#include "chrome/browser/chromeos/profiles/profile_helper.h" +#include "chrome/common/chrome_constants.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "chromeos/attestation/mock_attestation_flow.h" +#include "chromeos/cryptohome/async_method_caller.h" +#include "chromeos/cryptohome/mock_async_method_caller.h" +#include "chromeos/dbus/constants/attestation_constants.h" +#include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" +#include "components/prefs/pref_service.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::test::RunOnceCallback; +using testing::_; +using testing::StrictMock; + +namespace chromeos { +namespace attestation { +namespace { + +constexpr char kTestUserEmail[] = "test@google.com"; +constexpr char kTestUserGaiaId[] = "test_gaia_id"; +constexpr char kEmptyKeyName[] = ""; +constexpr char kNonDefaultKeyName[] = "key_name_123"; + +const char* GetDefaultKeyName(AttestationKeyType type) { + switch (type) { + case KEY_DEVICE: + return kEnterpriseMachineKey; + case KEY_USER: + return kEnterpriseUserKey; + } +} + +std::string GetChallenge() { + constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'c', 'h', + 'a', 'l', 0xfd, 0xfe, 0xff}; + return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); +} + +std::string GetChallengeResponse() { + constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'r', 'e', + 's', 'p', 0xfd, 0xfe, 0xff}; + return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); +} + +std::string GetPublicKey() { + constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'p', 'u', + 'b', 'k', 0xfd, 0xfe, 0xff}; + return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); +} + +class CallbackObserver { + public: + TpmChallengeKeyCallback GetCallback() { + return base::BindOnce(&CallbackObserver::Callback, base::Unretained(this)); + } + + const TpmChallengeKeyResult& GetResult() const { + CHECK(result_.has_value()) << "Callback was never called"; + return result_.value(); + } + + void WaitForCallback() { loop_.Run(); } + + private: + void Callback(const TpmChallengeKeyResult& result) { + CHECK(!result_.has_value()) << "Callback was called more than once"; + result_ = result; + loop_.Quit(); + } + + base::RunLoop loop_; + base::Optional<TpmChallengeKeyResult> result_; +}; + +//================== TpmChallengeKeySubtleTest ================================= + +class TpmChallengeKeySubtleTest : public ::testing::Test { + public: + TpmChallengeKeySubtleTest(); + ~TpmChallengeKeySubtleTest(); + + protected: + void InitSigninProfile(); + void InitUnaffiliatedProfile(); + void InitAffiliatedProfile(); + void SetDefaultSettings(); + + TestingProfile* CreateUserProfile(bool is_affiliated); + TestingProfile* GetProfile(); + chromeos::ScopedCrosSettingsTestHelper* GetCrosSettingsHelper(); + chromeos::StubInstallAttributes* GetInstallAttributes(); + + // Runs StartPrepareKeyStep and checks that the result is equal to + // |public_key|. + void RunOneStepAndExpect(AttestationKeyType key_type, + bool will_register_key, + const std::string& key_name, + const TpmChallengeKeyResult& public_key); + // Runs StartPrepareKeyStep and checks that the result is success. Then runs + // StartSignChallengeStep and checks that the result is equal to + // |challenge_response|. + void RunTwoStepsAndExpect(AttestationKeyType key_type, + bool will_register_key, + const std::string& key_name, + const TpmChallengeKeyResult& challenge_response); + // Runs first two steps and checks that results are success. Then runs + // StartRegisterKeyStep and checks that the result is equal to + // |register_result|. + void RunThreeStepsAndExpect(AttestationKeyType key_type, + bool will_register_key, + const std::string& key_name, + const TpmChallengeKeyResult& register_result); + + content::BrowserTaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + + StrictMock<chromeos::attestation::MockAttestationFlow> mock_attestation_flow_; + cryptohome::MockAsyncMethodCaller* mock_async_method_caller_ = nullptr; + chromeos::FakeCryptohomeClient cryptohome_client_; + + TestingProfileManager testing_profile_manager_; + chromeos::FakeChromeUserManager fake_user_manager_; + TestingProfile* testing_profile_ = nullptr; + + std::unique_ptr<TpmChallengeKeySubtleImpl> challenge_key_subtle_; +}; + +TpmChallengeKeySubtleTest::TpmChallengeKeySubtleTest() + : testing_profile_manager_(TestingBrowserProcess::GetGlobal()) { + CHECK(testing_profile_manager_.SetUp()); + + mock_async_method_caller_ = + new StrictMock<cryptohome::MockAsyncMethodCaller>(); + // Ownership of mock_async_method_caller_ is transferred to + // AsyncMethodCaller::InitializeForTesting. + cryptohome::AsyncMethodCaller::InitializeForTesting( + mock_async_method_caller_); + + challenge_key_subtle_ = + std::make_unique<TpmChallengeKeySubtleImpl>(&mock_attestation_flow_); + + cryptohome_client_.set_tpm_attestation_public_key( + CryptohomeClient::TpmAttestationDataResult{/*success=*/true, + GetPublicKey()}); +} + +TpmChallengeKeySubtleTest::~TpmChallengeKeySubtleTest() { + cryptohome::AsyncMethodCaller::Shutdown(); +} + +void TpmChallengeKeySubtleTest::InitSigninProfile() { + testing_profile_ = + testing_profile_manager_.CreateTestingProfile(chrome::kInitialProfile); + SetDefaultSettings(); +} + +void TpmChallengeKeySubtleTest::InitUnaffiliatedProfile() { + testing_profile_ = CreateUserProfile(/*is_affiliated=*/false); + SetDefaultSettings(); +} + +void TpmChallengeKeySubtleTest::InitAffiliatedProfile() { + testing_profile_ = CreateUserProfile(/*is_affiliated=*/true); + SetDefaultSettings(); + GetProfile()->GetTestingPrefService()->SetManagedPref( + prefs::kAttestationEnabled, std::make_unique<base::Value>(true)); +} + +void TpmChallengeKeySubtleTest::SetDefaultSettings() { + GetInstallAttributes()->SetCloudManaged("google.com", "device_id"); + + GetCrosSettingsHelper()->ReplaceDeviceSettingsProviderWithStub(); + GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled, + true); +} + +TestingProfile* TpmChallengeKeySubtleTest::CreateUserProfile( + bool is_affiliated) { + TestingProfile* testing_profile = + testing_profile_manager_.CreateTestingProfile(kTestUserEmail); + CHECK(testing_profile); + + auto test_account = + AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + fake_user_manager_.AddUserWithAffiliation(test_account, is_affiliated); + + chromeos::ProfileHelper::Get()->SetUserToProfileMappingForTesting( + fake_user_manager_.GetPrimaryUser(), testing_profile); + + return testing_profile; +} + +TestingProfile* TpmChallengeKeySubtleTest::GetProfile() { + return testing_profile_; +} + +chromeos::ScopedCrosSettingsTestHelper* +TpmChallengeKeySubtleTest::GetCrosSettingsHelper() { + return GetProfile()->ScopedCrosSettingsTestHelper(); +} + +chromeos::StubInstallAttributes* +TpmChallengeKeySubtleTest::GetInstallAttributes() { + return GetCrosSettingsHelper()->InstallAttributes(); +} + +void TpmChallengeKeySubtleTest::RunOneStepAndExpect( + AttestationKeyType key_type, + bool will_register_key, + const std::string& key_name, + const TpmChallengeKeyResult& public_key) { + CallbackObserver callback_observer; + challenge_key_subtle_->StartPrepareKeyStep(key_type, will_register_key, + key_name, GetProfile(), + callback_observer.GetCallback()); + callback_observer.WaitForCallback(); + + EXPECT_EQ(callback_observer.GetResult(), public_key); +} + +void TpmChallengeKeySubtleTest::RunTwoStepsAndExpect( + AttestationKeyType key_type, + bool will_register_key, + const std::string& key_name, + const TpmChallengeKeyResult& challenge_response) { + RunOneStepAndExpect(key_type, will_register_key, key_name, + TpmChallengeKeyResult::MakePublicKey(GetPublicKey())); + + CallbackObserver callback_observer; + challenge_key_subtle_->StartSignChallengeStep( + GetChallenge(), callback_observer.GetCallback()); + callback_observer.WaitForCallback(); + + EXPECT_EQ(callback_observer.GetResult(), challenge_response); +} + +void TpmChallengeKeySubtleTest::RunThreeStepsAndExpect( + AttestationKeyType key_type, + bool will_register_key, + const std::string& key_name, + const TpmChallengeKeyResult& register_result) { + RunTwoStepsAndExpect( + key_type, will_register_key, key_name, + TpmChallengeKeyResult::MakeChallengeResponse(GetChallengeResponse())); + + CallbackObserver callback_observer; + challenge_key_subtle_->StartRegisterKeyStep(callback_observer.GetCallback()); + callback_observer.WaitForCallback(); + + EXPECT_EQ(callback_observer.GetResult(), register_result); +} + +//============================================================================== + +TEST_F(TpmChallengeKeySubtleTest, DeviceKeyNonEnterpriseDevice) { + InitSigninProfile(); + + GetInstallAttributes()->SetConsumerOwned(); + + RunOneStepAndExpect( + KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kNonEnterpriseDeviceError)); +} + +TEST_F(TpmChallengeKeySubtleTest, DeviceKeyDeviceAttestationDisabled) { + InitSigninProfile(); + + GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled, + false); + + RunOneStepAndExpect( + KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kDevicePolicyDisabledError)); +} + +TEST_F(TpmChallengeKeySubtleTest, DeviceKeyUserNotManaged) { + InitUnaffiliatedProfile(); + + RunOneStepAndExpect(KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kUserNotManagedError)); +} + +TEST_F(TpmChallengeKeySubtleTest, UserKeyUserKeyNotAvailable) { + InitSigninProfile(); + + RunOneStepAndExpect( + KEY_USER, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kUserKeyNotAvailableError)); +} + +TEST_F(TpmChallengeKeySubtleTest, UserKeyUserPolicyDisabled) { + InitAffiliatedProfile(); + GetProfile()->GetTestingPrefService()->SetManagedPref( + prefs::kAttestationEnabled, std::make_unique<base::Value>(false)); + + RunOneStepAndExpect(KEY_USER, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kUserPolicyDisabledError)); +} + +// Checks that a user should be affiliated with a device +TEST_F(TpmChallengeKeySubtleTest, UserKeyUserNotAffiliated) { + InitUnaffiliatedProfile(); + GetProfile()->GetTestingPrefService()->SetManagedPref( + prefs::kAttestationEnabled, std::make_unique<base::Value>(true)); + + RunOneStepAndExpect(KEY_USER, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kUserNotManagedError)); +} + +TEST_F(TpmChallengeKeySubtleTest, UserKeyDeviceAttestationDisabled) { + InitAffiliatedProfile(); + GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled, + false); + + RunOneStepAndExpect( + KEY_USER, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kDevicePolicyDisabledError)); +} + +TEST_F(TpmChallengeKeySubtleTest, DoesKeyExistDbusFailed) { + InitSigninProfile(); + + cryptohome_client_.set_tpm_attestation_does_key_exist_should_succeed(false); + + RunOneStepAndExpect( + KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError(TpmChallengeKeyResultCode::kDbusError)); +} + +TEST_F(TpmChallengeKeySubtleTest, GetCertificateFailed) { + InitSigninProfile(); + AttestationKeyType key_type = KEY_DEVICE; + + EXPECT_CALL(mock_attestation_flow_, + GetCertificate(_, _, _, _, GetDefaultKeyName(key_type), _)) + .WillOnce(RunOnceCallback<5>( + chromeos::attestation::ATTESTATION_UNSPECIFIED_FAILURE, + /*pem_certificate_chain=*/"")); + + RunOneStepAndExpect( + key_type, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kGetCertificateFailedError)); +} + +TEST_F(TpmChallengeKeySubtleTest, KeyExists) { + InitSigninProfile(); + AttestationKeyType key_type = KEY_DEVICE; + + cryptohome_client_.SetTpmAttestationDeviceCertificate("attest-ent-machine", + std::string()); + // GetCertificate must not be called if the key exists. + EXPECT_CALL(mock_attestation_flow_, + GetCertificate(_, _, _, _, GetDefaultKeyName(key_type), _)) + .Times(0); + + RunOneStepAndExpect(key_type, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakePublicKey(GetPublicKey())); +} + +TEST_F(TpmChallengeKeySubtleTest, AttestationNotPrepared) { + InitSigninProfile(); + + cryptohome_client_.set_tpm_attestation_is_prepared(false); + + RunOneStepAndExpect(KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kResetRequiredError)); +} + +// Test that we get a proper error message in case we don't have a TPM. +TEST_F(TpmChallengeKeySubtleTest, AttestationUnsupported) { + InitSigninProfile(); + + cryptohome_client_.set_tpm_attestation_is_prepared(false); + cryptohome_client_.set_tpm_is_enabled(false); + + RunOneStepAndExpect( + KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kAttestationUnsupportedError)); +} + +TEST_F(TpmChallengeKeySubtleTest, AttestationPreparedDbusFailed) { + InitSigninProfile(); + + cryptohome_client_.SetServiceIsAvailable(false); + + RunOneStepAndExpect( + KEY_DEVICE, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError(TpmChallengeKeyResultCode::kDbusError)); +} + +TEST_F(TpmChallengeKeySubtleTest, DeviceKeyNotRegisteredSuccess) { + InitSigninProfile(); + AttestationKeyType key_type = KEY_DEVICE; + const char* key_name = GetDefaultKeyName(key_type); + + EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _)) + .WillOnce( + RunOnceCallback<5>(chromeos::attestation::ATTESTATION_SUCCESS, + /*pem_certificate_chain=*/"fake_certificate")); + + EXPECT_CALL(*mock_async_method_caller_, + TpmAttestationSignEnterpriseChallenge( + key_type, _, key_name, _, _, + AttestationChallengeOptions::CHALLENGE_OPTION_NONE, + GetChallenge(), kEmptyKeyName, _)) + .WillOnce(RunOnceCallback<8>( + /*success=*/true, /*data=*/GetChallengeResponse())); + + RunTwoStepsAndExpect( + key_type, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeChallengeResponse(GetChallengeResponse())); +} + +TEST_F(TpmChallengeKeySubtleTest, DeviceKeyRegisteredSuccess) { + InitSigninProfile(); + AttestationKeyType key_type = KEY_DEVICE; + const char* key_name = kNonDefaultKeyName; + + EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _)) + .WillOnce( + RunOnceCallback<5>(chromeos::attestation::ATTESTATION_SUCCESS, + /*pem_certificate_chain=*/"fake_certificate")); + + EXPECT_CALL( + *mock_async_method_caller_, + TpmAttestationSignEnterpriseChallenge( + key_type, _, GetDefaultKeyName(key_type), _, _, + AttestationChallengeOptions::CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY, + GetChallenge(), key_name, _)) + .WillOnce(RunOnceCallback<8>( + /*success=*/true, /*data=*/GetChallengeResponse())); + + EXPECT_CALL(*mock_async_method_caller_, + TpmAttestationRegisterKey(key_type, _, key_name, _)) + .WillOnce(RunOnceCallback<3>( + /*success=*/true, cryptohome::MOUNT_ERROR_NONE)); + + RunThreeStepsAndExpect(key_type, /*will_register_key=*/true, key_name, + TpmChallengeKeyResult::MakeSuccess()); +} + +TEST_F(TpmChallengeKeySubtleTest, UserKeyNotRegisteredSuccess) { + InitAffiliatedProfile(); + + AttestationKeyType key_type = KEY_USER; + const char* key_name = GetDefaultKeyName(key_type); + + EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _)) + .WillOnce( + RunOnceCallback<5>(chromeos::attestation::ATTESTATION_SUCCESS, + /*pem_certificate_chain=*/"fake_certificate")); + + EXPECT_CALL(*mock_async_method_caller_, + TpmAttestationSignEnterpriseChallenge( + key_type, _, key_name, _, _, + AttestationChallengeOptions::CHALLENGE_OPTION_NONE, + GetChallenge(), kEmptyKeyName, _)) + .WillOnce(RunOnceCallback<8>( + /*success=*/true, /*data=*/GetChallengeResponse())); + + RunTwoStepsAndExpect( + key_type, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeChallengeResponse(GetChallengeResponse())); +} + +TEST_F(TpmChallengeKeySubtleTest, UserKeyRegisteredSuccess) { + InitAffiliatedProfile(); + + AttestationKeyType key_type = KEY_USER; + const char* key_name = kNonDefaultKeyName; + + EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _)) + .WillOnce( + RunOnceCallback<5>(chromeos::attestation::ATTESTATION_SUCCESS, + /*pem_certificate_chain=*/"fake_certificate")); + + EXPECT_CALL( + *mock_async_method_caller_, + TpmAttestationSignEnterpriseChallenge( + key_type, _, key_name, _, _, + AttestationChallengeOptions::CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY, + GetChallenge(), kEmptyKeyName, _)) + .WillOnce(RunOnceCallback<8>( + /*success=*/true, /*data=*/GetChallengeResponse())); + + EXPECT_CALL(*mock_async_method_caller_, + TpmAttestationRegisterKey(key_type, _, key_name, _)) + .WillOnce(RunOnceCallback<3>( + /*success=*/true, cryptohome::MOUNT_ERROR_NONE)); + + RunThreeStepsAndExpect(key_type, /*will_register_key=*/true, key_name, + TpmChallengeKeyResult::MakeSuccess()); +} + +TEST_F(TpmChallengeKeySubtleTest, SignChallengeFailed) { + InitSigninProfile(); + AttestationKeyType key_type = KEY_DEVICE; + + EXPECT_CALL(mock_attestation_flow_, + GetCertificate(_, _, _, _, GetDefaultKeyName(key_type), _)) + .WillOnce( + RunOnceCallback<5>(chromeos::attestation::ATTESTATION_SUCCESS, + /*pem_certificate_chain=*/"fake_certificate")); + + EXPECT_CALL(*mock_async_method_caller_, TpmAttestationSignEnterpriseChallenge) + .WillOnce(RunOnceCallback<8>( + /*success=*/false, /*data=*/"")); + RunTwoStepsAndExpect( + key_type, /*will_register_key=*/false, kEmptyKeyName, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kSignChallengeFailedError)); +} + +TEST_F(TpmChallengeKeySubtleTest, RestorePreparedKeyState) { + InitAffiliatedProfile(); + AttestationKeyType key_type = KEY_USER; + const char* key_name = kNonDefaultKeyName; + + std::unique_ptr<TpmChallengeKeySubtle> challenge_key_subtle = + TpmChallengeKeySubtleFactory::CreateForPreparedKey( + key_type, /*will_register_key=*/true, key_name, GetProfile()); + + EXPECT_CALL( + *mock_async_method_caller_, + TpmAttestationSignEnterpriseChallenge( + key_type, _, key_name, _, _, + AttestationChallengeOptions::CHALLENGE_INCLUDE_SIGNED_PUBLIC_KEY, + GetChallenge(), kEmptyKeyName, _)) + .WillOnce(RunOnceCallback<8>( + /*success=*/true, /*data=*/GetChallengeResponse())); + + { + CallbackObserver callback_observer; + challenge_key_subtle->StartSignChallengeStep( + GetChallenge(), callback_observer.GetCallback()); + callback_observer.WaitForCallback(); + + EXPECT_EQ( + callback_observer.GetResult(), + TpmChallengeKeyResult::MakeChallengeResponse(GetChallengeResponse())); + } + + EXPECT_CALL(*mock_async_method_caller_, + TpmAttestationRegisterKey(key_type, _, key_name, _)) + .WillOnce(RunOnceCallback<3>( + /*success=*/true, cryptohome::MOUNT_ERROR_NONE)); + + { + CallbackObserver callback_observer; + challenge_key_subtle->StartRegisterKeyStep(callback_observer.GetCallback()); + callback_observer.WaitForCallback(); + + EXPECT_EQ(callback_observer.GetResult(), + TpmChallengeKeyResult::MakeSuccess()); + } +} + +TEST_F(TpmChallengeKeySubtleTest, KeyRegistrationFailed) { + InitAffiliatedProfile(); + AttestationKeyType key_type = KEY_USER; + const char* key_name = kNonDefaultKeyName; + + std::unique_ptr<TpmChallengeKeySubtle> challenge_key_subtle = + TpmChallengeKeySubtleFactory::CreateForPreparedKey( + key_type, /*will_register_key=*/true, key_name, GetProfile()); + + EXPECT_CALL(*mock_async_method_caller_, TpmAttestationRegisterKey) + .WillOnce( + RunOnceCallback<3>(/*success=*/false, cryptohome::MOUNT_ERROR_NONE)); + + CallbackObserver callback_observer; + challenge_key_subtle->StartRegisterKeyStep(callback_observer.GetCallback()); + callback_observer.WaitForCallback(); + + EXPECT_EQ(callback_observer.GetResult(), + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kKeyRegistrationFailedError)); +} + +TEST_F(TpmChallengeKeySubtleTest, GetPublicKeyFailed) { + InitAffiliatedProfile(); + const char* key_name = kNonDefaultKeyName; + + cryptohome_client_.set_tpm_attestation_public_key(base::nullopt); + + EXPECT_CALL(mock_attestation_flow_, GetCertificate(_, _, _, _, key_name, _)) + .WillOnce( + RunOnceCallback<5>(chromeos::attestation::ATTESTATION_SUCCESS, + /*pem_certificate_chain=*/"fake_certificate")); + + RunOneStepAndExpect(KEY_DEVICE, /*will_register_key=*/true, key_name, + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kGetPublicKeyFailedError)); +} + +} // namespace +} // namespace attestation +} // namespace chromeos
diff --git a/chrome/browser/chromeos/attestation/tpm_challenge_key_unittest.cc b/chrome/browser/chromeos/attestation/tpm_challenge_key_unittest.cc index ff4ebae8..37d5363 100644 --- a/chrome/browser/chromeos/attestation/tpm_challenge_key_unittest.cc +++ b/chrome/browser/chromeos/attestation/tpm_challenge_key_unittest.cc
@@ -4,944 +4,235 @@ #include "chrome/browser/chromeos/attestation/tpm_challenge_key.h" -#include <mutex> -#include <string> -#include <utility> - #include "base/bind.h" -#include "base/location.h" -#include "base/memory/ptr_util.h" -#include "base/strings/stringprintf.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/values.h" -#include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h" -#include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/chromeos/settings/cros_settings.h" -#include "chrome/browser/chromeos/settings/scoped_cros_settings_test_helper.h" -#include "chrome/browser/extensions/extension_function_test_utils.h" -#include "chrome/browser/signin/identity_manager_factory.h" -#include "chrome/browser/ui/browser.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/pref_names.h" -#include "chrome/test/base/browser_with_test_window_test.h" -#include "chrome/test/base/testing_browser_process.h" -#include "chrome/test/base/testing_profile_manager.h" -#include "chromeos/attestation/mock_attestation_flow.h" -#include "chromeos/cryptohome/async_method_caller.h" -#include "chromeos/cryptohome/cryptohome_parameters.h" -#include "chromeos/cryptohome/mock_async_method_caller.h" -#include "chromeos/dbus/constants/attestation_constants.h" -#include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" -#include "chromeos/tpm/stub_install_attributes.h" -#include "components/account_id/account_id.h" -#include "components/policy/core/common/cloud/cloud_policy_constants.h" -#include "components/prefs/pref_service.h" -#include "components/signin/public/identity_manager/identity_manager.h" -#include "components/signin/public/identity_manager/identity_test_utils.h" -#include "components/sync_preferences/testing_pref_service_syncable.h" -#include "components/user_manager/scoped_user_manager.h" -#include "extensions/common/extension_builder.h" -#include "testing/gmock/include/gmock/gmock.h" +#include "base/run_loop.h" +#include "base/test/gmock_callback_support.h" +#include "chrome/browser/chromeos/attestation/mock_tpm_challenge_key_subtle.h" +#include "chrome/browser/chromeos/attestation/tpm_challenge_key_result.h" +#include "chrome/browser/chromeos/attestation/tpm_challenge_key_subtle.h" +#include "chrome/test/base/testing_profile.h" +#include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/cros_system_api/dbus/service_constants.h" +using base::test::RunOnceCallback; using testing::_; -using testing::Invoke; -using testing::NiceMock; -using testing::Return; -using testing::WithArgs; +using testing::StrictMock; -namespace utils = extension_function_test_utils; +class Profile; namespace chromeos { namespace attestation { - namespace { -const char kUserEmail[] = "test@google.com"; -const char kChallenge[] = "challenge"; -const char kResponse[] = "response"; -const char kPublicKey[] = "fake_public_key_for_test"; -const char kKeyNameForSpkac[] = "attest-ent-machine-123456"; -const char kNonDefaultKeyName[] = "fake_key_name_1"; +constexpr char kEmptyKeyName[] = ""; +constexpr char kNonDefaultKeyName[] = "key_name_123"; -void RegisterKeyCallbackTrue(chromeos::attestation::AttestationKeyType key_type, - const cryptohome::Identification& user_id, - const std::string& key_name, - cryptohome::AsyncMethodCaller::Callback callback) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), true, cryptohome::MOUNT_ERROR_NONE)); +std::string GetChallenge() { + constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'c', 'h', + 'a', 'l', 0xfd, 0xfe, 0xff}; + return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); } -void RegisterKeyCallbackFalse( - chromeos::attestation::AttestationKeyType key_type, - const cryptohome::Identification& user_id, - const std::string& key_name, - cryptohome::AsyncMethodCaller::Callback callback) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), false, cryptohome::MOUNT_ERROR_NONE)); +std::string GetChallengeResponse() { + constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'r', 'e', + 's', 'p', 0xfd, 0xfe, 0xff}; + return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); } -void SignChallengeCallbackTrue( - chromeos::attestation::AttestationKeyType key_type, - const cryptohome::Identification& user_id, - const std::string& key_name, - const std::string& domain, - const std::string& device_id, - chromeos::attestation::AttestationChallengeOptions options, - const std::string& challenge, - const std::string& key_name_for_spkac, - cryptohome::AsyncMethodCaller::DataCallback callback) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), true, "response")); +std::string GetPublicKey() { + constexpr uint8_t kBuffer[] = {0x0, 0x1, 0x2, 'p', 'u', + 'b', 'k', 0xfd, 0xfe, 0xff}; + return std::string(reinterpret_cast<const char*>(kBuffer), sizeof(kBuffer)); } -void SignChallengeCallbackFalse( - chromeos::attestation::AttestationKeyType key_type, - const cryptohome::Identification& user_id, - const std::string& key_name, - const std::string& domain, - const std::string& device_id, - chromeos::attestation::AttestationChallengeOptions options, - const std::string& challenge, - const std::string& key_name_for_spkac, - cryptohome::AsyncMethodCaller::DataCallback callback) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), false, "")); -} - -void GetCertificateCallbackTrue( - chromeos::attestation::AttestationCertificateProfile certificate_profile, - const AccountId& account_id, - const std::string& request_origin, - bool force_new_key, - const std::string& key_name, - chromeos::attestation::AttestationFlow::CertificateCallback callback) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(std::move(callback), - chromeos::attestation::ATTESTATION_SUCCESS, - "certificate")); -} - -void GetCertificateCallbackUnspecifiedFailure( - chromeos::attestation::AttestationCertificateProfile certificate_profile, - const AccountId& account_id, - const std::string& request_origin, - bool force_new_key, - const std::string& key_name, - chromeos::attestation::AttestationFlow::CertificateCallback callback) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(std::move(callback), - chromeos::attestation::ATTESTATION_UNSPECIFIED_FAILURE, - "")); -} - -void GetCertificateCallbackBadRequestFailure( - chromeos::attestation::AttestationCertificateProfile certificate_profile, - const AccountId& account_id, - const std::string& request_origin, - bool force_new_key, - const std::string& key_name, - chromeos::attestation::AttestationFlow::CertificateCallback callback) { - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce( - std::move(callback), - chromeos::attestation::ATTESTATION_SERVER_BAD_REQUEST_FAILURE, "")); -} - -class TpmChallengeKeyTestBase : public BrowserWithTestWindowTest { +class TpmChallengeKeyTest : public ::testing::Test { public: - enum class ProfileType { kUserProfile, kSigninProfile }; - - protected: - TpmChallengeKeyTestBase(ProfileType profile_type, - chromeos::attestation::AttestationKeyType key_type) - : profile_type_(profile_type), - fake_user_manager_(new chromeos::FakeChromeUserManager()), - user_manager_enabler_(base::WrapUnique(fake_user_manager_)), - key_type_(key_type) { - mock_async_method_caller_ = - new NiceMock<cryptohome::MockAsyncMethodCaller>(); - // Ownership of mock_async_method_caller_ is transferred to - // AsyncMethodCaller::InitializeForTesting. - cryptohome::AsyncMethodCaller::InitializeForTesting( - mock_async_method_caller_); - - // Set up the default behavior of mocks. - ON_CALL(*mock_async_method_caller_, TpmAttestationRegisterKey) - .WillByDefault(Invoke(RegisterKeyCallbackTrue)); - ON_CALL(*mock_async_method_caller_, TpmAttestationSignEnterpriseChallenge) - .WillByDefault(Invoke(SignChallengeCallbackTrue)); - ON_CALL(mock_attestation_flow_, GetCertificate) - .WillByDefault(Invoke(GetCertificateCallbackTrue)); - ON_CALL(mock_attestation_flow_, GetCertificate) - .WillByDefault(Invoke(GetCertificateCallbackTrue)); - - GetInstallAttributes()->SetCloudManaged("google.com", "device_id"); - - GetCrosSettingsHelper()->ReplaceDeviceSettingsProviderWithStub(); - GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled, - true); - - cryptohome_client_.set_tpm_attestation_public_key( - CryptohomeClient::TpmAttestationDataResult{true, kPublicKey}); - } - - ~TpmChallengeKeyTestBase() { cryptohome::AsyncMethodCaller::Shutdown(); } - - void SetUp() override { - BrowserWithTestWindowTest::SetUp(); - if (profile_type_ == ProfileType::kUserProfile) { - prefs_ = GetProfile()->GetPrefs(); - SetAuthenticatedUser(); - } - } - - void TearDown() override { BrowserWithTestWindowTest::TearDown(); } - - // This will be called by BrowserWithTestWindowTest::SetUp(); - TestingProfile* CreateProfile() override { - switch (profile_type_) { - case ProfileType::kUserProfile: - fake_user_manager_->AddUserWithAffiliation( - AccountId::FromUserEmail(kUserEmail), true); - return profile_manager()->CreateTestingProfile(kUserEmail); - - case ProfileType::kSigninProfile: - return profile_manager()->CreateTestingProfile(chrome::kInitialProfile); - } - NOTREACHED() << "Invalid profile type: " << static_cast<int>(profile_type_); - } - - // Derived classes can override this method to set the required authenticated - // user in the IdentityManager class. - virtual void SetAuthenticatedUser() { - auto* identity_manager = - IdentityManagerFactory::GetForProfile(GetProfile()); - signin::MakePrimaryAccountAvailable(identity_manager, kUserEmail); - } - - void RunBuildResponse(const std::string& challenge, - bool register_key, - const std::string& key_name, - TpmChallengeKeyResult* res) { - auto callback = [](base::OnceClosure done_closure, - TpmChallengeKeyResult* res, - const TpmChallengeKeyResult& tpm_result) { - *res = tpm_result; - std::move(done_closure).Run(); - }; - + TpmChallengeKeyTest() { + auto mock_challenge_key_subtle = + std::make_unique<StrictMock<MockTpmChallengeKeySubtle>>(); + mock_tpm_challenge_key_subtle_ = mock_challenge_key_subtle.get(); TpmChallengeKeySubtleFactory::SetForTesting( - std::make_unique<TpmChallengeKeySubtleImpl>(&mock_attestation_flow_)); + std::move(mock_challenge_key_subtle)); - challenge_key_impl_ = TpmChallengeKeyFactory::Create(); - - base::RunLoop loop; - challenge_key_impl_->BuildResponse( - key_type_, GetProfile(), - base::BindOnce(callback, loop.QuitClosure(), res), challenge, - register_key, key_name); - loop.Run(); + challenge_key_ = TpmChallengeKeyFactory::Create(); } - void RunMultistepFlow(const std::string& challenge, - bool register_key, - const std::string& key_name, - TpmChallengeKeyResult* public_key_res, - TpmChallengeKeyResult* challenge_response_res, - TpmChallengeKeyResult* register_key_res) { - auto callback = [](base::OnceClosure done_closure, - TpmChallengeKeyResult* res, - const TpmChallengeKeyResult& tpm_result) { - *res = tpm_result; - std::move(done_closure).Run(); - }; - - TpmChallengeKeySubtleFactory::SetForTesting( - std::make_unique<TpmChallengeKeySubtleImpl>(&mock_attestation_flow_)); - - challenge_key_subtle_impl_ = TpmChallengeKeySubtleFactory::Create(); - - // Prepare key. - { - base::RunLoop loop; - challenge_key_subtle_impl_->StartPrepareKeyStep( - key_type_, /*will_register_key=*/register_key, key_name, GetProfile(), - base::BindOnce(callback, loop.QuitClosure(), public_key_res)); - loop.Run(); - } - - TpmChallengeKeySubtleFactory::SetForTesting( - std::make_unique<TpmChallengeKeySubtleImpl>(&mock_attestation_flow_)); - - // Destroy existing object and create a new one. - challenge_key_subtle_impl_ = - TpmChallengeKeySubtleFactory::CreateForPreparedKey( - key_type_, /*will_register_key=*/register_key, key_name, - GetProfile()); - - // Continue building challenge response. - { - base::RunLoop loop; - challenge_key_subtle_impl_->StartSignChallengeStep( - challenge, - base::BindOnce(callback, loop.QuitClosure(), challenge_response_res)); - loop.Run(); - } - - if (!register_key) { - return; - } - - TpmChallengeKeySubtleFactory::SetForTesting( - std::make_unique<TpmChallengeKeySubtleImpl>(&mock_attestation_flow_)); - - // Destroy existing object and create a new one. - challenge_key_subtle_impl_ = - TpmChallengeKeySubtleFactory::CreateForPreparedKey( - key_type_, /*will_register_key=*/register_key, key_name, - GetProfile()); - - // Register key. - { - base::RunLoop loop; - challenge_key_subtle_impl_->StartRegisterKeyStep( - base::BindOnce(callback, loop.QuitClosure(), register_key_res)); - loop.Run(); - } - } - - chromeos::FakeCryptohomeClient cryptohome_client_; - cryptohome::MockAsyncMethodCaller* mock_async_method_caller_ = nullptr; - NiceMock<chromeos::attestation::MockAttestationFlow> mock_attestation_flow_; - ProfileType profile_type_; - // fake_user_manager_ is owned by user_manager_enabler_. - chromeos::FakeChromeUserManager* fake_user_manager_; - user_manager::ScopedUserManager user_manager_enabler_; - PrefService* prefs_ = nullptr; - std::unique_ptr<TpmChallengeKey> challenge_key_impl_; - std::unique_ptr<TpmChallengeKeySubtle> challenge_key_subtle_impl_; - chromeos::attestation::AttestationKeyType key_type_; -}; - -class TpmChallengeMachineKeyTest : public TpmChallengeKeyTestBase { protected: - explicit TpmChallengeMachineKeyTest( - ProfileType profile_type = ProfileType::kUserProfile) - : TpmChallengeKeyTestBase(profile_type, - chromeos::attestation::KEY_DEVICE) {} + content::BrowserTaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + + MockTpmChallengeKeySubtle* mock_tpm_challenge_key_subtle_ = nullptr; + std::unique_ptr<TpmChallengeKey> challenge_key_; + // In the current implementation of TpmChallengeKey the profile is just + // forwarded, so actual value does not matter. + TestingProfile profile_; }; -TEST_F(TpmChallengeMachineKeyTest, NonEnterpriseDevice) { - GetInstallAttributes()->SetConsumerOwned(); +class CallbackObserver { + public: + TpmChallengeKeyCallback GetCallback() { + return base::BindOnce(&CallbackObserver::Callback, base::Unretained(this)); + } - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); + const TpmChallengeKeyResult& GetResult() const { + CHECK(result_.has_value()) << "Callback was never called"; + return result_.value(); + } - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kNonEnterpriseDeviceErrorMsg, - res.GetErrorMessage()); -} + void WaitForCallback() { loop_.Run(); } -TEST_F(TpmChallengeMachineKeyTest, DevicePolicyDisabled) { - GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled, - false); + private: + void Callback(const TpmChallengeKeyResult& result) { + CHECK(!result_.has_value()) << "Callback was called more than once"; + result_ = result; + loop_.Quit(); + } - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kDevicePolicyDisabledErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeMachineKeyTest, DoesKeyExistDbusFailed) { - cryptohome_client_.set_tpm_attestation_does_key_exist_should_succeed(false); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kDbusErrorMsg, res.GetErrorMessage()); -} - -TEST_F(TpmChallengeMachineKeyTest, GetCertificateFailed) { - EXPECT_CALL(mock_attestation_flow_, GetCertificate) - .WillRepeatedly(Invoke(GetCertificateCallbackUnspecifiedFailure)); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kGetCertificateFailedErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeMachineKeyTest, SignChallengeFailed) { - EXPECT_CALL(*mock_async_method_caller_, TpmAttestationSignEnterpriseChallenge) - .WillRepeatedly(Invoke(SignChallengeCallbackFalse)); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kSignChallengeFailedErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeMachineKeyTest, KeyExists) { - cryptohome_client_.SetTpmAttestationDeviceCertificate("attest-ent-machine", - std::string()); - // GetCertificate must not be called if the key exists. - EXPECT_CALL(mock_attestation_flow_, GetCertificate).Times(0); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_TRUE(res.IsSuccess()); - EXPECT_EQ(kResponse, res.challenge_response); -} - -TEST_F(TpmChallengeMachineKeyTest, AttestationNotPrepared) { - cryptohome_client_.set_tpm_attestation_is_prepared(false); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kResetRequiredErrorMsg, - res.GetErrorMessage()); -} - -// Test that we get proper error message in case we don't have TPM. -TEST_F(TpmChallengeMachineKeyTest, AttestationUnsupported) { - cryptohome_client_.set_tpm_attestation_is_prepared(false); - cryptohome_client_.set_tpm_is_enabled(false); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kAttestationUnsupportedErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeMachineKeyTest, AttestationPreparedDbusFailed) { - cryptohome_client_.SetServiceIsAvailable(false); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kDbusErrorMsg, res.GetErrorMessage()); -} - -TEST_F(TpmChallengeMachineKeyTest, KeyRegistrationFailed) { - EXPECT_CALL(*mock_async_method_caller_, TpmAttestationRegisterKey) - .WillRepeatedly(Invoke(RegisterKeyCallbackFalse)); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, kKeyNameForSpkac, &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kKeyRegistrationFailedErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeMachineKeyTest, KeyNotRegisteredSuccess) { - EXPECT_CALL(*mock_async_method_caller_, TpmAttestationRegisterKey).Times(0); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_TRUE(res.IsSuccess()); - EXPECT_EQ(kResponse, res.challenge_response); -} - -TEST_F(TpmChallengeMachineKeyTest, KeyRegisteredSuccess) { - // GetCertificate must be called exactly once. - EXPECT_CALL(mock_attestation_flow_, - GetCertificate( - chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, - _, _, _, _, _)) - .Times(1); - // TpmAttestationRegisterKey must be called exactly once. - EXPECT_CALL(*mock_async_method_caller_, - TpmAttestationRegisterKey(chromeos::attestation::KEY_DEVICE, - _ /* Unused by the API. */, - kKeyNameForSpkac, _)) - .Times(1); - // SignEnterpriseChallenge must be called exactly once. - EXPECT_CALL( - *mock_async_method_caller_, - TpmAttestationSignEnterpriseChallenge( - chromeos::attestation::KEY_DEVICE, _, "attest-ent-machine", - "google.com", "device_id", _, "challenge", kKeyNameForSpkac, _)) - .Times(1); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, kKeyNameForSpkac, &res); - - EXPECT_TRUE(res.IsSuccess()); - EXPECT_EQ(kResponse, res.challenge_response); -} - -// Tests the API with all profiles types as determined by the test parameter. -class TpmChallengeMachineKeyAllProfilesTest - : public TpmChallengeMachineKeyTest, - public ::testing::WithParamInterface< - TpmChallengeKeyTestBase::ProfileType> { - protected: - TpmChallengeMachineKeyAllProfilesTest() - : TpmChallengeMachineKeyTest(GetParam()) {} + base::RunLoop loop_; + base::Optional<TpmChallengeKeyResult> result_; }; -TEST_P(TpmChallengeMachineKeyAllProfilesTest, DontRegisterKeySuccess) { - // GetCertificate must be called exactly once. - EXPECT_CALL(mock_attestation_flow_, - GetCertificate( - chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, - _, _, _, _, _)) - .Times(1); - // SignEnterpriseChallenge must be called exactly once. - EXPECT_CALL(*mock_async_method_caller_, - TpmAttestationSignEnterpriseChallenge( - chromeos::attestation::KEY_DEVICE, _, "attest-ent-machine", - "google.com", "device_id", _, "challenge", - /*key_name_for_spkac=*/"", _)) - .Times(1); +TEST_F(TpmChallengeKeyTest, PrepareKeyFailed) { + const AttestationKeyType kKeyType = KEY_DEVICE; + const bool kRegisterKey = false; + const char* const kKeyName = kEmptyKeyName; - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartPrepareKeyStep(kKeyType, kRegisterKey, kKeyName, &profile_, + /*callback=*/_)) + .WillOnce(RunOnceCallback<4>(TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kGetCertificateFailedError))); - EXPECT_TRUE(res.IsSuccess()); - EXPECT_EQ(kResponse, res.challenge_response); + CallbackObserver callback_observer; + challenge_key_->BuildResponse(kKeyType, &profile_, + callback_observer.GetCallback(), GetChallenge(), + kRegisterKey, kKeyName); + callback_observer.WaitForCallback(); + + EXPECT_EQ(callback_observer.GetResult(), + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kGetCertificateFailedError)); } -TEST_P(TpmChallengeMachineKeyAllProfilesTest, RegisterSuccess) { - // GetCertificate must be called exactly once. - EXPECT_CALL(mock_attestation_flow_, - GetCertificate( - chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, - _, _, _, _, _)) - .Times(1); - // SignEnterpriseChallenge must be called exactly once. - EXPECT_CALL(*mock_async_method_caller_, - TpmAttestationSignEnterpriseChallenge( - chromeos::attestation::KEY_DEVICE, _, "attest-ent-machine", - "google.com", "device_id", _, "challenge", - /*key_name_for_spkac=*/kNonDefaultKeyName, _)) - .Times(1); +TEST_F(TpmChallengeKeyTest, SignChallengeFailed) { + const AttestationKeyType kKeyType = KEY_USER; + const bool kRegisterKey = true; + const char* const kKeyName = kNonDefaultKeyName; - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, - /*key_name=*/kNonDefaultKeyName, &res); + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartPrepareKeyStep(kKeyType, kRegisterKey, kKeyName, &profile_, + /*callback=*/_)) + .WillOnce(RunOnceCallback<4>( + TpmChallengeKeyResult::MakePublicKey(GetPublicKey()))); - EXPECT_TRUE(res.IsSuccess()); - EXPECT_EQ(kResponse, res.challenge_response); + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartSignChallengeStep(GetChallenge(), /*callback=*/_)) + .WillOnce(RunOnceCallback<1>(TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kSignChallengeFailedError))); + + CallbackObserver callback_observer; + challenge_key_->BuildResponse(kKeyType, &profile_, + callback_observer.GetCallback(), GetChallenge(), + kRegisterKey, kKeyName); + callback_observer.WaitForCallback(); + + EXPECT_EQ(callback_observer.GetResult(), + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kSignChallengeFailedError)); } -TEST_P(TpmChallengeMachineKeyAllProfilesTest, DontRegisterKeyMultistepSuccess) { - // GetCertificate must be called exactly once. - EXPECT_CALL(mock_attestation_flow_, - GetCertificate( - chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, - _, _, _, _, _)) - .Times(1); - // SignEnterpriseChallenge must be called exactly once. - EXPECT_CALL(*mock_async_method_caller_, - TpmAttestationSignEnterpriseChallenge( - chromeos::attestation::KEY_DEVICE, _, "attest-ent-machine", - "google.com", "device_id", _, "challenge", - /*key_name_for_spkac=*/"", _)) - .Times(1); +TEST_F(TpmChallengeKeyTest, RegisterKeyFailed) { + const AttestationKeyType kKeyType = KEY_USER; + const bool kRegisterKey = true; + const char* const kKeyName = kNonDefaultKeyName; - TpmChallengeKeyResult public_key_res; - TpmChallengeKeyResult challenge_response_res; - TpmChallengeKeyResult register_key_res; - RunMultistepFlow(kChallenge, /*register_key=*/false, - /*key_name=*/"", &public_key_res, &challenge_response_res, - ®ister_key_res); + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartPrepareKeyStep(kKeyType, kRegisterKey, kKeyName, &profile_, + /*callback=*/_)) + .WillOnce(RunOnceCallback<4>( + TpmChallengeKeyResult::MakePublicKey(GetPublicKey()))); - EXPECT_TRUE(public_key_res.IsSuccess()); - EXPECT_EQ(kPublicKey, public_key_res.public_key); - EXPECT_TRUE(challenge_response_res.IsSuccess()); - EXPECT_EQ(kResponse, challenge_response_res.challenge_response); - EXPECT_TRUE(register_key_res.IsSuccess()); + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartSignChallengeStep(GetChallenge(), /*callback=*/_)) + .WillOnce(RunOnceCallback<1>(TpmChallengeKeyResult::MakeChallengeResponse( + GetChallengeResponse()))); + + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartRegisterKeyStep(/*callback=*/_)) + .WillOnce(RunOnceCallback<0>(TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kKeyRegistrationFailedError))); + + CallbackObserver callback_observer; + challenge_key_->BuildResponse(kKeyType, &profile_, + callback_observer.GetCallback(), GetChallenge(), + kRegisterKey, kKeyName); + callback_observer.WaitForCallback(); + + EXPECT_EQ(callback_observer.GetResult(), + TpmChallengeKeyResult::MakeError( + TpmChallengeKeyResultCode::kKeyRegistrationFailedError)); } -TEST_P(TpmChallengeMachineKeyAllProfilesTest, RegisterKeyMultistepSuccess) { - // GetCertificate must be called exactly once. - EXPECT_CALL(mock_attestation_flow_, - GetCertificate( - chromeos::attestation::PROFILE_ENTERPRISE_MACHINE_CERTIFICATE, - _, _, _, _, _)) - .Times(1); - // SignEnterpriseChallenge must be called exactly once. - EXPECT_CALL(*mock_async_method_caller_, - TpmAttestationSignEnterpriseChallenge( - chromeos::attestation::KEY_DEVICE, _, "attest-ent-machine", - "google.com", "device_id", _, "challenge", - /*key_name_for_spkac=*/kNonDefaultKeyName, _)) - .Times(1); +TEST_F(TpmChallengeKeyTest, DontRegisterSuccess) { + const AttestationKeyType kKeyType = KEY_USER; + const bool kRegisterKey = false; + const char* const kKeyName = kEmptyKeyName; - TpmChallengeKeyResult public_key_res; - TpmChallengeKeyResult challenge_response_res; - TpmChallengeKeyResult register_key_res; - RunMultistepFlow(kChallenge, /*register_key=*/true, - /*key_name=*/kNonDefaultKeyName, &public_key_res, - &challenge_response_res, ®ister_key_res); + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartPrepareKeyStep(kKeyType, kRegisterKey, kKeyName, &profile_, + /*callback=*/_)) + .WillOnce(RunOnceCallback<4>( + TpmChallengeKeyResult::MakePublicKey(GetPublicKey()))); - EXPECT_TRUE(public_key_res.IsSuccess()); - EXPECT_EQ(kPublicKey, public_key_res.public_key); - EXPECT_TRUE(challenge_response_res.IsSuccess()); - EXPECT_EQ(kResponse, challenge_response_res.challenge_response); - EXPECT_TRUE(register_key_res.IsSuccess()); + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartSignChallengeStep(GetChallenge(), /*callback=*/_)) + .WillOnce(RunOnceCallback<1>(TpmChallengeKeyResult::MakeChallengeResponse( + GetChallengeResponse()))); + + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartRegisterKeyStep(/*callback=*/_)) + .Times(0); + + CallbackObserver callback_observer; + challenge_key_->BuildResponse(kKeyType, &profile_, + callback_observer.GetCallback(), GetChallenge(), + kRegisterKey, kKeyName); + callback_observer.WaitForCallback(); + + EXPECT_EQ( + callback_observer.GetResult(), + TpmChallengeKeyResult::MakeChallengeResponse(GetChallengeResponse())); } -INSTANTIATE_TEST_SUITE_P( - AllProfiles, - TpmChallengeMachineKeyAllProfilesTest, - ::testing::Values(TpmChallengeKeyTestBase::ProfileType::kUserProfile, - TpmChallengeKeyTestBase::ProfileType::kSigninProfile)); +TEST_F(TpmChallengeKeyTest, RegisterSuccess) { + const AttestationKeyType kKeyType = KEY_USER; + const bool kRegisterKey = true; + const char* const kKeyName = kEmptyKeyName; -class TpmChallengeUserKeyTest : public TpmChallengeKeyTestBase { - protected: - explicit TpmChallengeUserKeyTest( - ProfileType profile_type = ProfileType::kUserProfile) - : TpmChallengeKeyTestBase(profile_type, chromeos::attestation::KEY_USER) { - } + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartPrepareKeyStep(kKeyType, kRegisterKey, kKeyName, &profile_, + /*callback=*/_)) + .WillOnce(RunOnceCallback<4>( + TpmChallengeKeyResult::MakePublicKey(GetPublicKey()))); - void SetUp() override { - TpmChallengeKeyTestBase::SetUp(); + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartSignChallengeStep(GetChallenge(), /*callback=*/_)) + .WillOnce(RunOnceCallback<1>(TpmChallengeKeyResult::MakeChallengeResponse( + GetChallengeResponse()))); - if (profile_type_ == ProfileType::kUserProfile) { - GetProfile()->GetTestingPrefService()->SetManagedPref( - prefs::kAttestationEnabled, std::make_unique<base::Value>(true)); - } - } -}; + EXPECT_CALL(*mock_tpm_challenge_key_subtle_, + StartRegisterKeyStep(/*callback=*/_)) + .WillOnce(RunOnceCallback<0>(TpmChallengeKeyResult::MakeSuccess())); -TEST_F(TpmChallengeUserKeyTest, UserPolicyDisabled) { - GetProfile()->GetTestingPrefService()->SetManagedPref( - prefs::kAttestationEnabled, std::make_unique<base::Value>(false)); + CallbackObserver callback_observer; + challenge_key_->BuildResponse(kKeyType, &profile_, + callback_observer.GetCallback(), GetChallenge(), + kRegisterKey, kKeyName); + callback_observer.WaitForCallback(); - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kUserPolicyDisabledErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeUserKeyTest, DevicePolicyDisabled) { - GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled, - false); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kDevicePolicyDisabledErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeUserKeyTest, DoesKeyExistDbusFailed) { - cryptohome_client_.set_tpm_attestation_does_key_exist_should_succeed(false); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kDbusErrorMsg, res.GetErrorMessage()); -} - -TEST_F(TpmChallengeUserKeyTest, GetCertificateFailedWithUnspecifiedFailure) { - EXPECT_CALL(mock_attestation_flow_, GetCertificate) - .WillRepeatedly(Invoke(GetCertificateCallbackUnspecifiedFailure)); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kGetCertificateFailedErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeUserKeyTest, GetCertificateFailedWithBadRequestFailure) { - EXPECT_CALL(mock_attestation_flow_, GetCertificate) - .WillRepeatedly(Invoke(GetCertificateCallbackBadRequestFailure)); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kGetCertificateFailedErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeUserKeyTest, SignChallengeFailed) { - EXPECT_CALL(*mock_async_method_caller_, TpmAttestationSignEnterpriseChallenge) - .WillRepeatedly(Invoke(SignChallengeCallbackFalse)); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kSignChallengeFailedErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeUserKeyTest, KeyRegistrationFailed) { - EXPECT_CALL(*mock_async_method_caller_, TpmAttestationRegisterKey) - .WillRepeatedly(Invoke(RegisterKeyCallbackFalse)); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kKeyRegistrationFailedErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeUserKeyTest, KeyExists) { - cryptohome_client_.SetTpmAttestationUserCertificate( - cryptohome::CreateAccountIdentifierFromAccountId( - AccountId::FromUserEmail(kUserEmail)), - "attest-ent-user", std::string()); - // GetCertificate must not be called if the key exists. - EXPECT_CALL(mock_attestation_flow_, GetCertificate).Times(0); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_TRUE(res.IsSuccess()); - EXPECT_EQ(kResponse, res.challenge_response); -} - -TEST_F(TpmChallengeUserKeyTest, KeyNotRegisteredSuccess) { - EXPECT_CALL(*mock_async_method_caller_, TpmAttestationRegisterKey).Times(0); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_TRUE(res.IsSuccess()); - EXPECT_EQ(kResponse, res.challenge_response); -} - -TEST_F(TpmChallengeUserKeyTest, PersonalDevice) { - GetInstallAttributes()->SetConsumerOwned(); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - // Currently personal devices are not supported. - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kUserRejectedErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeUserKeyTest, Success) { - // GetCertificate must be called exactly once. - EXPECT_CALL( - mock_attestation_flow_, - GetCertificate(chromeos::attestation::PROFILE_ENTERPRISE_USER_CERTIFICATE, - _, _, _, _, _)) - .Times(1); - const AccountId account_id = AccountId::FromUserEmail(kUserEmail); - // SignEnterpriseChallenge must be called exactly once. - EXPECT_CALL(*mock_async_method_caller_, - TpmAttestationSignEnterpriseChallenge( - chromeos::attestation::KEY_USER, - cryptohome::Identification(account_id), "attest-ent-user", - cryptohome::Identification(account_id).id(), "device_id", _, - "challenge", /*key_name_for_spkac=*/"", _)) - .Times(1); - // RegisterKey must be called exactly once. - EXPECT_CALL(*mock_async_method_caller_, - TpmAttestationRegisterKey(chromeos::attestation::KEY_USER, - cryptohome::Identification(account_id), - "attest-ent-user", _)) - .Times(1); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_TRUE(res.IsSuccess()); - EXPECT_EQ(kResponse, res.challenge_response); -} - -TEST_F(TpmChallengeUserKeyTest, MultistepSuccess) { - // GetCertificate must be called exactly once. - EXPECT_CALL( - mock_attestation_flow_, - GetCertificate(chromeos::attestation::PROFILE_ENTERPRISE_USER_CERTIFICATE, - _, _, _, _, _)) - .Times(1); - const AccountId account_id = AccountId::FromUserEmail(kUserEmail); - // SignEnterpriseChallenge must be called exactly once. - EXPECT_CALL(*mock_async_method_caller_, - TpmAttestationSignEnterpriseChallenge( - chromeos::attestation::KEY_USER, - cryptohome::Identification(account_id), kNonDefaultKeyName, - cryptohome::Identification(account_id).id(), "device_id", _, - "challenge", /*key_name_for_spkac=*/"", _)) - .Times(1); - // RegisterKey must be called exactly once. - EXPECT_CALL(*mock_async_method_caller_, - TpmAttestationRegisterKey(chromeos::attestation::KEY_USER, - cryptohome::Identification(account_id), - kNonDefaultKeyName, _)) - .Times(1); - - TpmChallengeKeyResult public_key_res; - TpmChallengeKeyResult challenge_response_res; - TpmChallengeKeyResult register_key_res; - RunMultistepFlow(kChallenge, /*register_key=*/true, - /*key_name=*/kNonDefaultKeyName, &public_key_res, - &challenge_response_res, ®ister_key_res); - - EXPECT_TRUE(public_key_res.IsSuccess()); - EXPECT_EQ(kPublicKey, public_key_res.public_key); - EXPECT_TRUE(challenge_response_res.IsSuccess()); - EXPECT_EQ(kResponse, challenge_response_res.challenge_response); - EXPECT_TRUE(register_key_res.IsSuccess()); -} - -TEST_F(TpmChallengeUserKeyTest, AttestationNotPrepared) { - cryptohome_client_.set_tpm_attestation_is_prepared(false); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kResetRequiredErrorMsg, - res.GetErrorMessage()); -} - -TEST_F(TpmChallengeUserKeyTest, AttestationPreparedDbusFailed) { - cryptohome_client_.SetServiceIsAvailable(false); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kDbusErrorMsg, res.GetErrorMessage()); -} - -class TpmChallengeUserKeySigninProfileTest : public TpmChallengeUserKeyTest { - protected: - TpmChallengeUserKeySigninProfileTest() - : TpmChallengeUserKeyTest(ProfileType::kSigninProfile) {} -}; - -TEST_F(TpmChallengeUserKeySigninProfileTest, UserKeyNotAvailable) { - GetCrosSettingsHelper()->SetBoolean(chromeos::kDeviceAttestationEnabled, - false); - - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kUserKeyNotAvailableErrorMsg, - res.GetErrorMessage()); -} - -class TpmChallengeMachineKeyUnmanagedUserTest - : public TpmChallengeMachineKeyTest { - protected: - void SetAuthenticatedUser() override { - signin::MakePrimaryAccountAvailable( - IdentityManagerFactory::GetForProfile(GetProfile()), - account_id_.GetUserEmail()); - } - - TestingProfile* CreateProfile() override { - fake_user_manager_->AddUser(account_id_); - return profile_manager()->CreateTestingProfile(account_id_.GetUserEmail()); - } - - const std::string email = "test@chromium.com"; - const AccountId account_id_ = - AccountId::FromUserEmailGaiaId(email, - signin::GetTestGaiaIdForEmail(email)); -}; - -TEST_F(TpmChallengeMachineKeyUnmanagedUserTest, UserNotManaged) { - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/false, - /*key_name=*/"", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kUserNotManagedErrorMsg, - res.GetErrorMessage()); -} - -class TpmChallengeUserKeyUnmanagedUserTest : public TpmChallengeUserKeyTest { - protected: - void SetAuthenticatedUser() override { - signin::MakePrimaryAccountAvailable( - IdentityManagerFactory::GetForProfile(GetProfile()), - account_id_.GetUserEmail()); - } - - TestingProfile* CreateProfile() override { - fake_user_manager_->AddUser(account_id_); - return profile_manager()->CreateTestingProfile(account_id_.GetUserEmail()); - } - - const std::string email = "test@chromium.com"; - const AccountId account_id_ = - AccountId::FromUserEmailGaiaId(email, - signin::GetTestGaiaIdForEmail(email)); -}; - -TEST_F(TpmChallengeUserKeyUnmanagedUserTest, UserNotManaged) { - TpmChallengeKeyResult res; - RunBuildResponse(kChallenge, /*register_key=*/true, "", &res); - - EXPECT_FALSE(res.IsSuccess()); - EXPECT_EQ("", res.challenge_response); - EXPECT_EQ(TpmChallengeKeyResult::kUserNotManagedErrorMsg, - res.GetErrorMessage()); + EXPECT_EQ( + callback_observer.GetResult(), + TpmChallengeKeyResult::MakeChallengeResponse(GetChallengeResponse())); } } // namespace
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc index d24238c..acd5e27 100644 --- a/chrome/browser/chromeos/login/webview_login_browsertest.cc +++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -33,7 +33,6 @@ #include "chrome/browser/chromeos/login/test/js_checker.h" #include "chrome/browser/chromeos/login/test/local_policy_test_server_mixin.h" #include "chrome/browser/chromeos/login/test/oobe_base_test.h" -#include "chrome/browser/chromeos/login/test/oobe_screen_exit_waiter.h" #include "chrome/browser/chromeos/login/test/oobe_screen_waiter.h" #include "chrome/browser/chromeos/login/test/session_manager_state_waiter.h" #include "chrome/browser/chromeos/login/ui/login_display_host.h" @@ -49,7 +48,6 @@ #include "chrome/browser/ui/webui/chromeos/login/error_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/eula_screen_handler.h" #include "chrome/browser/ui/webui/chromeos/login/gaia_screen_handler.h" -#include "chrome/browser/ui/webui/chromeos/login/user_creation_screen_handler.h" #include "chrome/browser/ui/webui/signin/signin_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "chromeos/constants/chromeos_features.h" @@ -242,8 +240,7 @@ class WebviewLoginTest : public OobeBaseTest { public: WebviewLoginTest() { - scoped_feature_list_.InitWithFeatures( - {features::kGaiaActionButtons, features::kChildSpecificSignin}, {}); + scoped_feature_list_.InitWithFeatures({features::kGaiaActionButtons}, {}); } ~WebviewLoginTest() override = default; @@ -306,9 +303,9 @@ protected: chromeos::ScopedTestingCrosSettings scoped_testing_cros_settings_; FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()}; - base::test::ScopedFeatureList scoped_feature_list_; private: + base::test::ScopedFeatureList scoped_feature_list_; DISALLOW_COPY_AND_ASSIGN(WebviewLoginTest); }; @@ -426,16 +423,18 @@ test::WaitForPrimaryUserSessionStart(); } -IN_PROC_BROWSER_TEST_F(WebviewLoginTest, BackToUserCreationScreen) { +IN_PROC_BROWSER_TEST_F(WebviewLoginTest, ErrorScreenOnGaiaError) { WaitForGaiaPageLoadAndPropertyUpdate(); - - // Start with identifier page. ExpectIdentifierPage(); - // Click back to exit gaia screen. + // Make gaia landing page unreachable + fake_gaia_.fake_gaia()->SetErrorResponse( + GaiaUrls::GetInstance()->embedded_setup_chromeos_url(2), + net::HTTP_NOT_FOUND); + + // Click back to reload (unreachable) identifier page. test::OobeJS().ClickOnPath({"gaia-signin", "signin-back-button"}); - OobeScreenExitWaiter(GaiaView::kScreenId).Wait(); - OobeScreenWaiter(UserCreationView::kScreenId).Wait(); + OobeScreenWaiter(ErrorScreenView::kScreenId).Wait(); } // Create new account option should be available only if the settings allow it. @@ -1328,28 +1327,4 @@ ExpectIdentifierPage(); } -class WebviewLoginTestWithChildSigninDisabled : public WebviewLoginTest { - public: - WebviewLoginTestWithChildSigninDisabled() { - scoped_feature_list_.Reset(); - scoped_feature_list_.InitWithFeatures({features::kGaiaActionButtons}, - {features::kChildSpecificSignin}); - } -}; - -IN_PROC_BROWSER_TEST_F(WebviewLoginTestWithChildSigninDisabled, - ErrorScreenOnGaiaError) { - WaitForGaiaPageLoadAndPropertyUpdate(); - ExpectIdentifierPage(); - - // Make gaia landing page unreachable - fake_gaia_.fake_gaia()->SetErrorResponse( - GaiaUrls::GetInstance()->embedded_setup_chromeos_url(2), - net::HTTP_NOT_FOUND); - - // Click back to reload (unreachable) identifier page. - test::OobeJS().ClickOnPath({"gaia-signin", "signin-back-button"}); - OobeScreenWaiter(ErrorScreenView::kScreenId).Wait(); -} - } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index 89d85bb..438778b 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -654,6 +654,9 @@ if (login_screen_started_) return; + // Landed on the login screen. No longer skipping enrollment for tests. + wizard_context_->skip_to_login_for_tests = false; + if (!time_eula_accepted_.is_null()) { base::TimeDelta delta = base::TimeTicks::Now() - time_eula_accepted_; UMA_HISTOGRAM_MEDIUM_TIMES("OOBE.EULAToSignInTime", delta); @@ -662,9 +665,6 @@ UpdateStatusAreaVisibilityForScreen(GaiaView::kScreenId); GetLoginDisplayHost()->StartSignInScreen(); login_screen_started_ = true; - - // Landed on the login screen. No longer skipping to login for tests. - wizard_context_->skip_to_login_for_tests = false; } void WizardController::ShowGaiaPasswordChangedScreen(
diff --git a/chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.cc b/chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.cc new file mode 100644 index 0000000..208a6c73 --- /dev/null +++ b/chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.cc
@@ -0,0 +1,90 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.h" + +#include <utility> + +#include "base/bind.h" +#include "chromeos/services/network_config/in_process_instance.h" +#include "chromeos/services/network_config/public/cpp/cros_network_config_util.h" + +namespace chromeos { +namespace network_diagnostics { + +CaptivePortalRoutine::CaptivePortalRoutine() { + network_config::BindToInProcessInstance( + remote_cros_network_config_.BindNewPipeAndPassReceiver()); +} + +CaptivePortalRoutine::~CaptivePortalRoutine() = default; + +void CaptivePortalRoutine::RunRoutine(CaptivePortalRoutineCallback callback) { + if (!CanRun()) { + std::move(callback).Run(verdict(), std::move(problems_)); + return; + } + routine_completed_callback_ = std::move(callback); + FetchActiveNetworks(); +} + +void CaptivePortalRoutine::AnalyzeResultsAndExecuteCallback() { + if (no_active_networks_) { + set_verdict(mojom::RoutineVerdict::kProblem); + problems_.emplace_back(mojom::CaptivePortalProblem::kNoActiveNetworks); + } else if (restricted_connectivity_) { + set_verdict(mojom::RoutineVerdict::kProblem); + problems_.emplace_back( + mojom::CaptivePortalProblem::kRestrictedConnectivity); + } else if (state_is_captive_portal_) { + set_verdict(mojom::RoutineVerdict::kProblem); + problems_.emplace_back(mojom::CaptivePortalProblem::kCaptivePortalState); + } else { + set_verdict(mojom::RoutineVerdict::kNoProblem); + } + std::move(routine_completed_callback_).Run(verdict(), problems_); +} + +void CaptivePortalRoutine::FetchActiveNetworks() { + remote_cros_network_config_->GetNetworkStateList( + network_config::mojom::NetworkFilter::New( + network_config::mojom::FilterType::kActive, + network_config::mojom::NetworkType::kAll, + network_config::mojom::kNoLimit), + base::BindOnce(&CaptivePortalRoutine::OnNetworkStateListReceived, + base::Unretained(this))); +} + +void CaptivePortalRoutine::FetchManagedProperties(const std::string& guid) { + remote_cros_network_config_->GetManagedProperties( + guid, base::BindOnce(&CaptivePortalRoutine::OnManagedPropertiesReceived, + base::Unretained(this))); +} + +// Process the network interface information. +void CaptivePortalRoutine::OnNetworkStateListReceived( + std::vector<network_config::mojom::NetworkStatePropertiesPtr> networks) { + if (networks.size() == 0) { + no_active_networks_ = true; + AnalyzeResultsAndExecuteCallback(); + } else { + state_is_captive_portal_ = + networks[0]->connection_state == + network_config::mojom::ConnectionStateType::kPortal; + FetchManagedProperties(networks[0]->guid); + } +} + +void CaptivePortalRoutine::OnManagedPropertiesReceived( + network_config::mojom::ManagedPropertiesPtr managed_properties) { + if (!managed_properties) { + AnalyzeResultsAndExecuteCallback(); + return; + } + restricted_connectivity_ = managed_properties->restricted_connectivity; + AnalyzeResultsAndExecuteCallback(); +} + +} // namespace network_diagnostics +} // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.h b/chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.h new file mode 100644 index 0000000..31cb9bf --- /dev/null +++ b/chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.h
@@ -0,0 +1,58 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_CAPTIVE_PORTAL_ROUTINE_H_ +#define CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_CAPTIVE_PORTAL_ROUTINE_H_ + +#include <vector> + +#include "base/callback.h" +#include "chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_routine.h" +#include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" +#include "mojo/public/cpp/bindings/remote.h" + +namespace chromeos { +namespace network_diagnostics { + +// Tests whether the internet connection is trapped behind a captive portal. +class CaptivePortalRoutine : public NetworkDiagnosticsRoutine { + public: + using CaptivePortalRoutineCallback = + mojom::NetworkDiagnosticsRoutines::CaptivePortalCallback; + + CaptivePortalRoutine(); + CaptivePortalRoutine(const CaptivePortalRoutine&) = delete; + CaptivePortalRoutine& operator=(const CaptivePortalRoutine&) = delete; + ~CaptivePortalRoutine() override; + + // NetworkDiagnosticsRoutine: + void AnalyzeResultsAndExecuteCallback() override; + + // Run the core logic of this routine. Set |callback| to + // |routine_completed_callback_|, which is to be executed in + // AnalyzeResultsAndExecuteCallback(). + void RunRoutine(CaptivePortalRoutineCallback callback); + + private: + void FetchActiveNetworks(); + void FetchManagedProperties(const std::string& guid); + void OnNetworkStateListReceived( + std::vector<chromeos::network_config::mojom::NetworkStatePropertiesPtr> + networks); + void OnManagedPropertiesReceived( + network_config::mojom::ManagedPropertiesPtr managed_properties); + + bool no_active_networks_ = false; + bool restricted_connectivity_ = false; + bool state_is_captive_portal_ = false; + mojo::Remote<chromeos::network_config::mojom::CrosNetworkConfig> + remote_cros_network_config_; + std::vector<mojom::CaptivePortalProblem> problems_; + CaptivePortalRoutineCallback routine_completed_callback_; +}; + +} // namespace network_diagnostics +} // namespace chromeos + +#endif // CHROME_BROWSER_CHROMEOS_NET_NETWORK_DIAGNOSTICS_CAPTIVE_PORTAL_ROUTINE_H_
diff --git a/chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine_unittest.cc b/chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine_unittest.cc new file mode 100644 index 0000000..34fbe83 --- /dev/null +++ b/chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine_unittest.cc
@@ -0,0 +1,227 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.h" + +#include "chromeos/login/login_state/login_state.h" +#include "chromeos/network/managed_network_configuration_handler.h" +#include "chromeos/network/network_cert_loader.h" +#include "chromeos/network/network_configuration_handler.h" +#include "chromeos/network/network_handler.h" +#include "chromeos/network/network_metadata_store.h" +#include "chromeos/network/network_profile_handler.h" +#include "chromeos/network/onc/onc_utils.h" +#include "chromeos/network/proxy/ui_proxy_config_service.h" +#include "chromeos/services/network_config/public/cpp/cros_network_config_test_helper.h" +#include "components/onc/onc_constants.h" +#include "components/onc/onc_pref_names.h" +#include "components/prefs/testing_pref_service.h" +#include "components/proxy_config/pref_proxy_config_tracker_impl.h" +#include "components/proxy_config/proxy_config_pref_names.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" +#include "content/public/test/browser_task_environment.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/cros_system_api/dbus/shill/dbus-constants.h" + +namespace chromeos { +namespace network_diagnostics { + +class CaptivePortalRoutineTest : public ::testing::Test { + public: + CaptivePortalRoutineTest() { + LoginState::Initialize(); + NetworkCertLoader::Initialize(); + InitializeManagedNetworkConfigurationHandler(); + // Note that |cros_network_config_test_helper_| must be initialized before + // |captive_portal_routine_| is initialized in SetUpRoutine(). This + // is because |g_network_config_override| in + // OverrideInProcessInstanceForTesting() must be called before + // BindToInProcessInstance() is called. See + // chromeos/services/network_config/in_process_instance.cc for further + // details. + cros_network_config_test_helper().Initialize( + managed_network_configuration_handler_.get()); + captive_portal_routine_ = std::make_unique<CaptivePortalRoutine>(); + + // Wait until |cros_network_config_test_helper_| has initialized. + base::RunLoop().RunUntilIdle(); + } + + CaptivePortalRoutineTest(const CaptivePortalRoutineTest&) = delete; + CaptivePortalRoutineTest& operator=(const CaptivePortalRoutineTest&) = delete; + + ~CaptivePortalRoutineTest() override { + NetworkCertLoader::Shutdown(); + LoginState::Shutdown(); + } + + void CompareVerdict( + mojom::RoutineVerdict expected_verdict, + const std::vector<mojom::CaptivePortalProblem>& expected_problems, + mojom::RoutineVerdict actual_verdict, + const std::vector<mojom::CaptivePortalProblem>& actual_problems) { + DCHECK(run_loop_.running()); + EXPECT_EQ(expected_verdict, actual_verdict); + EXPECT_EQ(expected_problems, actual_problems); + run_loop_.Quit(); + } + + void SetUpWiFi(const char* state) { + DCHECK(wifi_path_.empty()); + // By default, NetworkStateTestHelper already adds a WiFi device, so, we + // do not need to add one here. All that remains to be done is configuring + // the WiFi service. + wifi_path_ = ConfigureService( + R"({"GUID": "wifi_guid", "Type": "wifi", "State": "idle"})"); + SetServiceProperty(wifi_path_, shill::kStateProperty, base::Value(state)); + base::RunLoop().RunUntilIdle(); + } + + // See IsCaptivePortalState() in chromeos/network/network_state.cc to see how + // the captive portal state is determined. + void SetUpCaptivePortalState(const std::string& portal_detection_phase, + const std::string& portal_detection_status) { + DCHECK(!wifi_path_.empty()); + SetServiceProperty(wifi_path_, shill::kPortalDetectionFailedPhaseProperty, + base::Value(portal_detection_phase)); + SetServiceProperty(wifi_path_, shill::kPortalDetectionFailedStatusProperty, + base::Value(portal_detection_status)); + } + + void InitializeManagedNetworkConfigurationHandler() { + network_profile_handler_ = NetworkProfileHandler::InitializeForTesting(); + network_configuration_handler_ = + base::WrapUnique<NetworkConfigurationHandler>( + NetworkConfigurationHandler::InitializeForTest( + network_state_helper().network_state_handler(), + cros_network_config_test_helper().network_device_handler())); + + PrefProxyConfigTrackerImpl::RegisterProfilePrefs(user_prefs_.registry()); + PrefProxyConfigTrackerImpl::RegisterPrefs(local_state_.registry()); + ::onc::RegisterProfilePrefs(user_prefs_.registry()); + ::onc::RegisterPrefs(local_state_.registry()); + + ui_proxy_config_service_ = std::make_unique<chromeos::UIProxyConfigService>( + &user_prefs_, &local_state_, + network_state_helper().network_state_handler(), + network_profile_handler_.get()); + + managed_network_configuration_handler_ = + ManagedNetworkConfigurationHandler::InitializeForTesting( + network_state_helper().network_state_handler(), + network_profile_handler_.get(), + cros_network_config_test_helper().network_device_handler(), + network_configuration_handler_.get(), + ui_proxy_config_service_.get()); + + managed_network_configuration_handler_->SetPolicy( + ::onc::ONC_SOURCE_DEVICE_POLICY, + /*userhash=*/std::string(), + /*network_configs_onc=*/base::ListValue(), + /*global_network_config=*/base::DictionaryValue()); + + // Wait until the |managed_network_configuration_handler_| is initialized + // and set up. + base::RunLoop().RunUntilIdle(); + } + + network_config::CrosNetworkConfigTestHelper& + cros_network_config_test_helper() { + return cros_network_config_test_helper_; + } + chromeos::NetworkStateTestHelper& network_state_helper() { + return cros_network_config_test_helper_.network_state_helper(); + } + CaptivePortalRoutine* captive_portal_routine() { + return captive_portal_routine_.get(); + } + + protected: + base::WeakPtr<CaptivePortalRoutineTest> weak_ptr() { + return weak_factory_.GetWeakPtr(); + } + base::RunLoop& run_loop() { return run_loop_; } + + private: + std::string ConfigureService(const std::string& shill_json_string) { + return network_state_helper().ConfigureService(shill_json_string); + } + void SetServiceProperty(const std::string& service_path, + const std::string& key, + const base::Value& value) { + network_state_helper().SetServiceProperty(service_path, key, value); + } + const std::string& wifi_path() const { return wifi_path_; } + + content::BrowserTaskEnvironment task_environment_; + base::RunLoop run_loop_; + sync_preferences::TestingPrefServiceSyncable user_prefs_; + TestingPrefServiceSimple local_state_; + network_config::CrosNetworkConfigTestHelper cros_network_config_test_helper_; + std::unique_ptr<NetworkProfileHandler> network_profile_handler_; + std::unique_ptr<NetworkConfigurationHandler> network_configuration_handler_; + std::unique_ptr<UIProxyConfigService> ui_proxy_config_service_; + std::unique_ptr<ManagedNetworkConfigurationHandler> + managed_network_configuration_handler_; + std::unique_ptr<CaptivePortalRoutine> captive_portal_routine_; + std::string wifi_path_; + base::WeakPtrFactory<CaptivePortalRoutineTest> weak_factory_{this}; +}; + +// Test whether an online active network successfully passes. +TEST_F(CaptivePortalRoutineTest, TestNoCaptivePortalState) { + SetUpWiFi(shill::kStateOnline); + std::vector<mojom::CaptivePortalProblem> expected_problems = {}; + captive_portal_routine()->RunRoutine( + base::BindOnce(&CaptivePortalRoutineTest::CompareVerdict, weak_ptr(), + mojom::RoutineVerdict::kNoProblem, expected_problems)); + run_loop().Run(); +} + +// Test whether an active network trapped in captive portal is reported +// correctly. +TEST_F(CaptivePortalRoutineTest, TestCaptivePortalState) { + SetUpWiFi(shill::kStatePortal); + // Provide an instance of the service properties and their corresponding + // values that occur when we do not know the portal detection state. This + // ensures the network is not in a state of restricted connectivity. + SetUpCaptivePortalState(shill::kPortalDetectionPhaseUnknown, + shill::kPortalDetectionStatusFailure); + std::vector<mojom::CaptivePortalProblem> expected_problems = { + mojom::CaptivePortalProblem::kCaptivePortalState}; + captive_portal_routine()->RunRoutine( + base::BindOnce(&CaptivePortalRoutineTest::CompareVerdict, weak_ptr(), + mojom::RoutineVerdict::kProblem, expected_problems)); + run_loop().Run(); +} + +// Test whether no active networks is reported correctly. +TEST_F(CaptivePortalRoutineTest, TestNoActiveNetworks) { + SetUpWiFi(shill::kStateOffline); + std::vector<mojom::CaptivePortalProblem> expected_problems = { + mojom::CaptivePortalProblem::kNoActiveNetworks}; + captive_portal_routine()->RunRoutine( + base::BindOnce(&CaptivePortalRoutineTest::CompareVerdict, weak_ptr(), + mojom::RoutineVerdict::kProblem, expected_problems)); + run_loop().Run(); +} + +// Test that an active network with restricted connectivity is detected. +TEST_F(CaptivePortalRoutineTest, TestRestrictedConnectivity) { + SetUpWiFi(shill::kStatePortal); + // Provide an instance of the service properties and their corresponding + // values that occur when trapped in a captive portal. This ensures that the + // network is in a state of restricted connectivity. + SetUpCaptivePortalState(shill::kPortalDetectionPhaseContent, + shill::kPortalDetectionStatusFailure); + std::vector<mojom::CaptivePortalProblem> expected_problems = { + mojom::CaptivePortalProblem::kRestrictedConnectivity}; + captive_portal_routine()->RunRoutine( + base::BindOnce(&CaptivePortalRoutineTest::CompareVerdict, weak_ptr(), + mojom::RoutineVerdict::kProblem, expected_problems)); + run_loop().Run(); +} + +} // namespace network_diagnostics +} // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.cc b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.cc index 37c19a6..2e853a1 100644 --- a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.cc +++ b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/bind.h" +#include "chrome/browser/chromeos/net/network_diagnostics/captive_portal_routine.h" #include "chrome/browser/chromeos/net/network_diagnostics/dns_latency_routine.h" #include "chrome/browser/chromeos/net/network_diagnostics/dns_resolution_routine.h" #include "chrome/browser/chromeos/net/network_diagnostics/dns_resolver_present_routine.h" @@ -138,5 +139,19 @@ std::move(routine), std::move(callback))); } +void NetworkDiagnosticsImpl::CaptivePortal(CaptivePortalCallback callback) { + auto routine = std::make_unique<CaptivePortalRoutine>(); + // RunRoutine() takes a lambda callback that takes ownership of the routine. + // This ensures that the routine stays alive when it makes asynchronous mojo + // calls. The routine will be destroyed when the lambda exits. + routine->RunRoutine(base::BindOnce( + [](std::unique_ptr<CaptivePortalRoutine> routine, + CaptivePortalCallback callback, mojom::RoutineVerdict verdict, + const std::vector<mojom::CaptivePortalProblem>& problems) { + std::move(callback).Run(verdict, problems); + }, + std::move(routine), std::move(callback))); +} + } // namespace network_diagnostics } // namespace chromeos
diff --git a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.h b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.h index cfac73842..fb05504 100644 --- a/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.h +++ b/chrome/browser/chromeos/net/network_diagnostics/network_diagnostics_impl.h
@@ -38,6 +38,7 @@ void DnsResolverPresent(DnsResolverPresentCallback callback) override; void DnsLatency(DnsLatencyCallback callback) override; void DnsResolution(DnsResolutionCallback callback) override; + void CaptivePortal(CaptivePortalCallback callback) override; private: mojo::ReceiverSet<mojom::NetworkDiagnosticsRoutines> receivers_;
diff --git a/chrome/browser/extensions/process_management_browsertest.cc b/chrome/browser/extensions/process_management_browsertest.cc index 8e72617..caee5a8 100644 --- a/chrome/browser/extensions/process_management_browsertest.cc +++ b/chrome/browser/extensions/process_management_browsertest.cc
@@ -6,6 +6,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_apitest.h" @@ -23,6 +24,7 @@ #include "content/public/browser/render_view_host.h" #include "content/public/browser/site_instance.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -50,6 +52,13 @@ } class ProcessManagementTest : public ExtensionBrowserTest { + public: + ProcessManagementTest() { + // TODO(https://crbug.com/1110891): Remove this once Extensions are + // supported with BackForwardCache. + disabled_feature_list_.InitWithFeatures({}, {features::kBackForwardCache}); + } + private: // This is needed for testing isolated apps, which are still experimental. void SetUpCommandLine(base::CommandLine* command_line) override { @@ -62,6 +71,8 @@ ExtensionBrowserTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); } + + base::test::ScopedFeatureList disabled_feature_list_; }; class ChromeWebStoreProcessTest : public ExtensionBrowserTest {
diff --git a/chrome/browser/extensions/process_manager_browsertest.cc b/chrome/browser/extensions/process_manager_browsertest.cc index 332d5bb3..d84302d9 100644 --- a/chrome/browser/extensions/process_manager_browsertest.cc +++ b/chrome/browser/extensions/process_manager_browsertest.cc
@@ -16,6 +16,7 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_browsertest.h" @@ -36,6 +37,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_features.h" #include "content/public/common/navigation_policy.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" @@ -197,6 +199,9 @@ public: ProcessManagerBrowserTest() { guest_view::GuestViewManager::set_factory_for_testing(&factory_); + // TODO(https://crbug.com/1110891): Remove this once Extensions are + // supported with BackForwardCache. + disabled_feature_list_.InitWithFeatures({}, {features::kBackForwardCache}); } void SetUpOnMainThread() override { @@ -298,6 +303,7 @@ private: guest_view::TestGuestViewManagerFactory factory_; std::vector<std::unique_ptr<TestExtensionDir>> temp_dirs_; + base::test::ScopedFeatureList disabled_feature_list_; }; class DefaultProfileExtensionBrowserTest : public ExtensionBrowserTest {
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 33c38a7..0bdb22a 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -678,8 +678,8 @@ }, { "name": "cross-origin-opener-policy-reporting", - "owners": [ "ahemery", "clamy", "pmeuleman" ], - "expiry_milestone": 85 + "owners": [ "ahemery", "arthursonzogni", "clamy", "pmeuleman" ], + "expiry_milestone": 86 }, { "name": "crostini-disk-resizing", @@ -1516,7 +1516,7 @@ }, { "name": "enable-filtering-scroll-events", - "owners": [ "axantoine", "eirage", "nzolghadr", "input-dev" ], + "owners": [ "eirage", "nzolghadr", "input-dev" ], "expiry_milestone": 85 }, { @@ -1760,8 +1760,8 @@ }, { "name": "enable-native-notifications", - "owners": [ "peter", "finnur" ], - "expiry_milestone": 84 + "owners": [ "peter", "finnur", "knollr" ], + "expiry_milestone": 90 }, { "name": "enable-navigation-predictor", @@ -2028,6 +2028,11 @@ "expiry_milestone": -1 }, { + "name": "enable-sign-in-profile-creation-flow", + "owners": [ "dizg", "droger", "msalama" ], + "expiry_milestone": 90 + }, + { "name": "enable-site-isolation-for-password-sites", "owners": [ "site-isolation-dev", "alexmos", "lukasza" ], // Note: while password-triggered site isolation launched in M77, it only @@ -2304,8 +2309,8 @@ }, { "name": "enable-webrtc-hybrid-agc", - "owners": [ "aleloi" ], - "expiry_milestone": 83 + "owners": [ "alessiob" ], + "expiry_milestone": 103 }, { "name": "enable-webrtc-new-encode-cpu-load-estimator", @@ -2589,7 +2594,7 @@ { "name": "freeze-user-agent", "owners": [ "yoavweiss", "aarontag" ], - "expiry_milestone": 85 + "expiry_milestone": 89 }, { "name": "fullscreen-controller-browser-scoped", @@ -2673,8 +2678,7 @@ "owners": [ "//chrome/browser/ui/hats/OWNERS" ], // A debugging and demo flag to allow UI/dev/testing team to always show the UI // components for the survey without being limited by the triggering mechanism. - // This flag should expire along with the above feature flag. - "expiry_milestone": 84 + "expiry_milestone": 90 }, { "name": "happiness-tracking-surveys-for-desktop-migration", @@ -3829,7 +3833,7 @@ { "name": "safe-browsing-available", "owners": [ "//ios/chrome/browser/safe_browsing/OWNERS", "bling-flags" ], - "expiry_milestone": 85 + "expiry_milestone": 87 }, { "name": "safe-browsing-enhanced-protection-android",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index d57ad8b7..b6cd69f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -170,8 +170,7 @@ 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. If disabled, this will also delete any AppCache data " - "from profile directories."; + "has been removed."; const char kDnsHttpssvcName[] = "Support for HTTPSSVC records in DNS."; const char kDnsHttpssvcDescription[] = @@ -1404,6 +1403,11 @@ const char kNewProfilePickerDescription[] = "Enables new profile picker implementation."; +const char kSignInProfileCreationFlowName[] = "Signin profile creation flow"; +const char kSignInProfileCreationFlowDescription[] = + "Enables signin promo page for the new profile creation flow in the " + "profile picker."; + const char kNewUsbBackendName[] = "Enable new USB backend"; const char kNewUsbBackendDescription[] = "Enables the new experimental USB backends for macOS and Windows";
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index b2ab277..b2bfb1a 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -831,6 +831,9 @@ extern const char kNewProfilePickerName[]; extern const char kNewProfilePickerDescription[]; +extern const char kSignInProfileCreationFlowName[]; +extern const char kSignInProfileCreationFlowDescription[]; + extern const char kNewUsbBackendName[]; extern const char kNewUsbBackendDescription[];
diff --git a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc index 9aac99b..cb6a29c 100644 --- a/chrome/browser/media/encrypted_media_supported_types_browsertest.cc +++ b/chrome/browser/media/encrypted_media_supported_types_browsertest.cc
@@ -204,10 +204,6 @@ test_launcher_utils::RemoveCommandLineSwitch( default_command_line, switches::kDisableComponentUpdate, command_line); #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) - command_line->AppendSwitchASCII( - switches::kEnableBlinkFeatures, - "EncryptedMediaEncryptionSchemeQuery," - "EncryptedMediaPersistentUsageRecordSession"); } void SetUpOnMainThread() override {
diff --git a/chrome/browser/media/feeds/media_feeds_contents_observer.cc b/chrome/browser/media/feeds/media_feeds_contents_observer.cc index c0d7012c..30572962a 100644 --- a/chrome/browser/media/feeds/media_feeds_contents_observer.cc +++ b/chrome/browser/media/feeds/media_feeds_contents_observer.cc
@@ -20,7 +20,13 @@ MediaFeedsContentsObserver::MediaFeedsContentsObserver( content::WebContents* web_contents) - : content::WebContentsObserver(web_contents) {} + : content::WebContentsObserver(web_contents) { + // The cookie observer cannot be created at initialization of + // MediaFeedsService because the network service is not ready and therefore we + // should create it when we get a web contents. + if (auto* service = GetService()) + service->EnsureCookieObserver(); +} MediaFeedsContentsObserver::~MediaFeedsContentsObserver() = default; @@ -56,6 +62,9 @@ return; } + // Clear the old binding for the old frame. + render_frame_.reset(); + render_frame_host->GetRemoteAssociatedInterfaces()->GetInterface( &render_frame_);
diff --git a/chrome/browser/media/feeds/media_feeds_service.cc b/chrome/browser/media/feeds/media_feeds_service.cc index 4ecc9da9..1eb22ee 100644 --- a/chrome/browser/media/feeds/media_feeds_service.cc +++ b/chrome/browser/media/feeds/media_feeds_service.cc
@@ -77,6 +77,7 @@ DCHECK(profile); DCHECK(!profile->IsOffTheRecord()); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + MaybeStartListening(); } @@ -154,12 +155,7 @@ base::TimeDelta::FromMinutes(30); MediaFeedsService::MediaFeedsService(Profile* profile) - : cookie_change_listener_(std::make_unique<CookieChangeListener>( - profile, - base::BindRepeating(&MediaFeedsService::OnResetOriginFromCookie, - base::Unretained(this)))), - profile_(profile), - clock_(base::DefaultClock::GetInstance()) { + : profile_(profile), clock_(base::DefaultClock::GetInstance()) { DCHECK(!profile->IsOffTheRecord()); pref_change_registrar_.Init(profile_->GetPrefs()); @@ -659,4 +655,13 @@ weak_factory_.GetWeakPtr())); } +void MediaFeedsService::EnsureCookieObserver() { + if (cookie_change_listener_) + return; + + cookie_change_listener_ = std::make_unique<CookieChangeListener>( + profile_, base::BindRepeating(&MediaFeedsService::OnResetOriginFromCookie, + base::Unretained(this))); +} + } // namespace media_feeds
diff --git a/chrome/browser/media/feeds/media_feeds_service.h b/chrome/browser/media/feeds/media_feeds_service.h index 7615c95..3c2a150 100644 --- a/chrome/browser/media/feeds/media_feeds_service.h +++ b/chrome/browser/media/feeds/media_feeds_service.h
@@ -112,6 +112,8 @@ bool HasCookieObserverForTest() const; + void EnsureCookieObserver(); + private: friend class MediaFeedsServiceTest;
diff --git a/chrome/browser/nearby_sharing/certificates/common.cc b/chrome/browser/nearby_sharing/certificates/common.cc index cbd1d36..4381c5c4 100644 --- a/chrome/browser/nearby_sharing/certificates/common.cc +++ b/chrome/browser/nearby_sharing/certificates/common.cc
@@ -45,6 +45,14 @@ new_num_bytes); } +std::vector<uint8_t> ComputeAuthenticationTokenHash( + base::span<const uint8_t> authentication_token, + base::span<const uint8_t> secret_key) { + return crypto::HkdfSha256(authentication_token, secret_key, + /*info=*/base::span<const uint8_t>(), + kNearbyShareNumBytesAuthenticationTokenHash); +} + std::unique_ptr<crypto::Encryptor> CreateNearbyShareCtrEncryptor( const crypto::SymmetricKey* secret_key, base::span<const uint8_t> salt) {
diff --git a/chrome/browser/nearby_sharing/certificates/common.h b/chrome/browser/nearby_sharing/certificates/common.h index 57745ec1..834d074 100644 --- a/chrome/browser/nearby_sharing/certificates/common.h +++ b/chrome/browser/nearby_sharing/certificates/common.h
@@ -31,6 +31,14 @@ base::Time not_after, bool use_public_certificate_tolerance); +// Uses HKDF to create a hash of the |authentication_token|, using the +// |secret_key|. A trivial info parameter is used, and the output length is +// fixed to be kNearbyShareNumBytesAuthenticationTokenHash to conform with the +// GmsCore implementation. +std::vector<uint8_t> ComputeAuthenticationTokenHash( + base::span<const uint8_t> authentication_token, + base::span<const uint8_t> secret_key); + // Uses HKDF to generate a new key of length |new_num_bytes| from |key|. To // conform with the GmsCore implementation, trivial salt and info are used. std::vector<uint8_t> DeriveNearbyShareKey(base::span<const uint8_t> key,
diff --git a/chrome/browser/nearby_sharing/certificates/common_unittest.cc b/chrome/browser/nearby_sharing/certificates/common_unittest.cc index 2e7e9005..226e565 100644 --- a/chrome/browser/nearby_sharing/certificates/common_unittest.cc +++ b/chrome/browser/nearby_sharing/certificates/common_unittest.cc
@@ -3,12 +3,22 @@ // found in the LICENSE file. #include "chrome/browser/nearby_sharing/certificates/common.h" + +#include "base/containers/span.h" #include "chrome/browser/nearby_sharing/certificates/constants.h" #include "chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h" #include "chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h" #include "chrome/browser/nearby_sharing/certificates/test_util.h" #include "testing/gtest/include/gtest/gtest.h" +TEST(NearbyShareCertificatesCommonTest, AuthenticationTokenHash) { + EXPECT_EQ(GetNearbyShareTestPayloadHashUsingSecretKey(), + ComputeAuthenticationTokenHash( + GetNearbyShareTestPayloadToSign(), + base::as_bytes( + base::make_span(GetNearbyShareTestSecretKey()->key())))); +} + TEST(NearbyShareCertificatesCommonTest, ValidityPeriod_PrivateCertificate) { NearbySharePrivateCertificate cert = GetNearbyShareTestPrivateCertificate(NearbyShareVisibility::kAllContacts);
diff --git a/chrome/browser/nearby_sharing/certificates/constants.h b/chrome/browser/nearby_sharing/certificates/constants.h index b31ad7d..c4dcc7c 100644 --- a/chrome/browser/nearby_sharing/certificates/constants.h +++ b/chrome/browser/nearby_sharing/certificates/constants.h
@@ -25,9 +25,8 @@ // rotated on the local device. extern const size_t kNearbyShareNumPrivateCertificates; -// The number of bytes that -// HMAC(/*key=*/|secret_key|, /*message=*/|authentication_token|) -// is converted to via HKDF before advertising. +// The number of bytes comprising the hash of the authentication token using the +// secret key. extern const size_t kNearbyShareNumBytesAuthenticationTokenHash; // Length of key in bytes required by AES-GCM encryption.
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.cc index 9b7c645..50da9e2 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.cc
@@ -14,7 +14,6 @@ #include "crypto/encryptor.h" #include "crypto/hmac.h" #include "crypto/signature_verifier.h" -#include "crypto/symmetric_key.h" namespace { @@ -161,30 +160,48 @@ } return NearbyShareDecryptedPublicCertificate( - not_before, not_after, std::move(public_key), std::move(id), - std::move(unencrypted_metadata)); + not_before, not_after, std::move(secret_key), std::move(public_key), + std::move(id), std::move(unencrypted_metadata)); } NearbyShareDecryptedPublicCertificate::NearbyShareDecryptedPublicCertificate( base::Time not_before, base::Time not_after, + std::unique_ptr<crypto::SymmetricKey> secret_key, std::vector<uint8_t> public_key, std::vector<uint8_t> id, nearbyshare::proto::EncryptedMetadata unencrypted_metadata) : not_before_(not_before), not_after_(not_after), + secret_key_(std::move(secret_key)), public_key_(std::move(public_key)), id_(std::move(id)), unencrypted_metadata_(std::move(unencrypted_metadata)) {} NearbyShareDecryptedPublicCertificate::NearbyShareDecryptedPublicCertificate( - const NearbyShareDecryptedPublicCertificate&) = default; + const NearbyShareDecryptedPublicCertificate& other) { + *this = other; +} + NearbyShareDecryptedPublicCertificate& NearbyShareDecryptedPublicCertificate::operator=( - const NearbyShareDecryptedPublicCertificate&) = default; + const NearbyShareDecryptedPublicCertificate& other) { + if (this == &other) + return *this; + + not_before_ = other.not_before_; + not_after_ = other.not_after_; + secret_key_ = crypto::SymmetricKey::Import( + crypto::SymmetricKey::Algorithm::AES, other.secret_key_->key()); + public_key_ = other.public_key_; + id_ = other.id_; + unencrypted_metadata_ = other.unencrypted_metadata_; + return *this; +} NearbyShareDecryptedPublicCertificate::NearbyShareDecryptedPublicCertificate( NearbyShareDecryptedPublicCertificate&&) = default; + NearbyShareDecryptedPublicCertificate& NearbyShareDecryptedPublicCertificate::operator=( NearbyShareDecryptedPublicCertificate&&) = default; @@ -206,3 +223,11 @@ return verifier.VerifyFinal(); } + +std::vector<uint8_t> +NearbyShareDecryptedPublicCertificate::HashAuthenticationToken( + base::span<const uint8_t> authentication_token) const { + return ComputeAuthenticationTokenHash( + authentication_token, + base::as_bytes(base::make_span(secret_key_->key()))); +}
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h index 77456ba..04b1499c 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h
@@ -14,6 +14,7 @@ #include "chrome/browser/nearby_sharing/certificates/nearby_share_encrypted_metadata_key.h" #include "chrome/browser/nearby_sharing/proto/encrypted_metadata.pb.h" #include "chrome/browser/nearby_sharing/proto/rpc_resources.pb.h" +#include "crypto/symmetric_key.h" // Stores decrypted metadata and crypto keys for the remote device that uploaded // this certificate to the Nearby Share server. Use DecryptPublicCertificate() @@ -32,9 +33,9 @@ const NearbyShareEncryptedMetadataKey& encrypted_metadata_key); NearbyShareDecryptedPublicCertificate( - const NearbyShareDecryptedPublicCertificate&); + const NearbyShareDecryptedPublicCertificate& other); NearbyShareDecryptedPublicCertificate& operator=( - const NearbyShareDecryptedPublicCertificate&); + const NearbyShareDecryptedPublicCertificate& other); NearbyShareDecryptedPublicCertificate( NearbyShareDecryptedPublicCertificate&&); NearbyShareDecryptedPublicCertificate& operator=( @@ -54,10 +55,17 @@ bool VerifySignature(base::span<const uint8_t> payload, base::span<const uint8_t> signature) const; + // Creates a hash of the |authentication_token|, using |secret_key_|. The use + // of HKDF and the output vector size is part of the Nearby Share protocol and + // conforms with the GmsCore implementation. + std::vector<uint8_t> HashAuthenticationToken( + base::span<const uint8_t> authentication_token) const; + private: NearbyShareDecryptedPublicCertificate( base::Time not_before, base::Time not_after, + std::unique_ptr<crypto::SymmetricKey> secret_key, std::vector<uint8_t> public_key, std::vector<uint8_t> id, nearbyshare::proto::EncryptedMetadata unencrypted_metadata); @@ -68,6 +76,10 @@ base::Time not_before_; base::Time not_after_; + // A 32-byte AES key that was used for metadata key and metadata decryption. + // Also, used to generate an authentication token hash. + std::unique_ptr<crypto::SymmetricKey> secret_key_; + // A P-256 public key used for verification. The bytes comprise a DER-encoded // ASN.1 SubjectPublicKeyInfo from the X.509 specification (RFC 5280). std::vector<uint8_t> public_key_;
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate_unittest.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate_unittest.cc index 8ce8d8ed..29ab6e85 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate_unittest.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate_unittest.cc
@@ -95,3 +95,12 @@ cert->VerifySignature(GetNearbyShareTestPayloadToSign(), /*signature=*/base::span<const uint8_t>())); } + +TEST(NearbyShareDecryptedPublicCertificateTest, HashAuthenticationToken) { + base::Optional<NearbyShareDecryptedPublicCertificate> cert = + NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate( + GetNearbyShareTestPublicCertificate(), + GetNearbyShareTestEncryptedMetadataKey()); + EXPECT_EQ(GetNearbyShareTestPayloadHashUsingSecretKey(), + cert->HashAuthenticationToken(GetNearbyShareTestPayloadToSign())); +}
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc index 5a6a24af..f9bcf3d 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc
@@ -248,6 +248,13 @@ return signature; } +std::vector<uint8_t> NearbySharePrivateCertificate::HashAuthenticationToken( + base::span<const uint8_t> authentication_token) const { + return ComputeAuthenticationTokenHash( + authentication_token, + base::as_bytes(base::make_span(secret_key_->key()))); +} + base::Optional<nearbyshare::proto::PublicCertificate> NearbySharePrivateCertificate::ToPublicCertificate() { std::vector<uint8_t> public_key;
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h index 85d5d62..7d05a18c 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.h
@@ -87,6 +87,12 @@ base::Optional<std::vector<uint8_t>> Sign( base::span<const uint8_t> payload) const; + // Creates a hash of the |authentication_token|, using |secret_key_|. The use + // of HKDF and the output vector size is part of the Nearby Share protocol and + // conforms with the GmsCore implementation. + std::vector<uint8_t> HashAuthenticationToken( + base::span<const uint8_t> authentication_token) const; + // Converts this private certificate to a public certificate proto that can be // shared with select contacts. Returns base::nullopt if the conversion was // unsuccessful. @@ -132,8 +138,9 @@ std::unique_ptr<crypto::ECPrivateKey> key_pair_; // A 32-byte AES key used, along with a salt, to encrypt the - // |metadata_encryption_key_|, after which it can be safely advertised. - // Included in the public certificate. + // |metadata_encryption_key_|, after which it can be safely advertised. Also, + // used to generate an authentication token hash. Included in the public + // certificate. std::unique_ptr<crypto::SymmetricKey> secret_key_; // A 14-byte symmetric key used to encrypt |unencrypted_metadata_|. Not
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate_unittest.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate_unittest.cc index e233d33..5cbdb63c 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate_unittest.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate_unittest.cc
@@ -143,3 +143,11 @@ EXPECT_TRUE(decrypted_public_certificate->VerifySignature( GetNearbyShareTestPayloadToSign(), *signature)); } + +TEST(NearbySharePrivateCertificateTest, HashAuthenticationToken) { + NearbySharePrivateCertificate private_certificate = + GetNearbyShareTestPrivateCertificate(NearbyShareVisibility::kAllContacts); + EXPECT_EQ(GetNearbyShareTestPayloadHashUsingSecretKey(), + private_certificate.HashAuthenticationToken( + GetNearbyShareTestPayloadToSign())); +}
diff --git a/chrome/browser/nearby_sharing/certificates/test_util.cc b/chrome/browser/nearby_sharing/certificates/test_util.cc index 553f925..ba16450 100644 --- a/chrome/browser/nearby_sharing/certificates/test_util.cc +++ b/chrome/browser/nearby_sharing/certificates/test_util.cc
@@ -110,6 +110,12 @@ // end s }; +// The result of HKDF of kTestPayloadToSign, using kTestSecretKey as salt. A +// trivial info parameter is used, and the output length is fixed to be +// kNearbyShareNumBytesAuthenticationTokenHash. +const uint8_t kTestPayloadHashUsingSecretKey[] = {0xE2, 0xCB, 0x90, + 0x58, 0xDE, 0x3A}; + const int64_t kTestNotBeforeMillis = 1881702000000; const int64_t kTestValidityOffsetMillis = 1800000; // 30 minutes @@ -215,6 +221,13 @@ return *signature; } +const std::vector<uint8_t>& GetNearbyShareTestPayloadHashUsingSecretKey() { + static const base::NoDestructor<std::vector<uint8_t>> hash( + std::begin(kTestPayloadHashUsingSecretKey), + std::end(kTestPayloadHashUsingSecretKey)); + return *hash; +} + NearbySharePrivateCertificate GetNearbyShareTestPrivateCertificate( NearbyShareVisibility visibility) { NearbySharePrivateCertificate cert(
diff --git a/chrome/browser/nearby_sharing/certificates/test_util.h b/chrome/browser/nearby_sharing/certificates/test_util.h index d21fd33f..467e8856 100644 --- a/chrome/browser/nearby_sharing/certificates/test_util.h +++ b/chrome/browser/nearby_sharing/certificates/test_util.h
@@ -38,6 +38,7 @@ const std::vector<uint8_t>& GetNearbyShareTestPayloadToSign(); const std::vector<uint8_t>& GetNearbyShareTestSampleSignature(); +const std::vector<uint8_t>& GetNearbyShareTestPayloadHashUsingSecretKey(); NearbySharePrivateCertificate GetNearbyShareTestPrivateCertificate( NearbyShareVisibility visibility);
diff --git a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc index 6cb86b0..a188111 100644 --- a/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_notification_manager_unittest.cc
@@ -623,7 +623,6 @@ manager()->OnTransferUpdate( share_target, TransferMetadataBuilder() .set_status(TransferMetadata::Status::kCancelled) - .set_is_final_status(true) .build()); // Notification should be closed.
diff --git a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.cc b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.cc index 99b59e4..89f68fa 100644 --- a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.cc +++ b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager.cc
@@ -44,6 +44,12 @@ /*token=*/base::nullopt, mojo::NullRemote()); break; default: + if (transfer_metadata.is_final_status() && + select_share_target_callback_) { + std::move(select_share_target_callback_) + .Run(nearby_share::mojom::SelectShareTargetResult::kError, + /*token=*/base::nullopt, mojo::NullRemote()); + } break; } } @@ -64,16 +70,6 @@ void NearbyPerSessionDiscoveryManager::StartDiscovery( mojo::PendingRemote<nearby_share::mojom::ShareTargetListener> listener, StartDiscoveryCallback callback) { - DCHECK(!share_target_listener_.is_bound()); - - if (nearby_sharing_service_->RegisterSendSurface( - this, this, NearbySharingService::SendSurfaceState::kForeground) != - NearbySharingService::StatusCodes::kOk) { - NS_LOG(WARNING) << "Failed to register send surface"; - std::move(callback).Run(/*success=*/false); - return; - } - share_target_listener_.Bind(std::move(listener)); // |share_target_listener_| owns the callbacks and is guaranteed to be // destroyed before |this|, therefore making base::Unretained() safe to use. @@ -81,12 +77,22 @@ base::BindOnce(&NearbyPerSessionDiscoveryManager::UnregisterSendSurface, base::Unretained(this))); + if (nearby_sharing_service_->RegisterSendSurface( + this, this, NearbySharingService::SendSurfaceState::kForeground) != + NearbySharingService::StatusCodes::kOk) { + NS_LOG(WARNING) << "Failed to register send surface"; + share_target_listener_.reset(); + std::move(callback).Run(/*success=*/false); + return; + } + std::move(callback).Run(/*success=*/true); } void NearbyPerSessionDiscoveryManager::SelectShareTarget( const base::UnguessableToken& share_target_id, SelectShareTargetCallback callback) { + DCHECK(share_target_listener_.is_bound()); DCHECK(!select_share_target_callback_); auto iter = discovered_share_targets_.find(share_target_id); @@ -108,7 +114,10 @@ void NearbyPerSessionDiscoveryManager::OnSend( NearbySharingService::StatusCodes status) { - DCHECK(select_share_target_callback_); + // Nothing to do if the result has been returned already. + if (!select_share_target_callback_) + return; + // If the send call succeeded, we expect OnTransferUpdate() to be called next. if (status == NearbySharingService::StatusCodes::kOk) return;
diff --git a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc index 627a105..e6ba17b0 100644 --- a/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_per_session_discovery_manager_unittest.cc
@@ -146,6 +146,12 @@ } TEST_F(NearbyPerSessionDiscoveryManagerTest, SelectShareTarget_Invalid) { + MockShareTargetListener listener; + EXPECT_CALL(sharing_service(), + RegisterSendSurface(testing::_, testing::_, testing::_)) + .WillOnce(testing::Return(NearbySharingService::StatusCodes::kOk)); + manager().StartDiscovery(listener.Bind(), base::DoNothing()); + MockSelectShareTargetCallback callback; EXPECT_CALL( callback,
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc index 83cde104..309a958 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.cc
@@ -565,12 +565,32 @@ return; } - // Once get the advertisement, first thing to do is to decrypt its device name - // based on its visibility and create a ShareTarget to represent this remote - // device. - // TODO(nmusgrave): Use valid certificate from certificate manager. + // Once get the advertisement, the first thing to do is decrypt the + // certificate. + std::vector<uint8_t> encrypted_metadata = advertisement->encrypted_metadata; + std::vector<uint8_t> salt = advertisement->salt; + + GetCertificateManager()->GetDecryptedPublicCertificate( + std::move(encrypted_metadata), std::move(salt), + base::BindOnce(&NearbySharingServiceImpl::OnOutgoingDecryptedCertificate, + weak_ptr_factory_.GetWeakPtr(), endpoint_id, + std::move(advertisement))); +} + +void NearbySharingServiceImpl::OnOutgoingDecryptedCertificate( + const std::string& endpoint_id, + sharing::mojom::AdvertisementPtr advertisement, + base::Optional<NearbyShareDecryptedPublicCertificate> certificate) { + // Check again for this endpoint id, to avoid race conditions. + if (outgoing_share_target_map_.find(endpoint_id) != + outgoing_share_target_map_.end()) { + return; + } + + // The certificate provides the device name, in order to create a ShareTarget + // to represent this remote device. base::Optional<ShareTarget> share_target = CreateShareTarget( - endpoint_id, std::move(advertisement), /*certificate=*/base::nullopt, + endpoint_id, std::move(advertisement), std::move(certificate), /*is_incoming=*/false); if (!share_target) { NS_LOG(VERBOSE) << __func__ @@ -1129,12 +1149,20 @@ TransferMetadata metadata) { if (metadata.status() != TransferMetadata::Status::kCancelled && metadata.status() != TransferMetadata::Status::kRejected) { - last_incoming_metadata_ = std::make_pair(share_target, metadata); + last_incoming_metadata_ = + std::make_pair(share_target, TransferMetadataBuilder::Clone(metadata) + .set_is_original(false) + .build()); } else { last_incoming_metadata_ = base::nullopt; } - // TODO(himanshujaju) - Handle is_final_status() + if (metadata.is_final_status()) { + OnTransferComplete(); + } else if (metadata.status() == + TransferMetadata::Status::kAwaitingLocalConfirmation) { + OnTransferStarted(/*is_incoming=*/true); + } base::ObserverList<TransferUpdateCallback>& transfer_callbacks = foreground_receive_callbacks_.might_have_observers() @@ -1146,6 +1174,28 @@ } } +void NearbySharingServiceImpl::OnTransferComplete() { + is_receiving_files_ = false; + is_transferring_ = false; + is_sending_files_ = false; + + NS_LOG(VERBOSE) << __func__ + << ": NearbySharing state change transfer finished"; + // TODO(himanshujaju) - Check if we need to delay InvalidateSurfaceState() + // similar to GmsCore impl. + InvalidateSurfaceState(); +} + +void NearbySharingServiceImpl::OnTransferStarted(bool is_incoming) { + is_transferring_ = true; + if (is_incoming) { + is_receiving_files_ = true; + } else { + is_sending_files_ = true; + } + InvalidateSurfaceState(); +} + NearbySharingService::StatusCodes NearbySharingServiceImpl::ReceivePayloads( const ShareTarget& share_target) { mutual_acceptance_timeout_alarm_.Cancel();
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h index 8274ee51..d55c046 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl.h
@@ -141,6 +141,10 @@ void OnOutgoingAdvertisementDecoded( const std::string& endpoint_id, sharing::mojom::AdvertisementPtr advertisement); + void OnOutgoingDecryptedCertificate( + const std::string& endpoint_id, + sharing::mojom::AdvertisementPtr advertisement, + base::Optional<NearbyShareDecryptedPublicCertificate> certificate); bool IsBluetoothPresent() const; bool IsBluetoothPowered() const; bool HasAvailableConnectionMediums(); @@ -155,6 +159,9 @@ void InvalidateAdvertisingState(); void StopAdvertising(); + void OnTransferComplete(); + void OnTransferStarted(bool is_incoming); + StatusCodes ReceivePayloads(const ShareTarget& share_target); StatusCodes SendPayloads(const ShareTarget& share_target); @@ -284,6 +291,8 @@ bool is_transferring_ = false; // True if we're currently receiving a file. bool is_receiving_files_ = false; + // True if we're currently sending a file. + bool is_sending_files_ = false; // True if we're currently attempting to connect to a remote device. bool is_connecting_ = false; // The time scanning began.
diff --git a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc index a1f980e..9645f8b 100644 --- a/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc +++ b/chrome/browser/nearby_sharing/nearby_sharing_service_impl_unittest.cc
@@ -397,6 +397,7 @@ TransferMetadata metadata) { EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation, metadata.status()); + EXPECT_FALSE(metadata.is_final_status()); share_target = incoming_share_target; run_loop.Quit(); })); @@ -714,6 +715,7 @@ // Ensure decoder parses a valid endpoint advertisement. SetUpAdvertisementDecoder(kValidV1EndpointInfo, /*return_empty_advertisement=*/false); + SetUpCertificateManager(/*return_empty_certificate=*/false); // Start discovering, to ensure a discovery listener is registered. base::RunLoop run_loop; @@ -725,10 +727,77 @@ SendSurfaceState::kForeground)); EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); - // Discover a new endpoint. + // Discover a new endpoint, with fields set up a valid certificate. EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) .WillOnce([&run_loop](ShareTarget share_target) { + EXPECT_FALSE(share_target.is_incoming); + EXPECT_TRUE(share_target.is_known); + EXPECT_FALSE(share_target.has_attachments()); EXPECT_EQ(kDeviceName, share_target.device_name); + EXPECT_EQ(GURL(kTestMetadataIconUrl), share_target.image_url); + EXPECT_EQ(nearby_share::mojom::ShareTargetType::kUnknown, + share_target.type); + EXPECT_TRUE(share_target.device_id); + EXPECT_NE(kEndpointId, share_target.device_id); + EXPECT_EQ(kTestMetadataFullName, share_target.full_name); + run_loop.Quit(); + }); + fake_nearby_connections_manager_->OnEndpointFound( + kEndpointId, + location::nearby::connections::mojom::DiscoveredEndpointInfo::New( + kValidV1EndpointInfo, kServiceId)); + run_loop.Run(); + + // Register another send surface, which will automatically catch up discovered + // endpoints. + base::RunLoop run_loop2; + MockTransferUpdateCallback transfer_callback2; + NiceMock<MockShareTargetDiscoveredCallback> discovery_callback2; + EXPECT_CALL(discovery_callback2, OnShareTargetDiscovered) + .WillOnce([&run_loop2](ShareTarget share_target) { + EXPECT_EQ(kDeviceName, share_target.device_name); + run_loop2.Quit(); + }); + + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback2, &discovery_callback2, + SendSurfaceState::kForeground)); + run_loop2.Run(); +} + +TEST_F(NearbySharingServiceImplTest, RegisterSendSurfaceEmptyCertificate) { + ui::ScopedSetIdleState unlocked(ui::IDLE_STATE_IDLE); + SetConnectionType(net::NetworkChangeNotifier::CONNECTION_WIFI); + + // Ensure decoder parses a valid endpoint advertisement. + SetUpAdvertisementDecoder(kValidV1EndpointInfo, + /*return_empty_advertisement=*/false); + SetUpCertificateManager(/*return_empty_certificate=*/true); + + // Start discovering, to ensure a discovery listener is registered. + base::RunLoop run_loop; + MockTransferUpdateCallback transfer_callback; + NiceMock<MockShareTargetDiscoveredCallback> discovery_callback; + EXPECT_EQ( + NearbySharingService::StatusCodes::kOk, + service_->RegisterSendSurface(&transfer_callback, &discovery_callback, + SendSurfaceState::kForeground)); + EXPECT_TRUE(fake_nearby_connections_manager_->IsDiscovering()); + + // Discover a new endpoint, with fields set up a valid certificate. + EXPECT_CALL(discovery_callback, OnShareTargetDiscovered) + .WillOnce([&run_loop](ShareTarget share_target) { + EXPECT_FALSE(share_target.is_incoming); + EXPECT_FALSE(share_target.is_known); + EXPECT_FALSE(share_target.has_attachments()); + EXPECT_EQ(kDeviceName, share_target.device_name); + EXPECT_FALSE(share_target.image_url); + EXPECT_EQ(nearby_share::mojom::ShareTargetType::kUnknown, + share_target.type); + EXPECT_TRUE(share_target.device_id); + EXPECT_EQ(kEndpointId, share_target.device_id); + EXPECT_FALSE(share_target.full_name); run_loop.Quit(); }); fake_nearby_connections_manager_->OnEndpointFound( @@ -1307,6 +1376,7 @@ EXPECT_EQ(TransferMetadata::Status::kUnsupportedAttachmentType, metadata.status()); + EXPECT_TRUE(metadata.is_final_status()); run_loop.Quit(); })); @@ -1359,6 +1429,7 @@ EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation, metadata.status()); + EXPECT_FALSE(metadata.is_final_status()); run_loop.Quit(); })); @@ -1383,6 +1454,7 @@ .WillOnce(testing::Invoke([&run_loop_2](const ShareTarget& share_target, TransferMetadata metadata) { EXPECT_EQ(TransferMetadata::Status::kFailed, metadata.status()); + EXPECT_TRUE(metadata.is_final_status()); run_loop_2.Quit(); })); @@ -1421,6 +1493,7 @@ EXPECT_EQ(TransferMetadata::Status::kAwaitingLocalConfirmation, metadata.status()); + EXPECT_FALSE(metadata.is_final_status()); run_loop.Quit(); })); @@ -1460,6 +1533,7 @@ [](const ShareTarget& share_target, TransferMetadata metadata) { EXPECT_EQ(TransferMetadata::Status::kAwaitingRemoteAcceptance, metadata.status()); + EXPECT_FALSE(metadata.is_final_status()); })); service_->Accept(share_target, @@ -1512,6 +1586,7 @@ .WillOnce(testing::Invoke( [](const ShareTarget& share_target, TransferMetadata metadata) { EXPECT_EQ(TransferMetadata::Status::kRejected, metadata.status()); + EXPECT_TRUE(metadata.is_final_status()); })); service_->Reject(share_target,
diff --git a/chrome/browser/nearby_sharing/transfer_metadata.cc b/chrome/browser/nearby_sharing/transfer_metadata.cc index 2eb708a..b2b033b3 100644 --- a/chrome/browser/nearby_sharing/transfer_metadata.cc +++ b/chrome/browser/nearby_sharing/transfer_metadata.cc
@@ -6,6 +6,25 @@ #include "chrome/browser/nearby_sharing/transfer_metadata.h" +// static +bool TransferMetadata::IsFinalStatus(Status status) { + switch (status) { + case Status::kAwaitingRemoteAcceptanceFailed: + case Status::kComplete: + case Status::kFailed: + case Status::kRejected: + case Status::kCancelled: + case Status::kTimedOut: + case Status::kMediaUnavailable: + case Status::kNotEnoughSpace: + case Status::kUnsupportedAttachmentType: + case Status::kExternalProviderLaunched: + return true; + default: + return false; + } +} + TransferMetadata::TransferMetadata(Status status, float progress, base::Optional<std::string> token,
diff --git a/chrome/browser/nearby_sharing/transfer_metadata.h b/chrome/browser/nearby_sharing/transfer_metadata.h index 39772961..5859fab 100644 --- a/chrome/browser/nearby_sharing/transfer_metadata.h +++ b/chrome/browser/nearby_sharing/transfer_metadata.h
@@ -34,6 +34,8 @@ kMaxValue = kExternalProviderLaunched }; + static bool IsFinalStatus(Status status); + TransferMetadata(Status status, float progress, base::Optional<std::string> token,
diff --git a/chrome/browser/nearby_sharing/transfer_metadata_builder.cc b/chrome/browser/nearby_sharing/transfer_metadata_builder.cc index 4b457f5c..122ab5c2 100644 --- a/chrome/browser/nearby_sharing/transfer_metadata_builder.cc +++ b/chrome/browser/nearby_sharing/transfer_metadata_builder.cc
@@ -4,13 +4,30 @@ #include "chrome/browser/nearby_sharing/transfer_metadata_builder.h" +// static +TransferMetadataBuilder TransferMetadataBuilder::Clone( + const TransferMetadata& metadata) { + TransferMetadataBuilder builder; + builder.is_original_ = metadata.is_original(); + builder.progress_ = metadata.progress(); + builder.status_ = metadata.status(); + builder.token_ = metadata.token(); + return builder; +} + TransferMetadataBuilder::TransferMetadataBuilder() = default; +TransferMetadataBuilder::TransferMetadataBuilder(TransferMetadataBuilder&&) = + default; + +TransferMetadataBuilder& TransferMetadataBuilder::operator=( + TransferMetadataBuilder&&) = default; + TransferMetadataBuilder::~TransferMetadataBuilder() = default; -TransferMetadataBuilder& TransferMetadataBuilder::set_is_final_status( - bool is_final_status) { - is_final_status_ = is_final_status; +TransferMetadataBuilder& TransferMetadataBuilder::set_is_original( + bool is_original) { + is_original_ = is_original; return *this; } @@ -33,6 +50,6 @@ } TransferMetadata TransferMetadataBuilder::build() const { - return TransferMetadata(status_, progress_, token_, - /*is_original=*/false, is_final_status_); + return TransferMetadata(status_, progress_, token_, is_original_, + TransferMetadata::IsFinalStatus(status_)); }
diff --git a/chrome/browser/nearby_sharing/transfer_metadata_builder.h b/chrome/browser/nearby_sharing/transfer_metadata_builder.h index 413efd4b6..125a088 100644 --- a/chrome/browser/nearby_sharing/transfer_metadata_builder.h +++ b/chrome/browser/nearby_sharing/transfer_metadata_builder.h
@@ -12,10 +12,14 @@ class TransferMetadataBuilder { public: + static TransferMetadataBuilder Clone(const TransferMetadata& metadata); + TransferMetadataBuilder(); + TransferMetadataBuilder(TransferMetadataBuilder&&); + TransferMetadataBuilder& operator=(TransferMetadataBuilder&&); ~TransferMetadataBuilder(); - TransferMetadataBuilder& set_is_final_status(bool is_final_status); + TransferMetadataBuilder& set_is_original(bool is_original); TransferMetadataBuilder& set_progress(double progress); @@ -26,7 +30,7 @@ TransferMetadata build() const; private: - bool is_final_status_ = false; + bool is_original_ = false; double progress_ = 0; TransferMetadata::Status status_ = TransferMetadata::Status::kInProgress; base::Optional<std::string> token_;
diff --git a/chrome/browser/password_check/android/password_check_manager_unittest.cc b/chrome/browser/password_check/android/password_check_manager_unittest.cc index ffcaab0..f3421f2e 100644 --- a/chrome/browser/password_check/android/password_check_manager_unittest.cc +++ b/chrome/browser/password_check/android/password_check_manager_unittest.cc
@@ -8,6 +8,8 @@ #include "base/bind.h" #include "base/memory/scoped_refptr.h" +#include "base/optional.h" +#include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind_test_util.h" #include "chrome/browser/password_check/android/password_check_ui_status.h" @@ -15,7 +17,6 @@ #include "chrome/browser/password_manager/password_store_factory.h" #include "chrome/test/base/testing_profile.h" #include "components/password_manager/core/browser/bulk_leak_check_service.h" -#include "components/password_manager/core/browser/mock_bulk_leak_check_service.h" #include "components/password_manager/core/browser/password_manager_test_utils.h" #include "components/password_manager/core/browser/test_password_store.h" #include "components/signin/public/identity_manager/identity_manager.h" @@ -30,15 +31,21 @@ using password_manager::BulkLeakCheckService; using password_manager::CompromisedCredentials; using password_manager::CompromiseType; -using password_manager::MockBulkLeakCheckService; using password_manager::PasswordCheckUIStatus; using password_manager::TestPasswordStore; using testing::_; +using testing::ElementsAre; +using testing::Field; +using testing::IsEmpty; using testing::NiceMock; +using CompromisedCredentialForUI = + PasswordCheckManager::CompromisedCredentialForUI; + namespace { constexpr char kExampleCom[] = "https://example.com"; +constexpr char kExampleApp[] = "com.example.app"; constexpr char kUsername1[] = "alice"; constexpr char kUsername2[] = "bob"; @@ -95,6 +102,22 @@ return form; } +std::string MakeAndroidRealm(base::StringPiece package_name) { + return base::StrCat({"android://hash@", package_name}); +} +PasswordForm MakeSavedAndroidPassword( + base::StringPiece package_name, + base::StringPiece username, + base::StringPiece app_display_name = "", + base::StringPiece affiliated_web_realm = "") { + PasswordForm form; + form.signon_realm = MakeAndroidRealm(package_name); + form.username_value = base::ASCIIToUTF16(username); + form.app_display_name = std::string(app_display_name); + form.affiliated_web_realm = std::string(affiliated_web_realm); + return form; +} + CompromisedCredentials MakeCompromised( base::StringPiece signon_realm, base::StringPiece username, @@ -108,6 +131,33 @@ }; } +// Creates matcher for a given compromised credential +auto ExpectCompromisedCredentialForUI( + const base::string16& display_username, + const base::string16& display_origin, + const base::Optional<std::string>& package_name, + const base::Optional<std::string>& change_password_url, + bool is_android_credential, + bool has_script) { + auto package_name_field_matcher = + package_name.has_value() + ? Field(&CompromisedCredentialForUI::package_name, + package_name.value()) + : Field(&CompromisedCredentialForUI::package_name, IsEmpty()); + auto change_password_url_field_matcher = + change_password_url.has_value() + ? Field(&CompromisedCredentialForUI::change_password_url, + change_password_url.value()) + : Field(&CompromisedCredentialForUI::change_password_url, IsEmpty()); + return AllOf( + Field(&CompromisedCredentialForUI::display_username, display_username), + Field(&CompromisedCredentialForUI::display_origin, display_origin), + package_name_field_matcher, change_password_url_field_matcher, + Field(&CompromisedCredentialForUI::is_android_credential, + is_android_credential), + Field(&CompromisedCredentialForUI::has_script, has_script)); +} + } // namespace class PasswordCheckManagerTest : public testing::Test { @@ -173,3 +223,44 @@ CompromiseType::kLeaked)); RunUntilIdle(); } + +TEST_F(PasswordCheckManagerTest, CorrectlyCreatesUIStructForSiteCredential) { + InitializeManager(); + store().AddLogin(MakeSavedPassword(kExampleCom, kUsername1)); + store().AddCompromisedCredentials(MakeCompromised(kExampleCom, kUsername1)); + RunUntilIdle(); + EXPECT_THAT( + manager_->GetCompromisedCredentials(), + ElementsAre(ExpectCompromisedCredentialForUI( + base::ASCIIToUTF16(kUsername1), base::ASCIIToUTF16("example.com"), + base::nullopt, "https://example.com/", + /*is_android_credential=*/false, /*has_script=*/false))); +} + +TEST_F(PasswordCheckManagerTest, CorrectlyCreatesUIStructForAppCredentials) { + InitializeManager(); + // A credential without affiliation information. + store().AddLogin(MakeSavedAndroidPassword(kExampleApp, kUsername1)); + // A credential for which affiliation information is known. + store().AddLogin(MakeSavedAndroidPassword(kExampleApp, kUsername2, + "Example App", kExampleCom)); + store().AddCompromisedCredentials( + MakeCompromised(MakeAndroidRealm(kExampleApp), kUsername1)); + store().AddCompromisedCredentials( + MakeCompromised(MakeAndroidRealm(kExampleApp), kUsername2)); + + RunUntilIdle(); + + EXPECT_THAT( + manager_->GetCompromisedCredentials(), + ElementsAre( + ExpectCompromisedCredentialForUI( + base::ASCIIToUTF16(kUsername1), + base::ASCIIToUTF16("App (com.example.app)"), "com.example.app", + base::nullopt, /*is_android_credential=*/true, + /*has_script=*/false), + ExpectCompromisedCredentialForUI( + base::ASCIIToUTF16(kUsername2), base::ASCIIToUTF16("Example App"), + "com.example.app", base::nullopt, /*is_android_credential=*/true, + /*has_script=*/false))); +}
diff --git a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc index a5ac123..10d0e344 100644 --- a/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc +++ b/chrome/browser/printing/print_preview_pdf_generated_browsertest.cc
@@ -389,7 +389,8 @@ ASSERT_TRUE(chrome_pdf::RenderPDFPageToBitmap( pdf_span, i, page_bitmap_data.data(), settings.area.size().width(), settings.area.size().height(), settings.dpi.width(), - settings.dpi.height(), settings.autorotate, settings.use_color)); + settings.dpi.height(), false, true, settings.autorotate, + settings.use_color)); FillPng(&page_bitmap_data, width_in_pixels, max_width_in_pixels, settings.area.size().height()); bitmap_data.insert(bitmap_data.end(),
diff --git a/chrome/browser/resources/inspect/OWNERS b/chrome/browser/resources/inspect/OWNERS index 13224fd71..82d9348f 100644 --- a/chrome/browser/resources/inspect/OWNERS +++ b/chrome/browser/resources/inspect/OWNERS
@@ -1,5 +1,7 @@ dgozman@chromium.org pfeldman@chromium.org yangguo@chromium.org +petermarshall@chromium.org +sigurds@chromium.org # COMPONENT: Platform>DevTools
diff --git a/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.html b/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.html index 8166c0c1..4995387 100644 --- a/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.html +++ b/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.html
@@ -55,7 +55,9 @@ } #chevronIcon { + height: 16px; margin: 0 16px; + width: 16px; } :host-context([dir=rtl]) #chevronIcon {
diff --git a/chrome/browser/resources/signin/profile_picker/BUILD.gn b/chrome/browser/resources/signin/profile_picker/BUILD.gn index 25f9d0b..be443e29 100644 --- a/chrome/browser/resources/signin/profile_picker/BUILD.gn +++ b/chrome/browser/resources/signin/profile_picker/BUILD.gn
@@ -43,6 +43,7 @@ deps = [ "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", "//ui/webui/resources/js:assert.m", + "//ui/webui/resources/js:load_time_data.m", ] }
diff --git a/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js b/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js index 2ddbbb2..c59bfa2 100644 --- a/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js +++ b/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js
@@ -9,7 +9,7 @@ * @typedef {{ * profilePath: string, * localProfileName: string, - * isSignedIn: Boolean, + * isSignedIn: boolean, * gaiaName: string, * userName: string, * avatarIcon: string, @@ -62,6 +62,12 @@ */ getProfileStatistics(profilePath) {} + /** + * Removes profile. + * @param {string} profilePath + */ + removeProfile(profilePath) {} + /** Loads Google sign in page.*/ loadSignInProfileCreationFlow() {} } @@ -94,6 +100,11 @@ } /** @override */ + removeProfile(profilePath) { + chrome.send('removeProfile', [profilePath]); + } + + /** @override */ getProfileStatistics(profilePath) { chrome.send('getProfileStatistics', [profilePath]); }
diff --git a/chrome/browser/resources/signin/profile_picker/navigation_behavior.js b/chrome/browser/resources/signin/profile_picker/navigation_behavior.js index 7bc103a..97f5175e 100644 --- a/chrome/browser/resources/signin/profile_picker/navigation_behavior.js +++ b/chrome/browser/resources/signin/profile_picker/navigation_behavior.js
@@ -3,6 +3,9 @@ // found in the LICENSE file. import {assert, assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; + +import './strings.js'; /** * Valid route pathnames. @@ -36,6 +39,7 @@ // TODO(msalama): Add support in profile creation mode for policies like: // - ForceSignIn --> load signin page directly. // - DisallowSignIn --> open local profile customization. + // - Check |signInProfileCreationFlow| is not enabled. return ProfileCreationSteps.PROFILE_TYPE_CHOICE; default: assertNotReached();
diff --git a/chrome/browser/resources/signin/profile_picker/profile_card_menu.html b/chrome/browser/resources/signin/profile_picker/profile_card_menu.html index 9a90116..b193eeb 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_card_menu.html +++ b/chrome/browser/resources/signin/profile_picker/profile_card_menu.html
@@ -18,6 +18,7 @@ } #removeConfirmation { + color: var(--cr-primary-text-color); margin-top: 16px; pointer-events: none; width: 234px; @@ -60,7 +61,7 @@ --bg-action: var(--google-red-700); --hover-bg-action: rgba(var(--google-red-700-rgb), .9); --hover-shadow-action-rgb: var(--google-red-500-rgb); - background-color: var(--google-red-700); + background-color: var(--bg-action); border-radius: 4px; color: var(--ink-color-action); font-weight: 500; @@ -81,13 +82,13 @@ aria-label$="[[profileMenuText_]]"> </cr-icon-button> -<cr-action-menu id="actionMenu" role-description="menu"> +<cr-action-menu id="actionMenu" role-description="$i18n{menu}"> <button class="dropdown-item" on-click="onRemoveButtonClicked_"> $i18n{profileMenuRemoveText} </button> </cr-action-menu> -<cr-action-menu id="removeActionMenu" role-description="menu"> +<cr-action-menu id="removeActionMenu" role-description="$i18n{menu}"> <div id="removeConfirmation"> <div class="header"> $i18n{profileMenuRemoveText}
diff --git a/chrome/browser/resources/signin/profile_picker/profile_card_menu.js b/chrome/browser/resources/signin/profile_picker/profile_card_menu.js index 0a2358d..a3f0f55 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_card_menu.js +++ b/chrome/browser/resources/signin/profile_picker/profile_card_menu.js
@@ -86,11 +86,13 @@ ], }, + /** @private */ profileMenuText_: { type: String, computed: 'computeProfileMenuText_(profileState)', }, + /** @private */ removeWarningText_: { type: String, computed: 'computeRemoveWarningText_(profileState)', @@ -109,6 +111,10 @@ /** @override */ attached() { this.addWebUIListener( + 'profiles-list-changed', () => this.handleProfilesUpdated_()); + this.addWebUIListener( + 'profile-removed', () => this.handleProfilesUpdated_()); + this.addWebUIListener( 'profile-statistics-received', this.handleProfileStatsReceived_.bind(this)); }, @@ -126,10 +132,9 @@ * @private */ computeRemoveWarningText_() { - if (this.profileState.isSignedIn) { - return this.i18n('removeWarningSignedInProfile'); - } - return this.i18n('removeWarningLocalProfile'); + return this.i18n( + this.profileState.isSignedIn ? 'removeWarningSignedInProfile' : + 'removeWarningLocalProfile'); }, /** @@ -168,7 +173,7 @@ }, /** - * @param {string} dataType + * @param {ProfileStatistics} dataType * @return {string} * @private */ @@ -205,6 +210,16 @@ onRemoveComfirationClicked_(e) { e.stopPropagation(); e.preventDefault(); - // TODO(crbug.com/1063856): Add implementation. + this.manageProfilesBrowserProxy_.removeProfile( + this.profileState.profilePath); + }, + + /** + * Ensure any menu is closed on profile list updated. + * @private + */ + handleProfilesUpdated_() { + this.$.actionMenu.close(); + this.$.removeActionMenu.close(); }, });
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js b/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js index 4b2facb..d161b9b3 100644 --- a/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js +++ b/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.js
@@ -56,6 +56,8 @@ attached() { this.addWebUIListener( 'profiles-list-changed', this.handleProfilesListChanged_.bind(this)); + this.addWebUIListener( + 'profile-removed', this.handleProfileRemoved_.bind(this)); this.manageProfilesBrowserProxy_.initializeMainView(); }, @@ -97,4 +99,15 @@ onLaunchGuestProfileClick_() { this.manageProfilesBrowserProxy_.launchGuestProfile(); }, + + /** @private */ + handleProfileRemoved_(profilePath) { + for (let i = 0; i < this.profilesList_.length; i += 1) { + if (this.profilesList_[i].profilePath === profilePath) { + // TODO(crbug.com/1063856): Add animation. + this.splice('profilesList_', i, 1); + break; + } + } + }, });
diff --git a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc index c8bc4ea..2dd5348 100644 --- a/chrome/browser/sync/test/integration/profile_sync_service_harness.cc +++ b/chrome/browser/sync/test/integration/profile_sync_service_harness.cc
@@ -9,6 +9,7 @@ #include <utility> #include "base/command_line.h" +#include "base/feature_list.h" #include "base/json/json_writer.h" #include "base/logging.h" #include "base/memory/ptr_util.h" @@ -24,6 +25,7 @@ #include "components/signin/public/identity_manager/identity_manager.h" #include "components/signin/public/identity_manager/identity_test_utils.h" #include "components/sync/driver/about_sync_util.h" +#include "components/sync/driver/sync_driver_switches.h" #include "components/sync/engine/sync_string_conversions.h" #include "components/sync/engine_impl/net/url_translator.h" #include "components/sync/engine_impl/traffic_logger.h" @@ -256,6 +258,10 @@ void ProfileSyncServiceHarness::ExitSyncPausedStateForPrimaryAccount() { signin::SetRefreshTokenForPrimaryAccount( IdentityManagerFactory::GetForProfile(profile_)); + if (base::FeatureList::IsEnabled(switches::kStopSyncInPausedState)) { + // The engine was off in the sync-paused state, so wait for it to start. + AwaitSyncSetupCompletion(); + } } bool ProfileSyncServiceHarness::SetupSync() {
diff --git a/chrome/browser/ui/ash/clipboard_history_browsertest.cc b/chrome/browser/ui/ash/clipboard_history_browsertest.cc index c98f5f4..ecabae9 100644 --- a/chrome/browser/ui/ash/clipboard_history_browsertest.cc +++ b/chrome/browser/ui/ash/clipboard_history_browsertest.cc
@@ -110,10 +110,10 @@ base::test::ScopedFeatureList feature_list_; }; -// Verify that the clipboard data history belonging to different users does not -// interfere with each other. +// Verify that the clipboard data history is recorded as expected in the +// Multiuser environment. IN_PROC_BROWSER_TEST_F(ClipboardHistoryWithMultiProfileBrowserTest, - DisconflictInMultiUser) { + VerifyClipboardHistoryAcrossMultiUser) { LoginUser(account_id1_); EXPECT_TRUE(GetClipboardData().empty()); @@ -127,10 +127,10 @@ EXPECT_EQ(copypaste_data1, data.front().text()); } - // Log in as the user2. The clipboard history should be empty. + // Log in as the user2. The clipboard history should be non-empty. chromeos::UserAddingScreen::Get()->Start(); AddUser(account_id2_); - EXPECT_TRUE(GetClipboardData().empty()); + EXPECT_FALSE(GetClipboardData().empty()); // Store text when the user2 is active. const std::string copypaste_data2("user2_text1"); @@ -138,7 +138,7 @@ { const std::list<ui::ClipboardData>& data = GetClipboardData(); - EXPECT_EQ(1u, data.size()); + EXPECT_EQ(2u, data.size()); EXPECT_EQ(copypaste_data2, data.front().text()); } @@ -151,7 +151,7 @@ { const std::list<ui::ClipboardData>& data = GetClipboardData(); - EXPECT_EQ(2u, data.size()); + EXPECT_EQ(3u, data.size()); // Note that items in |data| follow the time ordering. The most recent item // is always the first one. @@ -159,6 +159,9 @@ EXPECT_EQ(copypaste_data3, it->text()); std::advance(it, 1u); + EXPECT_EQ(copypaste_data2, it->text()); + + std::advance(it, 1u); EXPECT_EQ(copypaste_data1, it->text()); } }
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc index d4a699b..e804f54 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller.cc
@@ -289,6 +289,8 @@ "PasswordManager.AccountStorage.MoveToAccountStoreFlowOffered", password_manager::metrics_util::MoveToAccountStoreTrigger:: kSuccessfulLoginWithProfileStorePassword); + if (!GetPasswordFeatureManager()->IsOptedInForAccountStorage()) + GetPasswordFeatureManager()->RecordMoveOfferedToNonOptedInUser(); passwords_data_.OnPasswordMovable(std::move(form_to_move)); // TODO(crbug.com/1100814): Add smartness like OnPasswordSubmitted? bubble_status_ = BubbleStatus::SHOULD_POP_UP;
diff --git a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc index a1cc273..6730055 100644 --- a/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc +++ b/chrome/browser/ui/passwords/manage_passwords_ui_controller_unittest.cc
@@ -1636,6 +1636,8 @@ // A submitted form triggers the move dialog. EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()) .Times(AtLeast(1)); + EXPECT_CALL(*client().GetPasswordFeatureManager(), + RecordMoveOfferedToNonOptedInUser); controller()->OnShowMoveToAccountBubble(std::move(test_form_manager)); EXPECT_TRUE(controller()->opened_automatic_bubble()); ExpectIconAndControllerStateIs( @@ -1662,6 +1664,8 @@ // A submitted form triggers the move dialog. EXPECT_CALL(*controller(), OnUpdateBubbleAndIconVisibility()); + EXPECT_CALL(*client().GetPasswordFeatureManager(), + RecordMoveOfferedToNonOptedInUser); controller()->OnShowMoveToAccountBubble(std::move(test_form_manager)); EXPECT_TRUE(controller()->opened_automatic_bubble()); ExpectIconAndControllerStateIs(
diff --git a/chrome/browser/ui/tabs/tab_group_controller.h b/chrome/browser/ui/tabs/tab_group_controller.h index 38c4428..0bb1b16d 100644 --- a/chrome/browser/ui/tabs/tab_group_controller.h +++ b/chrome/browser/ui/tabs/tab_group_controller.h
@@ -18,6 +18,7 @@ class TabGroupController { public: virtual void CreateTabGroup(const tab_groups::TabGroupId& group) = 0; + virtual void OpenTabGroupEditor(const tab_groups::TabGroupId& group) = 0; virtual void ChangeTabGroupContents(const tab_groups::TabGroupId& group) = 0; virtual void ChangeTabGroupVisuals(const tab_groups::TabGroupId& group) = 0; virtual void MoveTabGroup(const tab_groups::TabGroupId& group) = 0;
diff --git a/chrome/browser/ui/tabs/tab_strip_model.cc b/chrome/browser/ui/tabs/tab_strip_model.cc index 155570d7..67198c3 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.cc +++ b/chrome/browser/ui/tabs/tab_strip_model.cc
@@ -1041,6 +1041,7 @@ const tab_groups::TabGroupId new_group = tab_groups::TabGroupId::GenerateNew(); AddToNewGroupImpl(indices, new_group); + OpenTabGroupEditor(new_group); return new_group; } @@ -1124,6 +1125,12 @@ observer.OnTabGroupChanged(change); } +void TabStripModel::OpenTabGroupEditor(const tab_groups::TabGroupId& group) { + TabGroupChange change(group, TabGroupChange::kEditorOpened); + for (auto& observer : observers_) + observer.OnTabGroupChanged(change); +} + void TabStripModel::ChangeTabGroupContents( const tab_groups::TabGroupId& group) { TabGroupChange change(group, TabGroupChange::kContentsChanged);
diff --git a/chrome/browser/ui/tabs/tab_strip_model.h b/chrome/browser/ui/tabs/tab_strip_model.h index 6a445c9..a8b4ddfe 100644 --- a/chrome/browser/ui/tabs/tab_strip_model.h +++ b/chrome/browser/ui/tabs/tab_strip_model.h
@@ -463,6 +463,7 @@ // TabGroupController: void CreateTabGroup(const tab_groups::TabGroupId& group) override; + void OpenTabGroupEditor(const tab_groups::TabGroupId& group) override; void ChangeTabGroupContents(const tab_groups::TabGroupId& group) override; void ChangeTabGroupVisuals(const tab_groups::TabGroupId& group) override; void MoveTabGroup(const tab_groups::TabGroupId& group) override;
diff --git a/chrome/browser/ui/tabs/tab_strip_model_observer.h b/chrome/browser/ui/tabs/tab_strip_model_observer.h index 6218040..a168383d 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_observer.h +++ b/chrome/browser/ui/tabs/tab_strip_model_observer.h
@@ -199,7 +199,14 @@ // a kContentsChange event is fired. Whenever the group's visual data changes, // such as its title or color, a kVisualsChange event is fired. Whenever the // group is moved by interacting with its header, a kMoved event is fired. - enum Type { kCreated, kContentsChanged, kVisualsChanged, kMoved, kClosed }; + enum Type { + kCreated, + kEditorOpened, + kContentsChanged, + kVisualsChanged, + kMoved, + kClosed + }; TabGroupChange(tab_groups::TabGroupId group, Type type); ~TabGroupChange();
diff --git a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc index f31ce31..efdc861 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
@@ -285,6 +285,9 @@ group_updates_[change.group] = TabGroupUpdate(); break; } + case TabGroupChange::kEditorOpened: { + break; + } case TabGroupChange::kContentsChanged: { group_updates_[change.group].contents_update_count++; break;
diff --git a/chrome/browser/ui/ui_features.cc b/chrome/browser/ui/ui_features.cc index 130fc24..a2bf3480 100644 --- a/chrome/browser/ui/ui_features.cc +++ b/chrome/browser/ui/ui_features.cc
@@ -59,6 +59,11 @@ const base::Feature kScrollableTabStrip{"ScrollableTabStrip", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables the signin promo page for the profile creation flow. +// https:://crbug.com/1105865 +const base::Feature kSignInProfileCreationFlow{ + "SignInProfileCreationFlow", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables grouping tabs together in the tab strip. https://crbug.com/905491 const base::Feature kTabGroups{"TabGroups", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/chrome/browser/ui/ui_features.h b/chrome/browser/ui/ui_features.h index de85992..97ec57d 100644 --- a/chrome/browser/ui/ui_features.h +++ b/chrome/browser/ui/ui_features.h
@@ -42,6 +42,8 @@ extern const base::Feature kScrollableTabStrip; +extern const base::Feature kSignInProfileCreationFlow; + extern const base::Feature kTabGroups; extern const base::Feature kTabGroupsCollapse;
diff --git a/chrome/browser/ui/views/download/download_shelf_view.cc b/chrome/browser/ui/views/download/download_shelf_view.cc index c5b942a..9fe2826 100644 --- a/chrome/browser/ui/views/download/download_shelf_view.cc +++ b/chrome/browser/ui/views/download/download_shelf_view.cc
@@ -73,14 +73,15 @@ // cases, like when installing a theme. See DownloadShelf::AddDownload(). SetVisible(false); - auto show_all_view = std::make_unique<views::MdTextButton>( - this, l10n_util::GetStringUTF16(IDS_SHOW_ALL_DOWNLOADS)); - show_all_view_ = AddChildView(std::move(show_all_view)); + show_all_view_ = AddChildView(std::make_unique<views::MdTextButton>( + this, l10n_util::GetStringUTF16(IDS_SHOW_ALL_DOWNLOADS))); + show_all_view_->SizeToPreferredSize(); - auto close_button = views::CreateVectorImageButton(this); - close_button->SetAccessibleName(l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); - close_button->SetFocusForPlatform(); - close_button_ = AddChildView(std::move(close_button)); + close_button_ = AddChildView(views::CreateVectorImageButton(this)); + close_button_->SetAccessibleName( + l10n_util::GetStringUTF16(IDS_ACCNAME_CLOSE)); + close_button_->SetFocusForPlatform(); + close_button_->SizeToPreferredSize(); accessible_alert_ = AddChildView(std::make_unique<views::View>()); @@ -144,11 +145,9 @@ // Let our base class layout our child views views::View::Layout(); - gfx::Size close_button_size = close_button_->GetPreferredSize(); - gfx::Size show_all_size = show_all_view_->GetPreferredSize(); int max_download_x = - std::max<int>(0, width() - kEndPadding - close_button_size.width() - - kCloseAndLinkPadding - show_all_size.width()); + std::max<int>(0, width() - kEndPadding - close_button_->width() - + kCloseAndLinkPadding - show_all_view_->width()); // If there is not enough room to show the first download item, show the // "Show all downloads" link to the left to make it more visible that there is // something to see. @@ -161,12 +160,10 @@ return std::max((height - item_height) / 2, kTopPadding); }; - show_all_view_->SetBounds(next_x, center_y(show_all_size.height()), - show_all_size.width(), show_all_size.height()); - next_x += show_all_size.width() + kCloseAndLinkPadding; - close_button_->SizeToPreferredSize(); + show_all_view_->SetPosition({next_x, center_y(show_all_view_->height())}); close_button_->SetPosition( - gfx::Point(next_x, center_y(close_button_->height()))); + {show_all_view_->bounds().right() + kCloseAndLinkPadding, + center_y(close_button_->height())}); if (show_link_only) { // Let's hide all the items. for (auto ri = download_views_.rbegin(); ri != download_views_.rend(); ++ri)
diff --git a/chrome/browser/ui/views/frame/browser_window_property_manager_win.cc b/chrome/browser/ui/views/frame/browser_window_property_manager_win.cc index 0fe28521..f6cf228 100644 --- a/chrome/browser/ui/views/frame/browser_window_property_manager_win.cc +++ b/chrome/browser/ui/views/frame/browser_window_property_manager_win.cc
@@ -24,10 +24,10 @@ using extensions::ExtensionRegistry; -BrowserWindowPropertyManager::BrowserWindowPropertyManager(BrowserView* view, - HWND hwnd) - : view_(view), - hwnd_(hwnd) { +BrowserWindowPropertyManager::BrowserWindowPropertyManager( + const BrowserView* view, + HWND hwnd) + : view_(view), hwnd_(hwnd) { // At this point, the HWND is unavailable from BrowserView. DCHECK(hwnd); profile_pref_registrar_.Init(view_->browser()->profile()->GetPrefs()); @@ -45,7 +45,7 @@ } void BrowserWindowPropertyManager::UpdateWindowProperties() { - Browser* browser = view_->browser(); + const Browser* browser = view_->browser(); Profile* profile = browser->profile(); // Set the app user model id for this application to that of the application @@ -56,12 +56,6 @@ base::UTF8ToWide(browser->app_name()), profile->GetPath()) : shell_integration::win::GetChromiumModelIdForProfile( profile->GetPath()); - base::FilePath icon_path; - base::string16 command_line_string; - base::string16 pinned_name; - ProfileManager* profile_manager = g_browser_process->profile_manager(); - ProfileShortcutManager* shortcut_manager = nullptr; - // Apps set their relaunch details based on app's details. if (browser->deprecated_is_app()) { ExtensionRegistry* registry = ExtensionRegistry::Get(profile); @@ -75,17 +69,20 @@ } } + ProfileManager* const profile_manager = g_browser_process->profile_manager(); + ProfileShortcutManager* const shortcut_manager = + profile_manager ? profile_manager->profile_shortcut_manager() : nullptr; // The profile manager may be null in testing. - if (profile_manager) - shortcut_manager = profile_manager->profile_shortcut_manager(); + base::FilePath icon_path; + base::string16 command_line_string; + base::string16 pinned_name; if (!browser->deprecated_is_app() && shortcut_manager && profile->GetPrefs()->HasPrefPath(prefs::kProfileIconVersion)) { - const base::FilePath& profile_path = profile->GetPath(); // Set relaunch details to use profile. base::CommandLine command_line(base::CommandLine::NO_PROGRAM); - shortcut_manager->GetShortcutProperties(profile_path, &command_line, + shortcut_manager->GetShortcutProperties(profile->GetPath(), &command_line, &pinned_name, &icon_path); command_line_string = command_line.GetCommandLineString(); } @@ -96,7 +93,7 @@ // static std::unique_ptr<BrowserWindowPropertyManager> BrowserWindowPropertyManager::CreateBrowserWindowPropertyManager( - BrowserView* view, + const BrowserView* view, HWND hwnd) { std::unique_ptr<BrowserWindowPropertyManager> browser_window_property_manager( new BrowserWindowPropertyManager(view, hwnd));
diff --git a/chrome/browser/ui/views/frame/browser_window_property_manager_win.h b/chrome/browser/ui/views/frame/browser_window_property_manager_win.h index 0f3e189..f66ca16 100644 --- a/chrome/browser/ui/views/frame/browser_window_property_manager_win.h +++ b/chrome/browser/ui/views/frame/browser_window_property_manager_win.h
@@ -12,26 +12,28 @@ class BrowserView; -// This class is resposible for updating the app id and relaunch details of a +// This class is responsible for updating the app id and relaunch details of a // browser frame. class BrowserWindowPropertyManager { public: + BrowserWindowPropertyManager(const BrowserWindowPropertyManager&) = delete; + BrowserWindowPropertyManager& operator=(const BrowserWindowPropertyManager&) = + delete; virtual ~BrowserWindowPropertyManager(); static std::unique_ptr<BrowserWindowPropertyManager> - CreateBrowserWindowPropertyManager(BrowserView* view, HWND hwnd); + CreateBrowserWindowPropertyManager(const BrowserView* view, HWND hwnd); private: - BrowserWindowPropertyManager(BrowserView* view, HWND hwnd); + BrowserWindowPropertyManager(const BrowserView* view, HWND hwnd); void UpdateWindowProperties(); void OnProfileIconVersionChange(); PrefChangeRegistrar profile_pref_registrar_; - BrowserView* view_; + const BrowserView* view_; const HWND hwnd_; - DISALLOW_COPY_AND_ASSIGN(BrowserWindowPropertyManager); }; #endif // CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_WINDOW_PROPERTY_MANAGER_WIN_H_
diff --git a/chrome/browser/ui/views/hats/hats_browsertest.cc b/chrome/browser/ui/views/hats/hats_browsertest.cc index 76c7ce6..a52e6b3 100644 --- a/chrome/browser/ui/views/hats/hats_browsertest.cc +++ b/chrome/browser/ui/views/hats/hats_browsertest.cc
@@ -190,6 +190,7 @@ MOCK_METHOD0(ShowWidget, void()); MOCK_METHOD0(CloseWidget, void()); + MOCK_METHOD1(UpdateWidgetSize, void(gfx::Size)); }; typedef InProcessBrowserTest HatsNextWebDialogBrowserTest; @@ -290,3 +291,36 @@ GURL("http://foo.com"), browser()->tab_strip_model()->GetActiveWebContents()->GetVisibleURL()); } + +IN_PROC_BROWSER_TEST_F(HatsNextWebDialogBrowserTest, DialogResize) { + ASSERT_TRUE(embedded_test_server()->Start()); + + auto* dialog = new MockHatsNextWebDialog( + browser(), "resize_for_testing", + embedded_test_server()->GetURL("/hats/hats_next_mock.html"), + base::TimeDelta::FromSeconds(100)); + + // Check that the dialog attempts to resize with the sizes defined in + // hats_next_mock.html. + base::RunLoop run_loop; + EXPECT_CALL(*dialog, UpdateWidgetSize(gfx::Size(123, 456))) + .WillOnce(testing::Invoke([&run_loop] { run_loop.Quit(); })); + run_loop.Run(); +} + +IN_PROC_BROWSER_TEST_F(HatsNextWebDialogBrowserTest, InvalidSize) { + ASSERT_TRUE(embedded_test_server()->Start()); + + // Check that providing a size which is too large results in the dialog being + // closed. + auto* dialog = new MockHatsNextWebDialog( + browser(), "invalid_size_for_testing", + embedded_test_server()->GetURL("/hats/hats_next_mock.html"), + base::TimeDelta::FromSeconds(100)); + + base::RunLoop run_loop; + EXPECT_CALL(*dialog, CloseWidget).WillOnce([&run_loop]() { + run_loop.Quit(); + }); + run_loop.Run(); +}
diff --git a/chrome/browser/ui/views/hats/hats_next_web_dialog.cc b/chrome/browser/ui/views/hats/hats_next_web_dialog.cc index d937fa3..a2fb7775 100644 --- a/chrome/browser/ui/views/hats/hats_next_web_dialog.cc +++ b/chrome/browser/ui/views/hats/hats_next_web_dialog.cc
@@ -31,7 +31,8 @@ class HatsNextWebDialog::WebContentsDelegate : public content::WebContentsDelegate { public: - explicit WebContentsDelegate(Browser* browser) : browser_(browser) {} + explicit WebContentsDelegate(Browser* browser, HatsNextWebDialog* dialog) + : browser_(browser), dialog_(dialog) {} bool IsWebContentsCreationOverridden( content::SiteInstance* source_site_instance, @@ -61,8 +62,23 @@ return nullptr; } + void SetContentsBounds(content::WebContents* source, + const gfx::Rect& bounds) override { + // Check that the provided bounds do not exceed the dummy window size + // provided to the HaTS library by the wrapper website. These are defined + // in the website source at google3/chrome/hats/website/www/index.html. + if (bounds.width() > 800 || bounds.height() > 600) { + LOG(ERROR) << "Desired dimensions provided by contents exceed maximum" + << "allowable."; + dialog_->CloseWidget(); + return; + } + dialog_->UpdateWidgetSize(bounds.size()); + } + private: Browser* browser_; + HatsNextWebDialog* dialog_; }; // A thin wrapper that forwards the reference part of the URL associated with @@ -147,11 +163,7 @@ } gfx::Size HatsNextWebDialog::CalculatePreferredSize() const { - // Default width/height of the dialog in screen size, these values are derived - // from the size of the HaTS HTML component displayed by this dialog. - constexpr int kDefaultHatsDialogWidth = 363; - constexpr int kDefaultHatsDialogHeight = 440; - return gfx::Size(kDefaultHatsDialogWidth, kDefaultHatsDialogHeight); + return size_; } void HatsNextWebDialog::OnProfileWillBeDestroyed(Profile* profile) { @@ -183,12 +195,14 @@ web_view_ = AddChildView(std::make_unique<views::WebDialogView>( otr_profile_, this, std::make_unique<ChromeWebContentsHandler>(), /* use_dialog_frame */ true)); + set_margins(gfx::Insets()); widget_ = views::BubbleDialogDelegateView::CreateBubble(this); web_contents_observer_ = std::make_unique<WebContentsObserver>(web_view_->web_contents(), this); - web_contents_delegate_ = std::make_unique<WebContentsDelegate>(browser_); + web_contents_delegate_ = + std::make_unique<WebContentsDelegate>(browser_, this); web_view_->web_contents()->SetDelegate(web_contents_delegate_.get()); loading_timer_.Start(FROM_HERE, timeout_, @@ -233,6 +247,11 @@ widget_->Close(); } +void HatsNextWebDialog::UpdateWidgetSize(gfx::Size size) { + size_ = size; + SizeToContents(); +} + bool HatsNextWebDialog::IsWaitingForSurveyForTesting() { return loading_timer_.IsRunning(); }
diff --git a/chrome/browser/ui/views/hats/hats_next_web_dialog.h b/chrome/browser/ui/views/hats/hats_next_web_dialog.h index afd5ea0..66bf1b7 100644 --- a/chrome/browser/ui/views/hats/hats_next_web_dialog.h +++ b/chrome/browser/ui/views/hats/hats_next_web_dialog.h
@@ -85,6 +85,10 @@ // closed. Virtual to allow mocking in tests. virtual void CloseWidget(); + // Updates dialog size, provided via state update by the webpage. Virtual to + // allow mocking in tests. + virtual void UpdateWidgetSize(gfx::Size size); + // Returns whether the dialog is still waiting for the survey to load. bool IsWaitingForSurveyForTesting(); @@ -100,6 +104,11 @@ // The HaTS Next survey trigger ID that is provided to the HaTS webpage. const std::string& trigger_id_; + // The size of the dialog. Desired dimensions are provided by the site loaded + // in the web contents. Initialised to arbitrary non-zero value as creation + // of 0 sized windows is disallowed on OSX. + gfx::Size size_ = gfx::Size(10, 10); + views::WebDialogView* web_view_ = nullptr; views::Widget* widget_ = nullptr;
diff --git a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc index 2517492a..9ad892d6 100644 --- a/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc +++ b/chrome/browser/ui/views/payments/payment_handler_web_flow_view_controller.cc
@@ -304,9 +304,11 @@ void PaymentHandlerWebFlowViewController::VisibleSecurityStateChanged( content::WebContents* source) { DCHECK_EQ(source, web_contents()); - UpdateHeaderView(); - if (!SslValidityChecker::IsValidPageInPaymentHandlerWindow(source)) + if (!SslValidityChecker::IsValidPageInPaymentHandlerWindow(source)) { AbortPayment(); + } else { + UpdateHeaderView(); + } } void PaymentHandlerWebFlowViewController::DidStartNavigation(
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 883377f..55d2d809 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -665,6 +665,10 @@ tabstrip_->OnGroupCreated(change.group); break; } + case TabGroupChange::kEditorOpened: { + tabstrip_->OnGroupEditorOpened(change.group); + break; + } case TabGroupChange::kContentsChanged: { tabstrip_->OnGroupContentsChanged(change.group); break;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 025b8e5..5d381d12 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1384,8 +1384,10 @@ auto group_view = std::make_unique<TabGroupViews>(this, group); layout_helper_->InsertGroupHeader(group, group_view->header()); group_views_[group] = std::move(group_view); +} - // The context menu relys on a Browser object which is not provided in +void TabStrip::OnGroupEditorOpened(const tab_groups::TabGroupId& group) { + // The context menu relies on a Browser object which is not provided in // TabStripTest. if (this->controller()->GetBrowser()) { group_views_[group]->header()->ShowContextMenuForViewImpl(
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 66202aa..83c438c 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -174,6 +174,10 @@ // Creates the views associated with a newly-created tab group. void OnGroupCreated(const tab_groups::TabGroupId& group); + // Opens the editor bubble for the tab |group| as a result of an explicit user + // action to create the |group|. + void OnGroupEditorOpened(const tab_groups::TabGroupId& group); + // Updates the group's contents and metadata when its tab membership changes. // This should be called when a tab is added to or removed from a group. void OnGroupContentsChanged(const tab_groups::TabGroupId& group);
diff --git a/chrome/browser/ui/webui/signin/profile_picker_handler.cc b/chrome/browser/ui/webui/signin/profile_picker_handler.cc index 2554cfc9..71750b6 100644 --- a/chrome/browser/ui/webui/signin/profile_picker_handler.cc +++ b/chrome/browser/ui/webui/signin/profile_picker_handler.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/profiles/profiles_state.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/profile_picker.h" +#include "chrome/browser/ui/webui/profile_helper.h" #include "chrome/common/pref_names.h" #include "chrome/common/search/generated_colors_info.h" #include "ui/base/l10n/l10n_util.h" @@ -59,6 +60,10 @@ &ProfilePickerHandler::HandleGetNewProfileSuggestedThemeInfo, base::Unretained(this))); web_ui()->RegisterMessageCallback( + "removeProfile", + base::BindRepeating(&ProfilePickerHandler::HandleRemoveProfile, + base::Unretained(this))); + web_ui()->RegisterMessageCallback( "getProfileStatistics", base::BindRepeating(&ProfilePickerHandler::HandleGetProfileStatistics, base::Unretained(this))); @@ -156,6 +161,20 @@ ResolveJavascriptCallback(callback_id, std::move(dict)); } +void ProfilePickerHandler::HandleRemoveProfile(const base::ListValue* args) { + CHECK_EQ(1U, args->GetSize()); + const base::Value& profile_path_value = args->GetList()[0]; + base::Optional<base::FilePath> profile_path = + util::ValueToFilePath(profile_path_value); + + if (!profile_path) { + NOTREACHED(); + return; + } + webui::DeleteProfileAtPath(*profile_path, + ProfileMetrics::DELETE_PROFILE_USER_MANAGER); +} + void ProfilePickerHandler::HandleGetProfileStatistics( const base::ListValue* args) { AllowJavascript(); @@ -259,7 +278,8 @@ void ProfilePickerHandler::OnProfileWasRemoved( const base::FilePath& profile_path, const base::string16& profile_name) { - PushProfilesList(); + DCHECK(IsJavascriptAllowed()); + FireWebUIListener("profile-removed", util::FilePathToValue(profile_path)); } void ProfilePickerHandler::OnProfileAvatarChanged(
diff --git a/chrome/browser/ui/webui/signin/profile_picker_handler.h b/chrome/browser/ui/webui/signin/profile_picker_handler.h index aa8ff0f..d85d7f5 100644 --- a/chrome/browser/ui/webui/signin/profile_picker_handler.h +++ b/chrome/browser/ui/webui/signin/profile_picker_handler.h
@@ -30,6 +30,7 @@ void HandleLaunchGuestProfile(const base::ListValue* args); void HandleAskOnStartupChanged(const base::ListValue* args); void HandleGetNewProfileSuggestedThemeInfo(const base::ListValue* args); + void HandleRemoveProfile(const base::ListValue* args); void HandleGetProfileStatistics(const base::ListValue* args); void HandleLoadSignInProfileCreationFlow(const base::ListValue* args);
diff --git a/chrome/browser/ui/webui/signin/profile_picker_ui.cc b/chrome/browser/ui/webui/signin/profile_picker_ui.cc index 260e254..936ea7e 100644 --- a/chrome/browser/ui/webui/signin/profile_picker_ui.cc +++ b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
@@ -3,9 +3,11 @@ // found in the LICENSE file. #include "chrome/browser/ui/webui/signin/profile_picker_ui.h" +#include "base/feature_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/webui/signin/profile_picker_handler.h" #include "chrome/browser/ui/webui/webui_util.h" #include "chrome/common/pref_names.h" @@ -15,6 +17,7 @@ #include "chrome/grit/profile_picker_resources.h" #include "chrome/grit/profile_picker_resources_map.h" #include "components/prefs/pref_service.h" +#include "components/strings/grit/components_strings.h" #include "content/public/browser/web_ui_data_source.h" #include "ui/base/webui/web_ui_util.h" @@ -27,7 +30,7 @@ {"addSpaceButton", IDS_PROFILE_PICKER_ADD_SPACE_BUTTON}, {"askOnStartupCheckboxText", IDS_PROFILE_PICKER_ASK_ON_STARTUP}, {"browseAsGuestButton", IDS_PROFILE_PICKER_BROWSE_AS_GUEST_BUTTON}, - {"backButtonLabel", IDS_PROFILE_PICKER_BACK_BUTTON_LABEL}, + {"menu", IDS_MENU}, {"profileMenuName", IDS_PROFILE_PICKER_PROFILE_MENU_BUTTON_NAME}, {"profileMenuRemoveText", IDS_PROFILE_PICKER_PROFILE_MENU_REMOVE_TEXT}, {"removeWarningLocalProfile", @@ -40,6 +43,7 @@ {"removeWarningAutofill", IDS_PROFILE_PICKER_REMOVE_WARNING_AUTOFILL}, {"removeWarningCalculating", IDS_PROFILE_PICKER_REMOVE_WARNING_CALCULATING}, + {"backButtonLabel", IDS_PROFILE_PICKER_BACK_BUTTON_LABEL}, {"profileTypeChoiceTitle", IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_TITLE}, {"profileTypeChoiceSubtitle", @@ -53,6 +57,9 @@ html_source->AddBoolean("askOnStartup", g_browser_process->local_state()->GetBoolean( prefs::kBrowserShowProfilePickerOnStartup)); + html_source->AddBoolean( + "signInProfileCreationFlow", + base::FeatureList::IsEnabled(features::kSignInProfileCreationFlow)); } } // namespace
diff --git a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc index b716195..54a540a 100644 --- a/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc +++ b/chrome/browser/ui/webui/tab_strip/tab_strip_ui_handler.cc
@@ -181,6 +181,7 @@ void TabStripUIHandler::OnTabGroupChanged(const TabGroupChange& change) { switch (change.type) { case TabGroupChange::kCreated: + case TabGroupChange::kEditorOpened: case TabGroupChange::kContentsChanged: { // TabGroupChange::kCreated events are unnecessary as the front-end will // assume a group was created if there is a tab-group-state-changed event
diff --git a/chrome/browser/web_applications/components/BUILD.gn b/chrome/browser/web_applications/components/BUILD.gn index 2202106a..5bec0ee1 100644 --- a/chrome/browser/web_applications/components/BUILD.gn +++ b/chrome/browser/web_applications/components/BUILD.gn
@@ -163,6 +163,7 @@ "web_app_icon_generator_unittest.cc", "web_app_install_utils_unittest.cc", "web_app_shortcut_unittest.cc", + "web_app_url_loader_unittest.cc", "web_app_utils_unittest.cc", ]
diff --git a/chrome/browser/web_applications/components/web_app_url_loader_unittest.cc b/chrome/browser/web_applications/components/web_app_url_loader_unittest.cc new file mode 100644 index 0000000..2958066 --- /dev/null +++ b/chrome/browser/web_applications/components/web_app_url_loader_unittest.cc
@@ -0,0 +1,153 @@ +// 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/web_applications/components/web_app_url_loader.h" + +#include <memory> + +#include "base/memory/ptr_util.h" +#include "base/test/bind_test_util.h" +#include "chrome/browser/web_applications/test/web_app_test.h" +#include "content/public/common/url_constants.h" +#include "content/public/test/web_contents_tester.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace web_app { + +class WebAppUrlLoaderTest : public WebAppTest { + public: + void SetUp() override { + WebAppTest::SetUp(); + loader_ = std::make_unique<WebAppUrlLoader>(); + } + + void TearDown() override { + loader_.reset(); + WebAppTest::TearDown(); + } + + content::WebContentsTester& web_contents_tester() { + // RenderViewHostTestHarness always contains TestWebContents. See comments + // in web_contents_tester.h. + content::WebContentsTester* web_contents_tester = + content::WebContentsTester::For(web_contents()); + DCHECK(web_contents_tester); + return *web_contents_tester; + } + + WebAppUrlLoader& loader() { + DCHECK(loader_); + return *loader_; + } + + WebAppUrlLoader::Result LoadUrl(const GURL& desired, const GURL& actual) { + WebAppUrlLoader::Result result; + + base::RunLoop run_loop; + loader().LoadUrl(desired, web_contents(), + WebAppUrlLoader::UrlComparison::kExact, + base::BindLambdaForTesting([&](WebAppUrlLoader::Result r) { + result = r; + run_loop.Quit(); + })); + web_contents_tester().TestDidFinishLoad(actual); + run_loop.Run(); + + return result; + } + + private: + std::unique_ptr<WebAppUrlLoader> loader_; +}; + +TEST_F(WebAppUrlLoaderTest, Url1Redirected_ThenUrl2Loaded) { + const GURL url1{"https://example.com"}; + const GURL url2{"https://example.org"}; + + EXPECT_EQ(WebAppUrlLoader::Result::kRedirectedUrlLoaded, + LoadUrl(/*desired=*/url1, /*actual=*/url2)); + + EXPECT_EQ(WebAppUrlLoader::Result::kUrlLoaded, + LoadUrl(/*desired=*/url2, /*actual=*/url2)); +} + +TEST_F(WebAppUrlLoaderTest, Url1DidFailLoad_ThenUrl2Loaded) { + const GURL url1{"https://example.com"}; + const GURL url2{"https://example.org"}; + + base::RunLoop run_loop; + loader().LoadUrl( + url1, web_contents(), WebAppUrlLoader::UrlComparison::kExact, + base::BindLambdaForTesting([&](WebAppUrlLoader::Result result) { + EXPECT_EQ(WebAppUrlLoader::Result::kFailedUnknownReason, result); + run_loop.Quit(); + })); + web_contents_tester().TestDidFailLoadWithError(url1, /*error_code=*/1); + run_loop.Run(); + + EXPECT_EQ(WebAppUrlLoader::Result::kUrlLoaded, + LoadUrl(/*desired=*/url2, /*actual=*/url2)); +} + +TEST_F(WebAppUrlLoaderTest, PrepareForLoad_ExcessiveDidFinishLoad) { + const GURL url1{"https://example.com"}; + const GURL url2{"https://example.org"}; + + // Expect successful navigation to url1. + EXPECT_EQ(WebAppUrlLoader::Result::kUrlLoaded, + LoadUrl(/*desired=*/url1, /*actual=*/url1)); + + // Simulate an excessive DidFinishLoad for url1 caused by active javascript + // while in PrepareForLoad state. PrepareForLoad() acts as a barrier here: + // it's flushing all url1-related noisy events so url2 loading will start + // clean later. + { + base::RunLoop run_loop; + loader().PrepareForLoad( + web_contents(), + base::BindLambdaForTesting([&](WebAppUrlLoader::Result result) { + EXPECT_EQ(WebAppUrlLoader::Result::kUrlLoaded, result); + run_loop.Quit(); + })); + web_contents_tester().TestDidFinishLoad(url1); + web_contents_tester().TestDidFinishLoad(GURL{url::kAboutBlankURL}); + run_loop.Run(); + } + + // Expect successful navigation to url2. + EXPECT_EQ(WebAppUrlLoader::Result::kUrlLoaded, + LoadUrl(/*desired=*/url2, /*actual=*/url2)); +} + +TEST_F(WebAppUrlLoaderTest, PrepareForLoad_ExcessiveDidFailLoad) { + const GURL url1{"https://example.com"}; + const GURL url2{"https://example.org"}; + + // Expect successful navigation to url1. + EXPECT_EQ(WebAppUrlLoader::Result::kUrlLoaded, + LoadUrl(/*desired=*/url1, /*actual=*/url1)); + + // Simulate an excessive DidFailLoad for url1 caused by active javascript + // while in PrepareForLoad state. PrepareForLoad() acts as a barrier here: + // it's flushing all url1-related noisy events so url2 loading will start + // clean later. + { + base::RunLoop run_loop; + loader().PrepareForLoad( + web_contents(), + base::BindLambdaForTesting([&](WebAppUrlLoader::Result result) { + EXPECT_EQ(WebAppUrlLoader::Result::kUrlLoaded, result); + run_loop.Quit(); + })); + web_contents_tester().TestDidFailLoadWithError(url1, /*error_code=*/1); + web_contents_tester().TestDidFinishLoad(GURL{url::kAboutBlankURL}); + run_loop.Run(); + } + + // Expect successful navigation to url2. + EXPECT_EQ(WebAppUrlLoader::Result::kUrlLoaded, + LoadUrl(/*desired=*/url2, /*actual=*/url2)); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/components/web_app_utils_unittest.cc b/chrome/browser/web_applications/components/web_app_utils_unittest.cc index d5c6f33..a5c8e0be 100644 --- a/chrome/browser/web_applications/components/web_app_utils_unittest.cc +++ b/chrome/browser/web_applications/components/web_app_utils_unittest.cc
@@ -23,7 +23,7 @@ namespace web_app { -class WebAppUtilsTest : public WebAppTest {}; +using WebAppUtilsTest = WebAppTest; TEST_F(WebAppUtilsTest, AreWebAppsEnabled) { Profile* regular_profile = profile();
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index 053f638c..1f40fc7 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-master-1597211695-37c2210c4f6de3e68198b41f1297acfc22a0b10f.profdata +chrome-mac-master-1597233486-9b99859a3e8f91576b2a111cc083e1a4b72a89f4.profdata
diff --git a/chrome/services/printing/pdf_thumbnailer.cc b/chrome/services/printing/pdf_thumbnailer.cc index 179ce3e..714ecc8 100644 --- a/chrome/services/printing/pdf_thumbnailer.cc +++ b/chrome/services/printing/pdf_thumbnailer.cc
@@ -17,9 +17,6 @@ namespace { -// The resolution of the bitmap in dots per inch; always 300. -constexpr int kDpi = 300; - // Whether or not to rotate PDF to fit the given size; always no. constexpr bool kAutorotate = false; @@ -66,9 +63,10 @@ } // Convert PDF bytes into a bitmap thumbnail. - if (!chrome_pdf::RenderPDFPageToBitmap(pdf_buffer, 0, result.getPixels(), - width_px, height_px, kDpi, kDpi, - kAutorotate, kUseColor)) { + if (!chrome_pdf::RenderPDFPageToBitmap( + pdf_buffer, 0, result.getPixels(), width_px, height_px, + params->dpi.width(), params->dpi.height(), params->stretch, + params->keep_aspect, kAutorotate, kUseColor)) { DLOG(ERROR) << "Failed to render PDF buffer as bitmap image"; std::move(callback).Run(SkBitmap()); return;
diff --git a/chrome/services/printing/pdf_thumbnailer_unittest.cc b/chrome/services/printing/pdf_thumbnailer_unittest.cc index 445fe00..06e86f7 100644 --- a/chrome/services/printing/pdf_thumbnailer_unittest.cc +++ b/chrome/services/printing/pdf_thumbnailer_unittest.cc
@@ -19,8 +19,12 @@ namespace { -constexpr int kThumbWidth = 96; -constexpr int kThumbHeight = 64; +constexpr int kThumbWidth = 256; +constexpr int kThumbHeight = 192; +constexpr int kHorizontalDpi = 300; +constexpr int kVerticalDpi = 300; +constexpr bool kStretch = true; +constexpr bool kKeepRatio = true; const char kPdfContent[] = R"(%PDF-1.2 9 0 obj @@ -62,7 +66,9 @@ class PdfThumbnailerTest : public testing::Test { public: void SetUp() override { - params_ = mojom::ThumbParams::New(gfx::Size(kThumbWidth, kThumbHeight)); + params_ = mojom::ThumbParams::New(gfx::Size(kThumbWidth, kThumbHeight), + gfx::Size(kHorizontalDpi, kVerticalDpi), + kStretch, kKeepRatio); } // Copies bytes from |bitmap| into |bitmap_|. This method is here due @@ -104,6 +110,25 @@ EXPECT_EQ(kThumbHeight, bitmap_.height()); } +// A low DPI, non-stretched thumbnail. +TEST_F(PdfThumbnailerTest, CreateLowResUnstretchedPdfThumbnail) { + base::RunLoop run_loop; + auto pdf_region = CreatePdfRegion(kPdfContent); + + auto params = mojom::ThumbParams::New(gfx::Size(kThumbWidth, kThumbHeight), + gfx::Size(15, 15), false, kKeepRatio); + thumbnailer_.GetThumbnail( + std::move(params), std::move(pdf_region), + base::BindOnce(&PdfThumbnailerTest::StoreResult, + weak_factory_.GetWeakPtr(), run_loop.QuitClosure())); + run_loop.Run(); + EXPECT_FALSE(bitmap_.isNull()); + // The bitmap size is still the requested size, even though the thumbnail + // itself does not fill the entire bitmap. + EXPECT_EQ(kThumbWidth, bitmap_.width()); + EXPECT_EQ(kThumbHeight, bitmap_.height()); +} + // An invalid PDF should cause failure (null bitmap returned). TEST_F(PdfThumbnailerTest, CreatePdfThumbnailFailure) { base::RunLoop run_loop; @@ -122,7 +147,9 @@ base::RunLoop run_loop; auto pdf_region = CreatePdfRegion(kPdfContent); - auto params = mojom::ThumbParams::New(gfx::Size(0, 0)); + auto params = mojom::ThumbParams::New(gfx::Size(0, 0), + gfx::Size(kHorizontalDpi, kVerticalDpi), + kStretch, kKeepRatio); thumbnailer_.GetThumbnail( std::move(params), std::move(pdf_region), base::BindOnce(&PdfThumbnailerTest::StoreResult, @@ -138,7 +165,8 @@ auto pdf_region = CreatePdfRegion(kPdfContent); auto params = mojom::ThumbParams::New( - gfx::Size(PdfThumbnailer::kMaxWidth + 1, PdfThumbnailer::kMaxHeight + 1)); + gfx::Size(PdfThumbnailer::kMaxWidth + 1, PdfThumbnailer::kMaxHeight + 1), + gfx::Size(kHorizontalDpi, kVerticalDpi), kStretch, kKeepRatio); thumbnailer_.GetThumbnail( std::move(params), std::move(pdf_region), base::BindOnce(&PdfThumbnailerTest::StoreResult,
diff --git a/chrome/services/printing/pdf_to_pwg_raster_converter.cc b/chrome/services/printing/pdf_to_pwg_raster_converter.cc index 0387efb..b6f1ac38 100644 --- a/chrome/services/printing/pdf_to_pwg_raster_converter.cc +++ b/chrome/services/printing/pdf_to_pwg_raster_converter.cc
@@ -57,7 +57,7 @@ if (!chrome_pdf::RenderPDFPageToBitmap( pdf_data, page_number, image.pixel_data(), image.size().width(), image.size().height(), settings.dpi.width(), settings.dpi.height(), - settings.autorotate, settings.use_color)) { + false, true, settings.autorotate, settings.use_color)) { return invalid_pwg_region; }
diff --git a/chrome/services/printing/public/mojom/pdf_thumbnailer.mojom b/chrome/services/printing/public/mojom/pdf_thumbnailer.mojom index 5418192..62c3fdb 100644 --- a/chrome/services/printing/public/mojom/pdf_thumbnailer.mojom +++ b/chrome/services/printing/public/mojom/pdf_thumbnailer.mojom
@@ -12,6 +12,15 @@ struct ThumbParams { // The dimensions of the thumbnail. gfx.mojom.Size size_px; + + // The resolution, in dots per inch, of the thumbnail. + gfx.mojom.Size dpi; + + // Whether or not to stretch the thumbnail to fill the supplied size. + bool stretch; + + // Whether or not to preserve the aspect ratio. + bool keep_aspect; }; // Interface used to generate a thumbnail for a PDF contents given as a set of
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index aa329b3..e581ac6e8 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -4046,6 +4046,7 @@ "//chrome/android/features/media_router:java", "//chrome/browser/optimization_guide/android:native_j_unittests_jni_headers", "//chrome/browser/optimization_guide/android:native_java_unittests", + "//chrome/browser/password_check/android:unit_tests", "//chrome/browser/thumbnail:unit_tests", "//chrome/browser/updates:unit_tests", "//chrome/services/media_gallery_util:unit_tests",
diff --git a/chrome/test/data/hats/hats_next_mock.html b/chrome/test/data/hats/hats_next_mock.html index 0883c853..bee761d 100644 --- a/chrome/test/data/hats/hats_next_mock.html +++ b/chrome/test/data/hats/hats_next_mock.html
@@ -20,6 +20,14 @@ window.open('http://foo.com', '_blank'); history.pushState('', '', '#loaded'); } + + if (params.get('trigger_id') == "resize_for_testing") { + window.resizeTo(123, 456); + } + + if (params.get('trigger_id') == "invalid_size_for_testing") { + window.resizeTo(1000, 1000); + } </script> </head> <body>
diff --git a/chrome/test/data/webui/media/media_feeds_webui_browsertest.js b/chrome/test/data/webui/media/media_feeds_webui_browsertest.js index c7c7c01..804a232 100644 --- a/chrome/test/data/webui/media/media_feeds_webui_browsertest.js +++ b/chrome/test/data/webui/media/media_feeds_webui_browsertest.js
@@ -343,7 +343,7 @@ assertDeepEquals( [ 'Background Fetching Enabled (value)', - 'Disabled', + 'Enabled', 'Background Fetching Enabled (pref)', 'Disabled (Toggle)', ], @@ -361,7 +361,7 @@ assertDeepEquals( [ 'Background Fetching Enabled (value)', - 'Disabled', + 'Enabled', 'Background Fetching Enabled (pref)', 'Enabled (Toggle)', ],
diff --git a/chrome/test/data/webui/media/media_history_webui_browsertest.js b/chrome/test/data/webui/media/media_history_webui_browsertest.js index c6e26056..91acae1 100644 --- a/chrome/test/data/webui/media/media_history_webui_browsertest.js +++ b/chrome/test/data/webui/media/media_history_webui_browsertest.js
@@ -57,6 +57,8 @@ assertDeepEquals( [ + ['mediaFeed', '0'], + ['mediaFeedItem', '0'], ['mediaImage', '0'], ['meta', '3'], ['origin', '0'],
diff --git a/chromeos/BUILD.gn b/chromeos/BUILD.gn index 2eaea00..dab95391 100644 --- a/chromeos/BUILD.gn +++ b/chromeos/BUILD.gn
@@ -349,16 +349,6 @@ deps = [ ":chromeos" ] } -# Commented out due to crbug.com/1106355 -# fuzzer_test("printer_configuration_fuzzer") { -# sources = [ "printing/printer_configuration_fuzzer.cc" ] -# seed_corpus = "printing/uri_fuzzer_seed_corpus" -# deps = [ -# ":chromeos", -# "//base", -# ] -# } - fuzzer_test("uri_fuzzer") { sources = [ "printing/uri_fuzzer.cc" ] seed_corpus = "printing/uri_fuzzer_seed_corpus"
diff --git a/chromeos/printing/printer_configuration_fuzzer.cc b/chromeos/printing/printer_configuration_fuzzer.cc deleted file mode 100644 index 58216c2e..0000000 --- a/chromeos/printing/printer_configuration_fuzzer.cc +++ /dev/null
@@ -1,34 +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 <stddef.h> -#include <stdint.h> - -#include <string> - -#include "base/optional.h" -#include "base/strings/strcat.h" -#include "base/strings/string_number_conversions.h" -#include "chromeos/printing/printer_configuration.h" -#include "chromeos/printing/uri_components.h" - -extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - chromeos::Printer printer("fuzz"); - printer.set_uri(std::string(reinterpret_cast<const char*>(data), size)); - printer.GetHostAndPort(); - printer.GetProtocol(); - base::Optional<chromeos::UriComponents> components = - printer.GetUriComponents(); - if (components) { - bool encrypted = components->encrypted(); - std::string scheme = components->scheme(); - std::string host = components->host(); - int port = components->port(); - std::string path = components->path(); - std::string reconstructed = - base::StrCat({encrypted ? "True" : "False", scheme, host, - base::NumberToString(port), path}); - } - return 0; -}
diff --git a/chromeos/services/network_health/public/mojom/network_diagnostics.mojom b/chromeos/services/network_health/public/mojom/network_diagnostics.mojom index e766fd2a9..59f8845 100644 --- a/chromeos/services/network_health/public/mojom/network_diagnostics.mojom +++ b/chromeos/services/network_health/public/mojom/network_diagnostics.mojom
@@ -76,6 +76,18 @@ kFailedToResolveHost, }; +// Problems related to the CaptivePortal routine. +[Extensible] +enum CaptivePortalProblem { + // No active networks found. + kNoActiveNetworks, + // The active network is detected to be behind a captive portal and have + // restricted connectivity. + kRestrictedConnectivity, + // The active network is detected to be behind a captive portal. + kCaptivePortalState, +}; + // This interface is to be used by any clients that need to run specific // network-related diagnostics. Expected clients of this interface are // NetworkHealth, cros_healthd, and a connectivity diagnostics Web UI (to name @@ -84,7 +96,7 @@ // Tests whether the device is connected to a LAN. It is possible that the // device may be trapped in a captive portal yet pass this test successfully. // Captive portal checks are done separately and are outside of the scope of - // this routine. + // this routine. See CaptivePortal() below. LanConnectivity() => (RoutineVerdict verdict); // Tests whether there is an acceptable signal strength on wireless networks. @@ -111,4 +123,8 @@ // Tests whether a DNS resolution can be completed successfully. DnsResolution() => (RoutineVerdict verdict, array<DnsResolutionProblem> problems); + + // Tests whether the internet connection is behind a captive portal. + CaptivePortal() => (RoutineVerdict verdict, + array<CaptivePortalProblem> problems); };
diff --git a/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java b/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java index 1ced117..f2a9a57 100644 --- a/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java +++ b/components/browser_ui/android/bottomsheet/internal/java/src/org/chromium/components/browser_ui/bottomsheet/BottomSheet.java
@@ -494,6 +494,16 @@ mSheetContent.getContentView().removeOnLayoutChangeListener(this); } + if (content != null && getParent() == null) { + mSheetContainer.addView(this); + } else if (content == null) { + if (mSheetContainer.getParent() == null) { + throw new RuntimeException( + "Attempting to detach sheet that was not in the hierarchy!"); + } + mSheetContainer.removeView(this); + } + swapViews(content != null ? content.getContentView() : null, mSheetContent != null ? mSheetContent.getContentView() : null, mBottomSheetContentContainer); @@ -625,13 +635,6 @@ setTranslationY(translationY); - float hiddenHeight = getHiddenRatio() * mContainerHeight; - if (mCurrentOffsetPx <= hiddenHeight && this.getParent() != null) { - mSheetContainer.removeView(this); - } else if (mCurrentOffsetPx > hiddenHeight && this.getParent() == null) { - mSheetContainer.addView(this); - } - // Do open/close computation based on the minimum allowed state by the sheet's content. // Note that when transitioning from hidden to peek, even dismissable sheets may want // to have a peek state.
diff --git a/components/enterprise/browser/reporting/policy_info.cc b/components/enterprise/browser/reporting/policy_info.cc index dd690664510..86bc07a 100644 --- a/components/enterprise/browser/reporting/policy_info.cc +++ b/components/enterprise/browser/reporting/policy_info.cc
@@ -111,6 +111,11 @@ void AppendExtensionPolicyInfoIntoProfileReport( const base::Value& policies, em::ChromeUserProfileInfo* profile_info) { + if (!policies.FindKey("extensionPolicies")) { + // Android and iOS don't support extensions and their policies. + return; + } + for (const auto& extension_iter : policies.FindKey("extensionPolicies")->DictItems()) { const base::Value& policies = extension_iter.second;
diff --git a/components/feed/core/v2/feed_stream.cc b/components/feed/core/v2/feed_stream.cc index 7aa40bc..9b3a6b9 100644 --- a/components/feed/core/v2/feed_stream.cc +++ b/components/feed/core/v2/feed_stream.cc
@@ -279,7 +279,6 @@ void FeedStream::LoadMore(SurfaceId surface_id, base::OnceCallback<void(bool)> callback) { - metrics_reporter_->OnLoadMoreBegin(surface_id); if (!model_) { DLOG(ERROR) << "Ignoring LoadMore() before the model is loaded"; return std::move(callback).Run(false); @@ -292,6 +291,7 @@ return std::move(callback).Run(false); } + metrics_reporter_->OnLoadMoreBegin(surface_id); surface_updater_->SetLoadingMore(true); // Have at most one in-flight LoadMore() request. Send the result to all @@ -411,6 +411,16 @@ if (model_) { ss << "model loaded, " << model_->GetContentList().size() << " contents\n"; } + RequestSchedule schedule = prefs::GetRequestSchedule(*profile_prefs_); + if (schedule.refresh_offsets.empty()) { + ss << "No request schedule\n"; + } else { + ss << "Request schedule reference " << schedule.anchor_time << '\n'; + for (base::TimeDelta entry : schedule.refresh_offsets) { + ss << " fetch at " << entry << '\n'; + } + } + return ss.str(); }
diff --git a/components/feed/core/v2/feed_stream_unittest.cc b/components/feed/core/v2/feed_stream_unittest.cc index 9cd5801..80bfd41 100644 --- a/components/feed/core/v2/feed_stream_unittest.cc +++ b/components/feed/core/v2/feed_stream_unittest.cc
@@ -408,6 +408,10 @@ MetricsReporter::OnLoadStream(load_from_store_status, final_status, std::move(latencies)); } + void OnLoadMoreBegin(SurfaceId surface_id) override { + load_more_surface_id = surface_id; + MetricsReporter::OnLoadMoreBegin(surface_id); + } void OnLoadMore(LoadStreamStatus final_status) override { load_more_status = final_status; MetricsReporter::OnLoadMore(final_status); @@ -425,6 +429,7 @@ base::Optional<int> slice_viewed_index; base::Optional<LoadStreamStatus> load_stream_status; + base::Optional<SurfaceId> load_more_surface_id; base::Optional<LoadStreamStatus> load_more_status; base::Optional<LoadStreamStatus> background_refresh_status; base::Optional<base::TimeDelta> time_since_last_clear; @@ -1168,6 +1173,8 @@ response_translator_.InjectResponse(MakeTypicalNextPageState(2)); CallbackReceiver<bool> callback; stream_->LoadMore(surface.GetSurfaceId(), callback.Bind()); + // Ensure metrics reporter was informed at the start of the operation. + EXPECT_EQ(surface.GetSurfaceId(), metrics_reporter_->load_more_surface_id); WaitForIdleTaskQueue(); ASSERT_EQ(base::Optional<bool>(true), callback.GetResult()); EXPECT_EQ("2 slices +spinner -> 4 slices", surface.DescribeUpdates()); @@ -1294,6 +1301,9 @@ EXPECT_EQ(base::Optional<bool>(false), callback.GetResult()); ASSERT_EQ(1, network_.send_query_call_count); EXPECT_EQ("loading -> 2 slices", surface.DescribeUpdates()); + EXPECT_EQ(base::nullopt, metrics_reporter_->load_more_surface_id) + << "metrics reporter was informed about a load more operation which " + "didn't begin"; } TEST_F(FeedStreamTest, LoadMoreFail) {
diff --git a/components/feed/core/v2/metrics_reporter.h b/components/feed/core/v2/metrics_reporter.h index 23f77c7b..95e80f7a 100644 --- a/components/feed/core/v2/metrics_reporter.h +++ b/components/feed/core/v2/metrics_reporter.h
@@ -104,7 +104,7 @@ LoadStreamStatus final_status, std::unique_ptr<LoadLatencyTimes> load_latencies); virtual void OnBackgroundRefresh(LoadStreamStatus final_status); - void OnLoadMoreBegin(SurfaceId surface_id); + virtual void OnLoadMoreBegin(SurfaceId surface_id); virtual void OnLoadMore(LoadStreamStatus final_status); virtual void OnClearAll(base::TimeDelta time_since_last_clear); // Called each time the surface receives new content.
diff --git a/components/omnibox/OWNERS b/components/omnibox/OWNERS index e5b4261..5965878 100644 --- a/components/omnibox/OWNERS +++ b/components/omnibox/OWNERS
@@ -3,5 +3,6 @@ mpearson@chromium.org orinj@chromium.org tommycli@chromium.org +yoangela@chromium.org # COMPONENT: UI>Browser>Omnibox
diff --git a/components/password_manager/core/browser/android_affiliation/affiliation_api.proto b/components/password_manager/core/browser/android_affiliation/affiliation_api.proto index 9f563a6..170e26a 100644 --- a/components/password_manager/core/browser/android_affiliation/affiliation_api.proto +++ b/components/password_manager/core/browser/android_affiliation/affiliation_api.proto
@@ -8,6 +8,10 @@ option optimize_for = LITE_RUNTIME; +// The messages below mirror the corresponding messages on the server side. +// These should be updated once the server side changes. +// Synced version: http://shortn/_g0W3toNGei + // Contains a list of affiliated facets. // Affiliated facets are allowed to share credentials among each other. message Affiliation { @@ -37,6 +41,11 @@ // http://somethinginvalid$%#^ -> somethinginvalid$%#^ // android://xyz@com.facebook -> field is not populated optional string main_domain = 3; + + // Info about where the user can change a password stored for this Facet. This + // info should be considered valid for any other Facet in the same FacetGroup. + // Only present for Facets in a FacetGroup. + optional ChangePasswordInfo change_password_info = 4; } // Message representing set of facets that should be grouped together in the UI. @@ -93,9 +102,17 @@ optional int32 icon_height = 5; } +// Various methods through which a user can change a password for a single +// facet. +message ChangePasswordInfo { + // A URL to a change password form or flow. + optional string change_password_url = 1; +} + // Request mask for LookupAffiliationRequest. +// Next id: 8 message LookupAffiliationMask { - // If true, branding info for Android apps will be returned. + // If true, branding info for all facets will be returned. optional bool branding_info = 1; // Preferred size of the icon returned in BrandingInfo or @@ -118,6 +135,10 @@ // grouping response. Can be set only if grouping_info and branding_info is // set to true. optional bool group_branding_info = 5; + + // Whether to include change password infos in the response. Can be set only + // if grouping_info is set to true, as this is only populated for FacetGroups. + optional bool change_password_info = 7; } // Request message for AffiliationService.Lookup.
diff --git a/components/password_manager/core/browser/bulk_leak_check_service.cc b/components/password_manager/core/browser/bulk_leak_check_service.cc index c731574..68157c2 100644 --- a/components/password_manager/core/browser/bulk_leak_check_service.cc +++ b/components/password_manager/core/browser/bulk_leak_check_service.cc
@@ -85,8 +85,15 @@ void BulkLeakCheckService::CheckUsernamePasswordPairs( std::vector<password_manager::LeakCheckCredential> credentials) { DVLOG(0) << "Bulk password check, start " << credentials.size(); - if (credentials.empty()) + if (credentials.empty()) { + // Nothing to check. Still important to go through the running state, so the + // observers know that the results are available. + state_ = State::kRunning; + NotifyStateChanged(); + state_ = State::kIdle; + NotifyStateChanged(); return; + } if (!metrics_reporter_) metrics_reporter_ = std::make_unique<MetricsReporter>(); metrics_reporter_->OnStartCheck(credentials.size());
diff --git a/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc b/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc index d18bb14..cfa4ee02 100644 --- a/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc +++ b/components/password_manager/core/browser/bulk_leak_check_service_unittest.cc
@@ -140,7 +140,10 @@ StrictMock<MockObserver> observer; service().AddObserver(&observer); + EXPECT_CALL(observer, OnStateChanged(BulkLeakCheckService::State::kRunning)); + EXPECT_CALL(observer, OnStateChanged(BulkLeakCheckService::State::kIdle)); service().CheckUsernamePasswordPairs({}); + EXPECT_EQ(BulkLeakCheckService::State::kIdle, service().GetState()); EXPECT_EQ(0u, service().GetPendingChecksCount()); EXPECT_THAT(
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 6e8a721..9e7e1154 100644 --- a/components/password_manager/core/browser/mock_password_feature_manager.h +++ b/components/password_manager/core/browser/mock_password_feature_manager.h
@@ -32,8 +32,8 @@ MOCK_CONST_METHOD0(ComputePasswordAccountStorageUsageLevel, metrics_util::PasswordAccountStorageUsageLevel()); - MOCK_METHOD0(IncrementMoveToAccountRefusedCount, void()); - MOCK_CONST_METHOD0(GetMoveToAccountRefusedCount, int()); + MOCK_METHOD0(RecordMoveOfferedToNonOptedInUser, void()); + MOCK_CONST_METHOD0(GetMoveOfferedToNonOptedInUserCount, 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 01fdfe1..594266a3 100644 --- a/components/password_manager/core/browser/password_feature_manager.h +++ b/components/password_manager/core/browser/password_feature_manager.h
@@ -71,17 +71,17 @@ 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; + // Increases the count of how many times Chrome automatically offered a user + // not opted-in to the account-scoped passwords storage to move a password to + // their account. Should only be called if the user is signed-in and not + // opted-in. + virtual void RecordMoveOfferedToNonOptedInUser() = 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; + // Gets the count of how many times Chrome automatically offered a user + // not opted-in to the account-scoped passwords storage to move a password to + // their account. Should only be called if the user is signed-in and not + // opted-in. + virtual int GetMoveOfferedToNonOptedInUserCount() 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 5535d354..6458f2bd 100644 --- a/components/password_manager/core/browser/password_feature_manager_impl.cc +++ b/components/password_manager/core/browser/password_feature_manager_impl.cc
@@ -77,14 +77,14 @@ sync_service_); } -void PasswordFeatureManagerImpl::IncrementMoveToAccountRefusedCount() { - features_util::IncrementMoveToAccountRefusedCount(pref_service_, - sync_service_); +void PasswordFeatureManagerImpl::RecordMoveOfferedToNonOptedInUser() { + features_util::RecordMoveOfferedToNonOptedInUser(pref_service_, + sync_service_); } -int PasswordFeatureManagerImpl::GetMoveToAccountRefusedCount() const { - return features_util::GetMoveToAccountRefusedCount(pref_service_, - sync_service_); +int PasswordFeatureManagerImpl::GetMoveOfferedToNonOptedInUserCount() const { + return features_util::GetMoveOfferedToNonOptedInUserCount(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 e7d2801..f7e67dc 100644 --- a/components/password_manager/core/browser/password_feature_manager_impl.h +++ b/components/password_manager/core/browser/password_feature_manager_impl.h
@@ -41,8 +41,8 @@ metrics_util::PasswordAccountStorageUsageLevel ComputePasswordAccountStorageUsageLevel() const override; - void IncrementMoveToAccountRefusedCount() override; - int GetMoveToAccountRefusedCount() const override; + void RecordMoveOfferedToNonOptedInUser() override; + int GetMoveOfferedToNonOptedInUserCount() const override; private: PrefService* const pref_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 2a8bdb9..aa117c15 100644 --- a/components/password_manager/core/browser/password_manager_client_helper.cc +++ b/components/password_manager/core/browser/password_manager_client_helper.cc
@@ -132,7 +132,7 @@ features::kMaxMoveToAccountOffersForNonOptedInUser, features::kMaxMoveToAccountOffersForNonOptedInUserDefaultValue); return feature_manager->IsOptedInForAccountStorage() || - feature_manager->GetMoveToAccountRefusedCount() < + feature_manager->GetMoveOfferedToNonOptedInUserCount() < max_move_to_account_offers_for_non_opted_in_user; }
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 1a7d1ba..4bdd59a 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
@@ -229,7 +229,7 @@ // Simulate that no refusals happened so far. Moving should be offered. EXPECT_CALL(*client()->GetPasswordFeatureManager(), - GetMoveToAccountRefusedCount) + GetMoveOfferedToNonOptedInUserCount) .WillOnce(Return(0)); EXPECT_CALL(*client(), PromptUserToMovePasswordToAccount); const PasswordForm form = @@ -239,7 +239,7 @@ // If the previous move was refused and the max is 1, shouldn't offer anymore. EXPECT_CALL(*client()->GetPasswordFeatureManager(), - GetMoveToAccountRefusedCount) + GetMoveOfferedToNonOptedInUserCount) .WillOnce(Return(1)); EXPECT_CALL(*client(), PromptUserToMovePasswordToAccount).Times(0); helper()->NotifySuccessfulLoginWithExistingPassword(
diff --git a/components/password_manager/core/browser/password_manager_features_util.cc b/components/password_manager/core/browser/password_manager_features_util.cc index bf94da4..4447bbd6 100644 --- a/components/password_manager/core/browser/password_manager_features_util.cc +++ b/components/password_manager/core/browser/password_manager_features_util.cc
@@ -72,7 +72,7 @@ const char kAccountStorageOptedInKey[] = "opted_in"; const char kAccountStorageDefaultStoreKey[] = "default_store"; -const char kMoveToAccountStoreRefusedCountKey[] = +const char kMoveToAccountStoreOfferedCountKey[] = "move_to_account_store_refused_count"; // Returns the total number of accounts for which an opt-in to the account @@ -117,10 +117,10 @@ return PasswordStoreFromInt(*value); } - int GetMoveToAccountRefusedCount() const { + int GetMoveOfferedToNonOptedInUserCount() const { if (!account_settings_) return 0; - return account_settings_->FindIntKey(kMoveToAccountStoreRefusedCountKey) + return account_settings_->FindIntKey(kMoveToAccountStoreOfferedCountKey) .value_or(0); } @@ -152,7 +152,7 @@ void SetOptedIn() { base::Value* account_settings = GetOrCreateAccountSettings(); // The count of refusals is only tracked when the user is not opted-in. - account_settings->RemoveKey(kMoveToAccountStoreRefusedCountKey); + account_settings->RemoveKey(kMoveToAccountStoreOfferedCountKey); account_settings->SetBoolKey(kAccountStorageOptedInKey, true); } @@ -162,11 +162,11 @@ static_cast<int>(default_store)); } - void IncrementMovePasswordToAccountBubble() { + void RecordMoveOfferedToNonOptedInUser() { base::Value* account_settings = GetOrCreateAccountSettings(); - int count = account_settings->FindIntKey(kMoveToAccountStoreRefusedCountKey) + int count = account_settings->FindIntKey(kMoveToAccountStoreOfferedCountKey) .value_or(0); - account_settings->SetIntKey(kMoveToAccountStoreRefusedCountKey, ++count); + account_settings->SetIntKey(kMoveToAccountStoreOfferedCountKey, ++count); } void ClearAllSettings() { update_->RemoveKey(account_hash_); } @@ -450,7 +450,7 @@ } } -void IncrementMoveToAccountRefusedCount( +void RecordMoveOfferedToNonOptedInUser( PrefService* pref_service, const syncer::SyncService* sync_service) { DCHECK(pref_service); @@ -462,11 +462,12 @@ .IsOptedIn()); ScopedAccountStorageSettingsUpdate(pref_service, GaiaIdHash::FromGaiaId(gaia_id)) - .IncrementMovePasswordToAccountBubble(); + .RecordMoveOfferedToNonOptedInUser(); } -int GetMoveToAccountRefusedCount(const PrefService* pref_service, - const syncer::SyncService* sync_service) { +int GetMoveOfferedToNonOptedInUserCount( + const PrefService* pref_service, + const syncer::SyncService* sync_service) { DCHECK(pref_service); DCHECK(sync_service); std::string gaia_id = sync_service->GetAuthenticatedAccountInfo().gaia; @@ -474,7 +475,7 @@ AccountStorageSettingsReader reader(pref_service, GaiaIdHash::FromGaiaId(gaia_id)); DCHECK(!reader.IsOptedIn()); - return reader.GetMoveToAccountRefusedCount(); + return reader.GetMoveOfferedToNonOptedInUserCount(); } } // namespace features_util
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 7b262ae..e99e113c 100644 --- a/components/password_manager/core/browser/password_manager_features_util.h +++ b/components/password_manager/core/browser/password_manager_features_util.h
@@ -128,24 +128,22 @@ const PrefService* pref_service, const syncer::SyncService* sync_service); -// 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. |pref_service| and -// |sync_service| must be non-null. -// See PasswordFeatureManager::IncrementMoveToAccountRefusedCount(). -void IncrementMoveToAccountRefusedCount( - PrefService* pref_service, - const syncer::SyncService* sync_service); +// Increases the count of how many times Chrome automatically offered a user +// not opted-in to the account-scoped passwords storage to move a password to +// their account. Should only be called if the user is signed-in and not +// opted-in. |pref_service| and |sync_service| must be non-null. +// See PasswordFeatureManager::RecordMoveOfferedToNonOptedInUser(). +void RecordMoveOfferedToNonOptedInUser(PrefService* pref_service, + const syncer::SyncService* sync_service); -// 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. |pref_service| and -// |sync_service| must be non-null. -// See PasswordFeatureManager::GetMoveToAccountRefusedCount(). -int GetMoveToAccountRefusedCount(const PrefService* pref_service, - const syncer::SyncService* sync_service); +// Gets the count of how many times Chrome automatically offered a user +// not opted-in to the account-scoped passwords storage to move a password to +// their account. Should only be called if the user is signed-in and not +// opted-in. |pref_service| and |sync_service| must be non-null. +// See PasswordFeatureManager::GetMoveOfferedToNonOptedInUserCount(). +int GetMoveOfferedToNonOptedInUserCount( + const PrefService* pref_service, + const syncer::SyncService* sync_service); } // namespace features_util
diff --git a/components/password_manager/core/browser/password_manager_features_util_unittest.cc b/components/password_manager/core/browser/password_manager_features_util_unittest.cc index 28872eb..9129c59 100644 --- a/components/password_manager/core/browser/password_manager_features_util_unittest.cc +++ b/components/password_manager/core/browser/password_manager_features_util_unittest.cc
@@ -506,7 +506,7 @@ "PasswordManager.AccountStorage.ClearedOptInForAllAccounts", 1, 1); } -TEST(PasswordFeatureManagerUtil, MovePasswordToAccountStoreRefusedCount) { +TEST(PasswordFeatureManagerUtil, MovePasswordToAccountStoreOfferedCount) { // Set up a user signed-in, not syncing and not opted-in. base::test::ScopedFeatureList features; features.InitAndEnableFeature(features::kEnablePasswordsAccountStorage); @@ -522,11 +522,14 @@ sync_service.SetIsAuthenticatedAccountPrimary(false); ASSERT_FALSE(IsOptedInForAccountStorage(&pref_service, &sync_service)); - EXPECT_EQ(0, GetMoveToAccountRefusedCount(&pref_service, &sync_service)); - IncrementMoveToAccountRefusedCount(&pref_service, &sync_service); - EXPECT_EQ(1, GetMoveToAccountRefusedCount(&pref_service, &sync_service)); - IncrementMoveToAccountRefusedCount(&pref_service, &sync_service); - EXPECT_EQ(2, GetMoveToAccountRefusedCount(&pref_service, &sync_service)); + EXPECT_EQ(0, + GetMoveOfferedToNonOptedInUserCount(&pref_service, &sync_service)); + RecordMoveOfferedToNonOptedInUser(&pref_service, &sync_service); + EXPECT_EQ(1, + GetMoveOfferedToNonOptedInUserCount(&pref_service, &sync_service)); + RecordMoveOfferedToNonOptedInUser(&pref_service, &sync_service); + EXPECT_EQ(2, + GetMoveOfferedToNonOptedInUserCount(&pref_service, &sync_service)); } } // namespace features_util
diff --git a/components/performance_manager/execution_context/execution_context_registry_impl_unittest.cc b/components/performance_manager/execution_context/execution_context_registry_impl_unittest.cc index 1e898f6..d405a31 100644 --- a/components/performance_manager/execution_context/execution_context_registry_impl_unittest.cc +++ b/components/performance_manager/execution_context/execution_context_registry_impl_unittest.cc
@@ -150,8 +150,7 @@ FrameToken(base::UnguessableToken::Null()))); EXPECT_FALSE(registry_->GetFrameNodeByFrameToken( FrameToken(base::UnguessableToken::Create()))); - EXPECT_FALSE(registry_->GetWorkerNodeByWorkerToken(WorkerToken::Null())); - EXPECT_FALSE(registry_->GetWorkerNodeByWorkerToken(WorkerToken::Create())); + EXPECT_FALSE(registry_->GetWorkerNodeByWorkerToken(WorkerToken())); // Destroy nodes one by one and expect observer notifications. EXPECT_CALL(obs, OnBeforeExecutionContextRemoved(worker_ec));
diff --git a/components/performance_manager/graph/worker_node_impl.cc b/components/performance_manager/graph/worker_node_impl.cc index 35fc3cf..9c723b1 100644 --- a/components/performance_manager/graph/worker_node_impl.cc +++ b/components/performance_manager/graph/worker_node_impl.cc
@@ -19,7 +19,6 @@ worker_token_(worker_token) { DETACH_FROM_SEQUENCE(sequence_checker_); DCHECK(process_node); - DCHECK(worker_token); } WorkerNodeImpl::~WorkerNodeImpl() {
diff --git a/components/performance_manager/graph/worker_node_impl_unittest.cc b/components/performance_manager/graph/worker_node_impl_unittest.cc index 804dd3e8..ce35cbad 100644 --- a/components/performance_manager/graph/worker_node_impl_unittest.cc +++ b/components/performance_manager/graph/worker_node_impl_unittest.cc
@@ -49,7 +49,7 @@ const std::string kTestBrowserContextId = base::UnguessableToken::Create().ToString(); auto process = CreateNode<ProcessNodeImpl>(); - static const WorkerToken kTestWorkerToken = WorkerToken::Create(); + static const WorkerToken kTestWorkerToken = WorkerToken(); auto worker_impl = CreateNode<WorkerNodeImpl>( kWorkerType, process.get(), kTestBrowserContextId, kTestWorkerToken);
diff --git a/components/performance_manager/test_support/graph_test_harness.h b/components/performance_manager/test_support/graph_test_harness.h index a95cc7a..30bec65a 100644 --- a/components/performance_manager/test_support/graph_test_harness.h +++ b/components/performance_manager/test_support/graph_test_harness.h
@@ -126,7 +126,7 @@ WorkerNode::WorkerType worker_type, ProcessNodeImpl* process_node, const std::string& browser_context_id = std::string(), - const WorkerToken& token = WorkerToken::Create()) { + const WorkerToken& token = WorkerToken()) { return std::make_unique<WorkerNodeImpl>(browser_context_id, worker_type, process_node, token); }
diff --git a/components/performance_manager/worker_watcher_unittest.cc b/components/performance_manager/worker_watcher_unittest.cc index 7c48df77..7ec634d 100644 --- a/components/performance_manager/worker_watcher_unittest.cc +++ b/components/performance_manager/worker_watcher_unittest.cc
@@ -106,8 +106,7 @@ content::GlobalFrameRoutingId client_render_frame_host_id) { // Create a new token for the worker and add it to the map, along with its // client ID. - const blink::DedicatedWorkerToken token( - blink::DedicatedWorkerToken::Create()); + const blink::DedicatedWorkerToken token; auto result = dedicated_worker_client_frame_.emplace( token, client_render_frame_host_id); @@ -208,8 +207,7 @@ blink::SharedWorkerToken TestSharedWorkerService::CreateSharedWorker( int worker_process_id) { // Create a new SharedWorkerToken for the worker and add it to the map. - const blink::SharedWorkerToken shared_worker_token = - blink::SharedWorkerToken::Create(); + const blink::SharedWorkerToken shared_worker_token; GURL worker_url = GenerateWorkerUrl(); bool inserted = @@ -348,7 +346,7 @@ observer.OnVersionStartedRunning( version_id, content::ServiceWorkerRunningInfo(worker_url, GURL(), worker_process_id, - blink::ServiceWorkerToken::Create())); + blink::ServiceWorkerToken())); } return version_id;
diff --git a/components/policy/core/common/cloud/cloud_policy_client.cc b/components/policy/core/common/cloud/cloud_policy_client.cc index 3255332..760865e 100644 --- a/components/policy/core/common/cloud/cloud_policy_client.cc +++ b/components/policy/core/common/cloud/cloud_policy_client.cc
@@ -62,7 +62,7 @@ bool IsChromePolicy(const std::string& type) { return type == dm_protocol::kChromeDevicePolicyType || type == dm_protocol::kChromeUserPolicyType || - type == dm_protocol::kChromeMachineLevelUserCloudPolicyType; + IsMachineLevelUserCloudPolicyType(type); } em::PolicyValidationReportRequest::ValidationResultType
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.cc b/components/policy/core/common/cloud/cloud_policy_constants.cc index 316a19e0..110e23c 100644 --- a/components/policy/core/common/cloud/cloud_policy_constants.cc +++ b/components/policy/core/common/cloud/cloud_policy_constants.cc
@@ -82,6 +82,8 @@ "google/chromeos/signinextension"; const char kChromeMachineLevelUserCloudPolicyType[] = "google/chrome/machine-level-user"; +const char kChromeMachineLevelUserCloudPolicyIOSType[] = + "google/chrome/machine-level-user-ios"; const char kChromeMachineLevelExtensionCloudPolicyType[] = "google/chrome/machine-level-extension"; const char kChromeRemoteCommandPolicyType[] = "google/chromeos/remotecommand";
diff --git a/components/policy/core/common/cloud/cloud_policy_constants.h b/components/policy/core/common/cloud/cloud_policy_constants.h index e8e790ef..2fe917c5 100644 --- a/components/policy/core/common/cloud/cloud_policy_constants.h +++ b/components/policy/core/common/cloud/cloud_policy_constants.h
@@ -67,6 +67,7 @@ POLICY_EXPORT extern const char kChromeExtensionPolicyType[]; POLICY_EXPORT extern const char kChromeSigninExtensionPolicyType[]; POLICY_EXPORT extern const char kChromeMachineLevelUserCloudPolicyType[]; +POLICY_EXPORT extern const char kChromeMachineLevelUserCloudPolicyIOSType[]; POLICY_EXPORT extern const char kChromeMachineLevelExtensionCloudPolicyType[]; POLICY_EXPORT extern const char kChromeRemoteCommandPolicyType[];
diff --git a/components/policy/core/common/cloud/cloud_policy_service.cc b/components/policy/core/common/cloud/cloud_policy_service.cc index 5356f12..4cfc856 100644 --- a/components/policy/core/common/cloud/cloud_policy_service.cc +++ b/components/policy/core/common/cloud/cloud_policy_service.cc
@@ -11,6 +11,7 @@ #include "base/metrics/histogram_macros.h" #include "base/time/time.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" +#include "components/policy/core/common/cloud/cloud_policy_util.h" #include "components/policy/proto/device_management_backend.pb.h" namespace em = enterprise_management; @@ -133,8 +134,7 @@ } else if (policy_type_ == dm_protocol::kChromeDevicePolicyType) { UMA_HISTOGRAM_CUSTOM_COUNTS("Enterprise.PolicyUpdatePeriod.Device", age.InDays(), 1, 1000, 100); - } else if (policy_type_ == - dm_protocol::kChromeMachineLevelUserCloudPolicyType) { + } else if (IsMachineLevelUserCloudPolicyType(policy_type_)) { UMA_HISTOGRAM_CUSTOM_COUNTS( "Enterprise.PolicyUpdatePeriod.MachineLevelUser", age.InDays(), 1, 1000, 100);
diff --git a/components/policy/core/common/cloud/cloud_policy_util.cc b/components/policy/core/common/cloud/cloud_policy_util.cc index 2d08bd00..10a07528 100644 --- a/components/policy/core/common/cloud/cloud_policy_util.cc +++ b/components/policy/core/common/cloud/cloud_policy_util.cc
@@ -5,6 +5,7 @@ #include "components/policy/core/common/cloud/cloud_policy_util.h" #include "build/build_config.h" +#include "components/policy/core/common/cloud/cloud_policy_constants.h" #if defined(OS_WIN) #include <Windows.h> // For GetComputerNameW() @@ -220,4 +221,16 @@ return device_identifier; } +bool IsMachineLevelUserCloudPolicyType(const std::string& type) { + return type == GetMachineLevelUserCloudPolicyTypeForCurrentOS(); +} + +std::string GetMachineLevelUserCloudPolicyTypeForCurrentOS() { +#if defined(OS_IOS) + return dm_protocol::kChromeMachineLevelUserCloudPolicyIOSType; +#else + return dm_protocol::kChromeMachineLevelUserCloudPolicyType; +#endif +} + } // namespace policy
diff --git a/components/policy/core/common/cloud/cloud_policy_util.h b/components/policy/core/common/cloud/cloud_policy_util.h index 73b77df6d..538dda3 100644 --- a/components/policy/core/common/cloud/cloud_policy_util.h +++ b/components/policy/core/common/cloud/cloud_policy_util.h
@@ -44,6 +44,13 @@ POLICY_EXPORT std::unique_ptr<enterprise_management::BrowserDeviceIdentifier> GetBrowserDeviceIdentifier(); +// Returns true if the given policy type corresponds to the machine-level user +// cloud policy type of the current platform. +POLICY_EXPORT bool IsMachineLevelUserCloudPolicyType(const std::string& type); + +// Returns the machine-level user cloud policy type for the current platform. +POLICY_EXPORT std::string GetMachineLevelUserCloudPolicyTypeForCurrentOS(); + } // namespace policy #endif // COMPONENTS_POLICY_CORE_COMMON_CLOUD_CLOUD_POLICY_UTIL_H_
diff --git a/components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.cc b/components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.cc index 8ec5300..6c9bc208 100644 --- a/components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.cc +++ b/components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.cc
@@ -10,6 +10,7 @@ #include "base/threading/thread_task_runner_handle.h" #include "components/policy/core/common/cloud/cloud_external_data_manager.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" +#include "components/policy/core/common/cloud/cloud_policy_util.h" #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_store.h" #include "components/policy/core/common/features.h" #include "components/policy/core/common/policy_pref_names.h" @@ -30,7 +31,7 @@ const base::FilePath& policy_dir, const scoped_refptr<base::SequencedTaskRunner>& task_runner, network::NetworkConnectionTrackerGetter network_connection_tracker_getter) - : CloudPolicyManager(dm_protocol::kChromeMachineLevelUserCloudPolicyType, + : CloudPolicyManager(GetMachineLevelUserCloudPolicyTypeForCurrentOS(), std::string(), store.get(), task_runner,
diff --git a/components/policy/core/common/cloud/machine_level_user_cloud_policy_store.cc b/components/policy/core/common/cloud/machine_level_user_cloud_policy_store.cc index bfa2517b..f4162a0 100644 --- a/components/policy/core/common/cloud/machine_level_user_cloud_policy_store.cc +++ b/components/policy/core/common/cloud/machine_level_user_cloud_policy_store.cc
@@ -9,6 +9,7 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" +#include "components/policy/core/common/cloud/cloud_policy_util.h" #include "components/policy/core/common/cloud/dm_token.h" #include "components/policy/proto/device_management_backend.pb.h" @@ -117,7 +118,7 @@ auto validator = std::make_unique<UserCloudPolicyValidator>( std::move(policy), background_task_runner()); validator->ValidatePolicyType( - dm_protocol::kChromeMachineLevelUserCloudPolicyType); + GetMachineLevelUserCloudPolicyTypeForCurrentOS()); validator->ValidateDMToken(machine_dm_token_.value(), CloudPolicyValidatorBase::DM_TOKEN_REQUIRED); validator->ValidateDeviceId(machine_client_id_,
diff --git a/components/policy/core/common/cloud/machine_level_user_cloud_policy_store_unittest.cc b/components/policy/core/common/cloud/machine_level_user_cloud_policy_store_unittest.cc index 32fe587bd..c063444 100644 --- a/components/policy/core/common/cloud/machine_level_user_cloud_policy_store_unittest.cc +++ b/components/policy/core/common/cloud/machine_level_user_cloud_policy_store_unittest.cc
@@ -11,6 +11,7 @@ #include "base/test/task_environment.h" #include "base/threading/thread_task_runner_handle.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" +#include "components/policy/core/common/cloud/cloud_policy_util.h" #include "components/policy/core/common/cloud/mock_cloud_policy_store.h" #include "components/policy/core/common/cloud/policy_builder.h" #include "testing/gmock/include/gmock/gmock.h" @@ -29,7 +30,7 @@ : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) { policy_.SetDefaultInitialSigningKey(); policy_.policy_data().set_policy_type( - dm_protocol::kChromeMachineLevelUserCloudPolicyType); + GetMachineLevelUserCloudPolicyTypeForCurrentOS()); policy_.payload().mutable_searchsuggestenabled()->set_value(false); policy_.Build(); }
diff --git a/components/policy/core/common/policy_map.cc b/components/policy/core/common/policy_map.cc index 3fa33e9..8c8cb7d 100644 --- a/components/policy/core/common/policy_map.cc +++ b/components/policy/core/common/policy_map.cc
@@ -217,19 +217,6 @@ PolicyLevel level, PolicyScope scope, PolicySource source, - std::unique_ptr<base::Value> value, - std::unique_ptr<ExternalDataFetcher> external_data_fetcher) { - Entry entry(level, scope, source, - value ? base::make_optional(std::move(*value)) : base::nullopt, - std::move(external_data_fetcher)); - Set(policy, std::move(entry)); -} - -void PolicyMap::Set( - const std::string& policy, - PolicyLevel level, - PolicyScope scope, - PolicySource source, base::Optional<base::Value> value, std::unique_ptr<ExternalDataFetcher> external_data_fetcher) { Entry entry(level, scope, source, std::move(value),
diff --git a/components/policy/core/common/policy_map.h b/components/policy/core/common/policy_map.h index 5990345..9b07543 100644 --- a/components/policy/core/common/policy_map.h +++ b/components/policy/core/common/policy_map.h
@@ -143,16 +143,6 @@ // Overwrites any existing information stored in the map for the key |policy|. // Resets the error for that policy to the empty string. - // DEPRECATED: Use the other version that takes base::Optional<base::Value> - // below. - // TODO(crbug.com/1092469): Migrate the existing usages and delete this - // method. - void Set(const std::string& policy, - PolicyLevel level, - PolicyScope scope, - PolicySource source, - std::unique_ptr<base::Value> value, - std::unique_ptr<ExternalDataFetcher> external_data_fetcher); void Set(const std::string& policy, PolicyLevel level, PolicyScope scope,
diff --git a/components/policy/proto/device_management_backend.proto b/components/policy/proto/device_management_backend.proto index 9d192cc..d4a56bcb6 100644 --- a/components/policy/proto/device_management_backend.proto +++ b/components/policy/proto/device_management_backend.proto
@@ -2885,7 +2885,7 @@ CRX_FETCH_URL_EMPTY = 25; CRX_FETCH_URL_INVALID = 26; - }; + } // Stage of extension installing process. See InstallStageTracker::Stage for // more details. InstallStageTracker::Stage is the main enum and this is @@ -2909,7 +2909,7 @@ INSTALLING = 3; COMPLETE = 4; - }; + } // Type of current user. See user_manager::UserType for more details. // user_manager::UserType is the main enum and this is a copy used for @@ -2958,7 +2958,7 @@ DOWNLOADING_CRX_RETRY = 8; FINISHED = 9; - }; + } // Timestamp, in microseconds since epoch. Set for all log // events.
diff --git a/components/policy/resources/policy_templates.json b/components/policy/resources/policy_templates.json index ebda116..09ea3e0d 100644 --- a/components/policy/resources/policy_templates.json +++ b/components/policy/resources/policy_templates.json
@@ -7515,7 +7515,7 @@ 'tags': ['local-data-access'], 'desc': '''Setting the policy to Enabled imports the homepage from the previous default browser on first run. Setting the policy to Disabled or leaving it unset means the homepage isn't imported on first run. - Users can trigger an import dialog and the the homepage checkbox will be checked or unchecked to match this policy's value.''', + Users can trigger an import dialog and the homepage checkbox will be checked or unchecked to match this policy's value.''', 'label': '''Import of homepage from default browser on first run''', }, { @@ -17361,6 +17361,7 @@ 'type': 'string', 'schema': { 'type': 'string' }, 'supported_on': ['chrome.*:72-'], + 'future_on': [ 'ios' ], 'features': { 'dynamic_refresh': False, 'per_profile': False, @@ -22730,16 +22731,12 @@ 'id': 758, 'caption': '''Control the <ph name="PRODUCT_NAME">BackForwardCache</ph> feature.''', 'tags': [], - 'desc': '''When enabled the <ph name="PRODUCT_NAME">BackForwardCache</ph> feature causes web pages to be preserved in its current state (document tree, script, etc.) into the back-forward cache when navigated away from the page. - If we navigated back to the page, the page will be restored from the back-forward cache, showing it in the state it was in when cached before. + 'desc': '''When enabled the <ph name="PRODUCT_NAME">BackForwardCache</ph> feature allows the use of the back-forward cache. When navigating away from a page, its current state (document tree, script, etc.) may be preserved in the back-forward cache. If the browser navigates back to the page, the page may be restored from the back-forward cache and displayed in the state it was in before being cached. - This feature might break some websites that does not expect itself to - get cached, particularly websites that depend on unload handlers being - fired when navigated away from the page, as the unload event will - not be dispatched when navigated away from a page and it gets saved - in the back-forward cache. + This feature might cause issues for some websites that do not expect this caching. In particular, some websites depend on the "<ph name="UNLOAD_HANDLER_NAME">unload</ph>" event being dispatched when the browser navigates away from the page. The "<ph name="UNLOAD_HANDLER_NAME">unload</ph>" event will not be dispatched if the page enters the back-forward cache. - If this policy is set to enabled or not set, the <ph name="PRODUCT_NAME">BackForwardCache</ph> feature will be enabled. + If this policy is set to enabled or not set, + the <ph name="PRODUCT_NAME">BackForwardCache</ph> feature will be enabled. If this policy is set to disabled then the feature will be force disabled. ''',
diff --git a/components/policy/tools/template_writers/writers/jamf_writer.py b/components/policy/tools/template_writers/writers/jamf_writer.py index 1e9b6eaa..e00ac95 100755 --- a/components/policy/tools/template_writers/writers/jamf_writer.py +++ b/components/policy/tools/template_writers/writers/jamf_writer.py
@@ -108,7 +108,7 @@ if 'minimum' in policy['schema']: policy_output['minimum'] = policy['schema']['minimum'] if 'maximum' in policy['schema']: - policy_output['properties']['maximum'] = policy['schema']['maximum'] + policy_output['maximum'] = policy['schema']['maximum'] elif policy['type'] == 'list': policy_output['items'] = policy['schema']['items'] elif policy['type'] == 'string-enum-list' or policy[
diff --git a/components/policy/tools/template_writers/writers/jamf_writer_unittest.py b/components/policy/tools/template_writers/writers/jamf_writer_unittest.py index e73346f1..3d9f0ba 100755 --- a/components/policy/tools/template_writers/writers/jamf_writer_unittest.py +++ b/components/policy/tools/template_writers/writers/jamf_writer_unittest.py
@@ -15,6 +15,10 @@ from writers import writer_unittest_common +def _JsonFormat(input): + return json.dumps(input, indent=2, sort_keys=True, separators=(',', ': ')) + + class JamfWriterUnitTests(writer_unittest_common.WriterUnittestCommon): '''Unit tests for JamfWriter.''' @@ -53,10 +57,7 @@ 'placeholders': [], 'messages': {}, } - return json.dumps(template, - indent=2, - sort_keys=True, - separators=(',', ': ')) + return _JsonFormat(template) def _GetExpectedOutput(self, policy_name, policy_type, policy_caption, initial_type): @@ -96,7 +97,7 @@ 'title': 'title_obj' } - return json.dumps(output, indent=2, sort_keys=True, separators=(',', ': ')) + return _JsonFormat(output) def testStringPolicy(self): policy_json = self._GetTestPolicyTemplate('stringPolicy', 'string', '', @@ -114,6 +115,48 @@ output = self.GetOutput(policy_json, {'_google_chrome': '1'}, 'jamf') self.assertEquals(output.strip(), expected.strip()) + def testIntPolicyWithMinAndMax(self): + template = { + 'policy_definitions': [{ + 'name': 'intPolicyWithMinAndMax', + 'id': 1, + 'type': 'int', + 'supported_on': ['chrome.mac:*-'], + 'caption': 'An int policy with min and max', + 'desc': '', + 'schema': { + 'type': 'int', + 'minimum': 0, + 'maximum': 10 + } + }], + 'policy_atomic_group_definitions': [], + 'placeholders': [], + 'messages': {}, + } + policy_json = _JsonFormat(template) + + expected = { + 'description': 'Google Chrome', + 'options': { + 'remove_empty_properties': True + }, + 'properties': { + 'intPolicyWithMinAndMax': { + 'description': 'An int policy with min and max', + 'maximum': 10, + 'minimum': 0, + 'title': 'intPolicyWithMinAndMax', + 'type': 'integer' + } + }, + 'title': 'com.google.chrome' + } + expected_json = _JsonFormat(expected) + + output = self.GetOutput(policy_json, {'_google_chrome': '1'}, 'jamf') + self.assertEquals(output.strip(), expected_json.strip()) + def testIntEnumPolicy(self): policy_json = self._GetTestPolicyTemplate('intPolicy', 'int-enum', '', 'An int-enum policy') @@ -203,10 +246,7 @@ 'placeholders': [], 'messages': {}, } - policy_json = json.dumps(template, - indent=2, - sort_keys=True, - separators=(',', ': ')) + policy_json = _JsonFormat(template) expected = { 'description': 'Google Chrome', @@ -237,10 +277,7 @@ 'items': copy.deepcopy(expected['properties']['name']['items']) } - output_expected = json.dumps(expected, - indent=2, - sort_keys=True, - separators=(',', ': ')) + output_expected = _JsonFormat(expected) output = self.GetOutput(policy_json, {'_google_chrome': '1'}, 'jamf') self.assertEquals(output.strip(), output_expected.strip())
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index 64bab355..75637e6 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -47,7 +47,6 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_data.h" #include "third_party/blink/public/platform/web_double_size.h" -#include "third_party/blink/public/platform/web_scoped_page_pauser.h" #include "third_party/blink/public/platform/web_size.h" #include "third_party/blink/public/platform/web_url.h" #include "third_party/blink/public/platform/web_url_request.h" @@ -1113,11 +1112,6 @@ const GURL& url, base::Optional<blink::WebNavigationType> navigation_type) { is_loading_ = true; - - // If the renderer navigates while paused, unpause to let the navigation - // proceed. - if (print_preview_context_.IsPaused()) - auto pauser = print_preview_context_.TakePauser(); } void PrintRenderFrameHelper::DidFailProvisionalLoad() { @@ -1152,12 +1146,7 @@ web_frame->DispatchBeforePrintEvent(); if (!weak_this) return; - - // Pause between onbeforeprint and onafterprint events. - // https://html.spec.whatwg.org/C/#printing-steps - Print(web_frame, blink::WebNode(), PrintRequestType::kScripted, - blink::WebScopedPagePauser::Create()); - + Print(web_frame, blink::WebNode(), PrintRequestType::kScripted); if (weak_this) web_frame->DispatchAfterPrintEvent(); } @@ -1192,12 +1181,7 @@ // If we are printing a PDF extension frame, find the plugin node and print // that instead. auto plugin = delegate_->GetPdfElement(frame); - - // Pause between onbeforeprint and onafterprint events. - // https://html.spec.whatwg.org/C/#printing-steps - Print(frame, plugin, PrintRequestType::kRegular, - blink::WebScopedPagePauser::Create()); - + Print(frame, plugin, PrintRequestType::kRegular); if (!render_frame_gone_) frame->DispatchAfterPrintEvent(); // WARNING: |this| may be gone at this point. Do not do any more work here and @@ -1213,13 +1197,10 @@ NOTREACHED(); return; } - - // Hand over control, including Print Preview's WebScopedPagePauser, to the - // system print dialog. - Print(frame, print_preview_context_.source_node(), PrintRequestType::kRegular, - print_preview_context_.TakePauser()); + Print(frame, print_preview_context_.source_node(), + PrintRequestType::kRegular); if (!render_frame_gone_) - print_preview_context_.DispatchAfterPrintEvent(); + frame->DispatchAfterPrintEvent(); // WARNING: |this| may be gone at this point. Do not do any more work here and // just return. } @@ -1314,7 +1295,7 @@ void PrintRenderFrameHelper::OnPrintPreviewDialogClosed() { ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr()); - print_preview_context_.DispatchAfterPrintEvent(); + print_preview_context_.source_frame()->DispatchAfterPrintEvent(); } #endif // BUILDFLAG(ENABLE_PRINT_PREVIEW) @@ -1364,9 +1345,6 @@ // try to handle pdf plugin element until that bug is fixed. { TRACE_EVENT0("print", "PrintRenderFrameHelper::PrintFrameContent"); - // Pause between onbeforeprint and onafterprint events. - // https://html.spec.whatwg.org/C/#printing-steps - auto page_pauser = blink::WebScopedPagePauser::Create(); if (frame->PrintBegin(web_print_params, /*constrain_to_node=*/blink::WebElement())) { frame->PrintPage(0, canvas); @@ -1464,12 +1442,6 @@ prep_frame_view_ = std::make_unique<PrepareFrameAndViewForPrint>( print_params, print_preview_context_.source_frame(), print_preview_context_.source_node(), ignore_css_margins_); - - // The renderer needs to load a new page to print the selection. Must unpause - // to do that. - if (print_params.selection_only) - auto pauser_to_destroy = print_preview_context_.TakePauser(); - prep_frame_view_->CopySelectionIfNeeded( render_frame()->GetWebkitPreferences(), base::BindOnce(&PrintRenderFrameHelper::OnFramePreparedForPreviewDocument, @@ -1481,16 +1453,7 @@ PrepareFrameForPreviewDocument(); return; } - CreatePreviewDocumentResult result = CreatePreviewDocument(); - - // Now that the renderer has finished generating the print preview for a - // selection, pause again. The system print dialog path in Print() does not - // need to do this, since that dialog is done, whereas the Print Preview - // dialog will continue to generate more previews. - if (print_pages_params_->params.selection_only) - print_preview_context_.Pause(); - if (result != CREATE_IN_PROGRESS) DidFinishPrinting(result == CREATE_SUCCESS ? OK : FAIL_PREVIEW); } @@ -1816,7 +1779,7 @@ return; Print(duplicate_node.GetDocument().GetFrame(), duplicate_node, - PrintRequestType::kRegular, blink::WebScopedPagePauser::Create()); + PrintRequestType::kRegular); // Check if |this| is still valid. if (!weak_this) return; @@ -1829,11 +1792,9 @@ print_node_in_progress_ = false; } -void PrintRenderFrameHelper::Print( - blink::WebLocalFrame* frame, - const blink::WebNode& node, - PrintRequestType print_request_type, - std::unique_ptr<blink::WebScopedPagePauser> pauser) { +void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame, + const blink::WebNode& node, + PrintRequestType print_request_type) { // If still not finished with earlier print request simply ignore. if (prep_frame_view_) return; @@ -1879,11 +1840,6 @@ } } - // The renderer needs to load a new page to print the selection. Must unpause - // to do that. - if (print_pages_params_->params.selection_only) - pauser.reset(); - // Render Pages for printing. if (!RenderPagesForPrint(frame_ref.GetFrame(), node)) { LOG(ERROR) << "RenderPagesForPrint failed"; @@ -2375,10 +2331,9 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type) { auto weak_this = weak_ptr_factory_.GetWeakPtr(); - print_preview_context_.DispatchBeforePrintEvent(weak_this); + print_preview_context_.source_frame()->DispatchBeforePrintEvent(); if (!weak_this) return; - const bool is_from_arc = print_preview_context_.IsForArc(); const bool is_modifiable = print_preview_context_.IsModifiable(); const bool is_pdf = print_preview_context_.IsPdf(); @@ -2536,12 +2491,7 @@ PrintRenderFrameHelper::PrintPreviewContext::PrintPreviewContext() = default; -PrintRenderFrameHelper::PrintPreviewContext::~PrintPreviewContext() { - // Make sure |pauser_| is null. If |pauser_| still exists, it will try to - // unpause during teardown, and that is too late. - // DispatchAfterPrintEvent() or TakePauser() should have destroyed it already. - DCHECK(!pauser_); -} +PrintRenderFrameHelper::PrintPreviewContext::~PrintPreviewContext() = default; void PrintRenderFrameHelper::PrintPreviewContext::InitWithFrame( blink::WebLocalFrame* web_frame) { @@ -2564,38 +2514,6 @@ CalculatePluginAttributes(); } -bool PrintRenderFrameHelper::PrintPreviewContext::IsPaused() const { - return !!pauser_; -} - -void PrintRenderFrameHelper::PrintPreviewContext::Pause() { - DCHECK(!pauser_); - pauser_ = blink::WebScopedPagePauser::Create(); -} - -std::unique_ptr<blink::WebScopedPagePauser> -PrintRenderFrameHelper::PrintPreviewContext::TakePauser() { - DCHECK(pauser_); - return std::move(pauser_); -} - -void PrintRenderFrameHelper::PrintPreviewContext::DispatchBeforePrintEvent( - base::WeakPtr<PrintRenderFrameHelper> weak_this) { - source_frame()->DispatchBeforePrintEvent(); - if (!weak_this) - return; - - DCHECK(!pauser_); - pauser_ = blink::WebScopedPagePauser::Create(); -} - -void PrintRenderFrameHelper::PrintPreviewContext::DispatchAfterPrintEvent() { - // No DCHECK(pauser_), as |pauser_| may have been reset by TakePauser(). - pauser_.reset(); - - source_frame()->DispatchAfterPrintEvent(); -} - void PrintRenderFrameHelper::PrintPreviewContext::OnPrintPreview() { DCHECK_EQ(INITIALIZED, state_); ClearContext();
diff --git a/components/printing/renderer/print_render_frame_helper.h b/components/printing/renderer/print_render_frame_helper.h index 9f69646..6ad711f 100644 --- a/components/printing/renderer/print_render_frame_helper.h +++ b/components/printing/renderer/print_render_frame_helper.h
@@ -50,9 +50,8 @@ namespace blink { class WebLocalFrame; -class WebScopedPagePauser; class WebView; -} // namespace blink +} namespace content { class AXTreeSnapshotter; @@ -292,8 +291,7 @@ // WARNING: |this| may be gone after this method returns. void Print(blink::WebLocalFrame* frame, const blink::WebNode& node, - PrintRequestType print_request_type, - std::unique_ptr<blink::WebScopedPagePauser> pauser); + PrintRequestType print_request_type); // Notification when printing is done - signal tear-down/free resources. void DidFinishPrinting(PrintingResult result); @@ -475,17 +473,6 @@ void InitWithFrame(blink::WebLocalFrame* web_frame); void InitWithNode(const blink::WebNode& web_node); - // Manual control of pausing/unpausing for special situations. - bool IsPaused() const; - void Pause(); - std::unique_ptr<blink::WebScopedPagePauser> TakePauser(); - - // Dispatchs onbeforeprint/onafterprint events. Use these instead of calling - // the WebLocalFrame version on source_frame(). - void DispatchBeforePrintEvent( - base::WeakPtr<PrintRenderFrameHelper> weak_this); - void DispatchAfterPrintEvent(); - // Does bookkeeping at the beginning of print preview. void OnPrintPreview(); @@ -571,10 +558,6 @@ std::unique_ptr<PrepareFrameAndViewForPrint> prep_frame_view_; - // Manages when to pause between onbeforeprint and onafterprint events. - // https://html.spec.whatwg.org/C/#printing-steps - std::unique_ptr<blink::WebScopedPagePauser> pauser_; - // The typefaces encountered in the content during document serialization. ContentProxySet typeface_content_info_;
diff --git a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChromeSigninController.java b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChromeSigninController.java index f12d1ad..3fc00cd 100644 --- a/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChromeSigninController.java +++ b/components/signin/core/browser/android/java/src/org/chromium/components/signin/ChromeSigninController.java
@@ -14,8 +14,7 @@ public class ChromeSigninController { public static final String TAG = "ChromeSigninController"; - // Used by ChromeBackupAgent and for testing. - public static final String SIGNED_IN_ACCOUNT_KEY = "google.services.username"; + private static final String SIGNED_IN_ACCOUNT_KEY = "google.services.username"; private static final Object LOCK = new Object();
diff --git a/components/sync/driver/sync_driver_switches.cc b/components/sync/driver/sync_driver_switches.cc index 8482a15..5d3d3ed 100644 --- a/components/sync/driver/sync_driver_switches.cc +++ b/components/sync/driver/sync_driver_switches.cc
@@ -48,7 +48,7 @@ // If enabled, the sync engine will be shut down in the "paused" state. const base::Feature kStopSyncInPausedState{"StopSyncInPausedState", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Controls whether to enable syncing of Wi-Fi configurations. const base::Feature kSyncWifiConfigurations{"SyncWifiConfigurations",
diff --git a/components/variations/proto/client_variations.proto b/components/variations/proto/client_variations.proto index e349c938..6eecca2 100644 --- a/components/variations/proto/client_variations.proto +++ b/components/variations/proto/client_variations.proto
@@ -14,10 +14,9 @@ // NOTE: If you update this proto, you'll also need to rebuild the JS parser for // devtools. See //components/variations/proto/devtools/BUILD.gn for details. message ClientVariations { - // A list of client experiment variation IDs that are active. + // Active client experiment variation IDs. repeated int32 variation_id = 1; - // A list of client experiment variation IDs that trigger server side - // behavior. + // Active client experiment variation IDs that trigger server-side behavior. repeated int32 trigger_variation_id = 3; }
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc index 5a22a89d..a6e6174 100644 --- a/components/viz/service/display/skia_renderer.cc +++ b/components/viz/service/display/skia_renderer.cc
@@ -2519,6 +2519,10 @@ } } + if (!content_image) { + return; + } + // If the RP generated mipmaps when it was created, set quality to medium, // which turns on mipmap filtering in Skia. if (backing.generate_mipmap)
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 11c1162..b9cdd83 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -598,7 +598,9 @@ image_context->color_space(), Fulfill, DoNothing, DoNothing, image_context.get()), backend_format); - DCHECK(image_context->has_image()); + if (!image_context->has_image()) { + return nullptr; + } } images_in_current_paint_.push_back(image_context.get()); return image_context->image();
diff --git a/content/browser/accessibility/accessibility_event_recorder_auralinux.cc b/content/browser/accessibility/accessibility_event_recorder_auralinux.cc index e4fb424..bfe6f5a 100644 --- a/content/browser/accessibility/accessibility_event_recorder_auralinux.cc +++ b/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
@@ -168,6 +168,8 @@ AddATKEventListener("ATK:AtkText:text-caret-moved"); AddATKEventListener("ATK:AtkText:text-attributes-changed"); AddATKEventListener("ATK:AtkSelection:selection-changed"); + AddATKEventListener("ATK:AtkTable:column-reordered"); + AddATKEventListener("ATK:AtkTable:row-reordered"); } void AccessibilityEventRecorderAuraLinux::RemoveATKEventListeners() {
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc index f5b834bc..7b3c963 100644 --- a/content/browser/child_process_security_policy_impl.cc +++ b/content/browser/child_process_security_policy_impl.cc
@@ -1890,8 +1890,21 @@ // available IsolatedOriginEntries. BrowsingInstanceId browsing_instance_id( isolation_context.browsing_instance_id()); - if (browsing_instance_id.is_null()) + + if (browsing_instance_id.is_null()) { browsing_instance_id = SiteInstanceImpl::NextBrowsingInstanceId(); + } else { + // Check the opt-in isolation status of |origin| in |isolation_context|. + // Note that while IsolatedOrigins considers any sub-origin of an isolated + // origin as also being isolated, with opt-in we will always either return + // false, or true with result set to |origin|. We give priority to origins + // requesting opt-in isolation over command-line isolation, but don't check + // for opt-in if we didn't get a valid BrowsingInstance id. + if (ShouldOriginGetOptInIsolation(isolation_context, origin)) { + *result = origin; + return true; + } + } // Look up the list of origins corresponding to |origin|'s site. auto it = isolated_origins_.find(site_url); @@ -1957,16 +1970,6 @@ } } - // If no match was found via IsolatedOrigins, then check the opt-in - // isolation status of |origin| in |isolation_context|. Note that while - // IsolatedOrigins considers any sub-origin of an isolated origin as also - // being isolated, with opt-in we will always either return false, or true - // with result set to |origin|. - if (!found && ShouldOriginGetOptInIsolation(isolation_context, origin)) { - *result = origin; - found = true; - } - return found; }
diff --git a/content/browser/isolated_origin_browsertest.cc b/content/browser/isolated_origin_browsertest.cc index 15a73607..58ca7d9 100644 --- a/content/browser/isolated_origin_browsertest.cc +++ b/content/browser/isolated_origin_browsertest.cc
@@ -146,15 +146,19 @@ IsolateAllSitesForTesting(command_line); command_line->AppendSwitch(switches::kIgnoreCertificateErrors); feature_list_.InitAndEnableFeature(feature_switch()); - } - void SetUpOnMainThread() override { - IsolatedOriginTestBase::SetUpOnMainThread(); + // Start the HTTPS server here so derived tests can use it if they override + // SetUpCommandLine(). https_server()->AddDefaultHandlers(GetTestDataFilePath()); https_server()->RegisterRequestHandler( base::BindRepeating(&OriginIsolationOptInServerTest::HandleResponse, base::Unretained(this))); ASSERT_TRUE(https_server()->Start()); + } + + void SetUpOnMainThread() override { + IsolatedOriginTestBase::SetUpOnMainThread(); + host_resolver()->AddRule("*", "127.0.0.1"); embedded_test_server()->StartAcceptingConnections(); } @@ -281,6 +285,81 @@ DISALLOW_COPY_AND_ASSIGN(OriginIsolationOptInHeaderTest); }; +// This class allows testing the interaction of OptIn isolation and command-line +// isolation for origins. Tests using this class will isolate foo.com and +// bar.com by default using command-line isolation, but any opt-in isolation +// will override this. +class OriginIsolationOptInOriginPolicyCommandLineTest + : public OriginIsolationOptInOriginPolicyTest { + public: + OriginIsolationOptInOriginPolicyCommandLineTest() = default; + + void SetUpCommandLine(base::CommandLine* command_line) override { + OriginIsolationOptInOriginPolicyTest::SetUpCommandLine(command_line); + // The base class should already have started the HTTPS server so we can use + // it here to generate origins to specify on the command line. + ASSERT_TRUE(https_server()->Started()); + + std::string origin_list = https_server()->GetURL("foo.com", "/").spec() + + "," + + https_server()->GetURL("bar.com", "/").spec(); + command_line->AppendSwitchASCII(switches::kIsolateOrigins, origin_list); + } + + private: + DISALLOW_COPY_AND_ASSIGN(OriginIsolationOptInOriginPolicyCommandLineTest); +}; + +// This test verifies that opt-in isolation takes precedence over command-line +// isolation. It loads an opt-in isolated base origin (which would have +// otherwise been isolated via command-line isolation), and then loads a child +// frame sub-origin which should-not be isolated (but would have been if the +// base origin was command-line isolated). +IN_PROC_BROWSER_TEST_F(OriginIsolationOptInOriginPolicyCommandLineTest, + OptInOverridesCommandLine) { + SetOriginPolicyManifest(R"({ "ids": ["my-policy"], "isolation": true })"); + // Start off with an isolated base-origin in an a(a) configuration, then + // navigate the subframe to a sub-origin not requesting isolation. + // Note: this works because we serve mock headers with the base origin's html + // file, requesting loading the origin policy. + GURL isolated_base_origin_url(https_server()->GetURL( + "foo.com", "/isolated_base_origin_with_subframe.html")); + GURL non_isolated_sub_origin( + https_server()->GetURL("non_isolated.foo.com", "/title1.html")); + EXPECT_TRUE(NavigateToURL(shell(), isolated_base_origin_url)); + EXPECT_EQ(2u, shell()->web_contents()->GetAllFrames().size()); + + FrameTreeNode* root = web_contents()->GetFrameTree()->root(); + FrameTreeNode* child_frame_node = root->child_at(0); + NavigateFrameToURL(child_frame_node, non_isolated_sub_origin); + + auto* policy = ChildProcessSecurityPolicyImpl::GetInstance(); + EXPECT_TRUE(policy->ShouldOriginGetOptInIsolation( + root->current_frame_host()->GetSiteInstance()->GetIsolationContext(), + url::Origin::Create(isolated_base_origin_url))); + EXPECT_FALSE(policy->ShouldOriginGetOptInIsolation( + root->current_frame_host()->GetSiteInstance()->GetIsolationContext(), + url::Origin::Create(non_isolated_sub_origin))); + // Make sure the child (i.e. sub-origin) is not isolated. + EXPECT_NE(root->current_frame_host()->GetSiteInstance(), + child_frame_node->current_frame_host()->GetSiteInstance()); + EXPECT_EQ( + GURL("https://foo.com"), + child_frame_node->current_frame_host()->GetSiteInstance()->GetSiteURL()); + // The following test passes because IsIsolatedOrigin doesn't distinguish + // between command-line isolation and opt-in isolation. + EXPECT_TRUE(policy->IsIsolatedOrigin( + root->current_frame_host()->GetSiteInstance()->GetIsolationContext(), + url::Origin::Create(non_isolated_sub_origin))); + + // Make sure the master opt-in list has the base origin isolated and the sub + // origin not isolated. + EXPECT_TRUE(policy->HasOriginEverRequestedOptInIsolation( + url::Origin::Create(isolated_base_origin_url))); + EXPECT_FALSE(policy->HasOriginEverRequestedOptInIsolation( + url::Origin::Create(non_isolated_sub_origin))); +} + // This tests that origin policy opt-in causes the origin to end up in the // isolated origins list. IN_PROC_BROWSER_TEST_F(OriginIsolationOptInOriginPolicyTest, Basic) {
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 2aecfd92..79d364a 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -612,6 +612,7 @@ GetWidget()->RendererExited(); delegate_->RenderViewTerminated(this, info.status, info.exit_code); + // |this| might have been deleted. Do not add code here. } bool RenderViewHostImpl::Send(IPC::Message* msg) {
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index 97ea7e3..5f8b0a1 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -864,7 +864,7 @@ status_ = EmbeddedWorkerStatus::STARTING; starting_phase_ = ALLOCATING_PROCESS; network_accessed_for_script_ = false; - token_ = blink::ServiceWorkerToken::Create(); + token_ = blink::ServiceWorkerToken(); for (auto& observer : listener_list_) observer.OnStarting();
diff --git a/content/browser/service_worker/service_worker_container_host_unittest.cc b/content/browser/service_worker/service_worker_container_host_unittest.cc index 55a738a..ecc6d713 100644 --- a/content/browser/service_worker/service_worker_container_host_unittest.cc +++ b/content/browser/service_worker/service_worker_container_host_unittest.cc
@@ -1032,14 +1032,14 @@ ASSERT_TRUE( base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker)); TestReservedClientsAreNotExposed( - ServiceWorkerClientInfo(blink::DedicatedWorkerToken::Create()), + ServiceWorkerClientInfo(blink::DedicatedWorkerToken()), GURL("https://www.example.com/dedicated_worker.js")); } TEST_F(ServiceWorkerContainerHostTest, ReservedClientsAreNotExposedToClientsApiForSharedWorker) { TestReservedClientsAreNotExposed( - ServiceWorkerClientInfo(blink::SharedWorkerToken::Create()), + ServiceWorkerClientInfo(blink::SharedWorkerToken()), GURL("https://www.example.com/shared_worker.js")); } @@ -1103,14 +1103,13 @@ ASSERT_TRUE( base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker)); TestClientPhaseTransition( - ServiceWorkerClientInfo(blink::DedicatedWorkerToken::Create()), + ServiceWorkerClientInfo(blink::DedicatedWorkerToken()), GURL("https://www.example.com/dedicated_worker.js")); } TEST_F(ServiceWorkerContainerHostTest, ClientPhaseForSharedWorker) { - TestClientPhaseTransition( - ServiceWorkerClientInfo(blink::SharedWorkerToken::Create()), - GURL("https://www.example.com/shared_worker.js")); + TestClientPhaseTransition(ServiceWorkerClientInfo(blink::SharedWorkerToken()), + GURL("https://www.example.com/shared_worker.js")); } // Run tests with BackForwardCache.
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc index faef6fb..c121519 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc +++ b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/optional.h" +#include "base/stl_util.h" #include "base/task/post_task.h" #include "content/browser/frame_host/frame_tree_node.h" #include "content/browser/frame_host/navigation_request_info.h" @@ -85,8 +86,7 @@ bool are_ancestors_secure, int frame_tree_node_id, int process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken* worker_token, mojo::PendingAssociatedReceiver<blink::mojom::ServiceWorkerContainerHost> host_receiver, mojo::PendingAssociatedRemote<blink::mojom::ServiceWorkerContainer> @@ -128,11 +128,10 @@ } else { DCHECK(resource_type == blink::mojom::ResourceType::kWorker || resource_type == blink::mojom::ResourceType::kSharedWorker); + DCHECK(worker_token); ServiceWorkerClientInfo client_info = - resource_type == blink::mojom::ResourceType::kWorker - ? ServiceWorkerClientInfo(dedicated_worker_token) - : ServiceWorkerClientInfo(shared_worker_token); + ServiceWorkerClientInfo(*worker_token); container_host = context_core->CreateContainerHostForWorker( std::move(host_receiver), process_id, std::move(client_remote), @@ -213,16 +212,14 @@ : blink::mojom::ResourceType::kSubFrame, request_info.begin_params->skip_service_worker, request_info.are_ancestors_secure, request_info.frame_tree_node_id, - ChildProcessHost::kInvalidUniqueID, blink::DedicatedWorkerToken::Null(), - blink::SharedWorkerToken::Null())); + ChildProcessHost::kInvalidUniqueID, /* worker_token = */ nullptr)); } std::unique_ptr<NavigationLoaderInterceptor> ServiceWorkerMainResourceLoaderInterceptor::CreateForWorker( const network::ResourceRequest& resource_request, int process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle) { DCHECK_CURRENTLY_ON(BrowserThread::UI); @@ -240,8 +237,7 @@ return base::WrapUnique(new ServiceWorkerMainResourceLoaderInterceptor( std::move(navigation_handle), resource_type, resource_request.skip_service_worker, /*are_ancestors_secure=*/false, - FrameTreeNode::kFrameTreeNodeInvalidId, process_id, - dedicated_worker_token, shared_worker_token)); + FrameTreeNode::kFrameTreeNodeInvalidId, process_id, &worker_token)); } ServiceWorkerMainResourceLoaderInterceptor:: @@ -296,7 +292,7 @@ base::BindOnce(&MaybeCreateLoaderOnCoreThread, GetWeakPtr(), handle_->core(), resource_type_, skip_service_worker_, are_ancestors_secure_, frame_tree_node_id_, process_id_, - dedicated_worker_token_, shared_worker_token_, + base::OptionalOrNullptr(worker_token_), std::move(host_receiver), std::move(client_remote), tentative_resource_request, browser_context, std::move(loader_callback), std::move(fallback_callback), @@ -366,16 +362,14 @@ bool are_ancestors_secure, int frame_tree_node_id, int process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token) + const DedicatedOrSharedWorkerToken* worker_token) : handle_(std::move(handle)), resource_type_(resource_type), skip_service_worker_(skip_service_worker), are_ancestors_secure_(are_ancestors_secure), frame_tree_node_id_(frame_tree_node_id), process_id_(process_id), - dedicated_worker_token_(dedicated_worker_token), - shared_worker_token_(shared_worker_token) { + worker_token_(base::OptionalFromPtr(worker_token)) { DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK(handle_); }
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h index 9d4ed77..c06736d 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h +++ b/content/browser/service_worker/service_worker_main_resource_loader_interceptor.h
@@ -9,11 +9,13 @@ #include "base/gtest_prod_util.h" #include "base/memory/weak_ptr.h" +#include "base/optional.h" #include "content/browser/loader/navigation_loader_interceptor.h" #include "content/browser/loader/single_request_url_loader_factory.h" #include "content/browser/navigation_subresource_loader_params.h" #include "content/common/content_export.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/service_worker_client_info.h" #include "content/public/common/child_process_host.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -48,8 +50,7 @@ static std::unique_ptr<NavigationLoaderInterceptor> CreateForWorker( const network::ResourceRequest& resource_request, int process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, base::WeakPtr<ServiceWorkerMainResourceHandle> navigation_handle); ~ServiceWorkerMainResourceLoaderInterceptor() override; @@ -89,8 +90,7 @@ bool are_ancestors_secure, int frame_tree_node_id, int process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token); + const DedicatedOrSharedWorkerToken* worker_token); // Returns true if a ServiceWorkerMainResourceLoaderInterceptor should be // created for a navigation to |url|. @@ -117,16 +117,21 @@ const blink::mojom::ResourceType resource_type_; const bool skip_service_worker_; - // For windows: + // For window clients: // Whether all ancestor frames of the frame that is navigating have a secure // origin. True for main frames. const bool are_ancestors_secure_; + // If the intercepted resource load is on behalf + // of a window, the |frame_tree_node_id_| will be set, |worker_token_| will be + // base::nullopt, and |process_id_| will be invalid. const int frame_tree_node_id_; - // For web workers: + // For web worker clients: + // If the intercepted resource load is on behalf of a worker the + // |frame_tree_node_id_| will be invalid, and both |process_id_| and + // |worker_token_| will be set. const int process_id_; - const blink::DedicatedWorkerToken dedicated_worker_token_; - const blink::SharedWorkerToken shared_worker_token_; + const base::Optional<DedicatedOrSharedWorkerToken> worker_token_; base::Optional<SubresourceLoaderParams> subresource_loader_params_;
diff --git a/content/browser/sms/sms_browsertest.cc b/content/browser/sms/sms_browsertest.cc index ce32f040..8c8271e4 100644 --- a/content/browser/sms/sms_browsertest.cc +++ b/content/browser/sms/sms_browsertest.cc
@@ -720,4 +720,34 @@ navigate.Run(); } +IN_PROC_BROWSER_TEST_F(SmsBrowserTest, ReportSMSReceiverStartInUseCounter) { + GURL url = GetTestUrl(nullptr, "simple_page.html"); + EXPECT_TRUE(NavigateToURL(shell(), url)); + + shell()->web_contents()->SetDelegate(&delegate_); + + ExpectSmsPrompt(); + auto provider = std::make_unique<MockSmsProvider>(); + MockSmsProvider* mock_provider_ptr = provider.get(); + BrowserMainLoop::GetInstance()->SetSmsProviderForTesting(std::move(provider)); + + EXPECT_CALL(*mock_provider_ptr, Retrieve(_)).WillOnce(Invoke([&]() { + mock_provider_ptr->NotifyReceive(url::Origin::Create(url), "hello"); + ConfirmPrompt(); + })); + base::HistogramTester histogram_tester; + std::string script = R"( + (async () => { + let cred = await navigator.credentials.get({otp: {transport: ["sms"]}}); + return cred.code; + }) (); + )"; + EXPECT_EQ("hello", EvalJs(shell(), script)); + + content::FetchHistogramsFromChildProcesses(); + histogram_tester.ExpectBucketCount( + "Blink.UseCounter.Features", blink::mojom::WebFeature::kSMSReceiverStart, + 1); +} + } // namespace content
diff --git a/content/browser/storage_partition_impl_map.cc b/content/browser/storage_partition_impl_map.cc index c7aa618..db270a1 100644 --- a/content/browser/storage_partition_impl_map.cc +++ b/content/browser/storage_partition_impl_map.cc
@@ -451,14 +451,6 @@ 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 cbb4b2c..f7db83b9 100644 --- a/content/browser/storage_partition_impl_map_unittest.cc +++ b/content/browser/storage_partition_impl_map_unittest.cc
@@ -9,14 +9,11 @@ #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 { @@ -49,48 +46,4 @@ 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 7ad9729..8194f70 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -712,6 +712,20 @@ return inner_web_contents; } +// WebContentsObserverList ----------------------------------------------------- +WebContentsImpl::WebContentsObserverList::WebContentsObserverList() = default; +WebContentsImpl::WebContentsObserverList::~WebContentsObserverList() = default; + +void WebContentsImpl::WebContentsObserverList::AddObserver( + WebContentsObserver* observer) { + observers_.AddObserver(observer); +} + +void WebContentsImpl::WebContentsObserverList::RemoveObserver( + WebContentsObserver* observer) { + observers_.RemoveObserver(observer); +} + // WebContentsImpl ------------------------------------------------------------- WebContentsImpl::WebContentsImpl(BrowserContext* browser_context) @@ -733,7 +747,6 @@ visible_capturer_count_(0), hidden_capturer_count_(0), is_being_destroyed_(false), - is_notifying_observers_(false), notify_disconnection_(false), dialog_manager_(nullptr), is_showing_before_unload_dialog_(false), @@ -800,7 +813,7 @@ // A WebContents should never be deleted while it is notifying observers, // since this will lead to a use-after-free as it continues to notify later // observers. - CHECK(!is_notifying_observers_); + CHECK(!observers_.is_notifying_observers()); FullscreenContentsSet(GetBrowserContext())->erase(this); @@ -881,34 +894,32 @@ // disappearing. if (is_currently_audible_) { is_currently_audible_ = false; - for (auto& observer : observers_) - observer.OnAudioStateChanged(false); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnAudioStateChanged(false); + }); if (GetOuterWebContents()) GetOuterWebContents()->OnAudioStateChanged(); } - for (auto& observer : observers_) - observer.FrameDeleted(root->current_frame_host()); - - for (auto& observer : observers_) - observer.RenderViewDeleted(root->current_host()); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->FrameDeleted(root->current_frame_host()); + }); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->RenderViewDeleted(root->current_host()); + }); #if defined(OS_ANDROID) // For simplicity, destroy the Java WebContents before we notify of the // destruction of the WebContents. ClearWebContentsAndroid(); #endif - for (auto& observer : observers_) - observer.WebContentsDestroyed(); - + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->WebContentsDestroyed(); }); if (display_cutout_host_impl_) display_cutout_host_impl_->WebContentsDestroyed(); - for (auto& observer : observers_) - observer.ResetWebContents(); - + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->ResetWebContents(); }); SetDelegate(nullptr); } @@ -1040,7 +1051,7 @@ bool WebContentsImpl::OnMessageReceived(RenderViewHostImpl* render_view_host, const IPC::Message& message) { - for (auto& observer : observers_) { + for (auto& observer : observers_.observer_list()) { // TODO(nick, creis): https://crbug.com/758026: Replace all uses of this // variant of OnMessageReceived with the version that takes a // RenderFrameHost, and then delete it. @@ -1063,7 +1074,7 @@ bool WebContentsImpl::OnMessageReceived(RenderFrameHostImpl* render_frame_host, const IPC::Message& message) { - for (auto& observer : observers_) { + for (auto& observer : observers_.observer_list()) { if (observer.OnMessageReceived(message, render_frame_host)) return true; } @@ -1349,8 +1360,9 @@ void WebContentsImpl::NotifyViewportFitChanged( blink::mojom::ViewportFit value) { - for (auto& observer : observers_) - observer.ViewportFitChanged(value); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->ViewportFitChanged(value); + }); } FindRequestManager* WebContentsImpl::GetFindRequestManagerForTesting() { @@ -1419,8 +1431,9 @@ void WebContentsImpl::NotifyManifestUrlChanged( RenderFrameHost* rfh, const base::Optional<GURL>& manifest_url) { - for (auto& observer : observers_) - observer.DidUpdateWebManifestURL(rfh, manifest_url); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidUpdateWebManifestURL(rfh, manifest_url); + }); } WebUI* WebContentsImpl::GetWebUI() { @@ -1466,8 +1479,9 @@ controller_.Reload(ReloadType::BYPASSING_CACHE, true); } - for (auto& observer : observers_) - observer.UserAgentOverrideSet(ua_override); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->UserAgentOverrideSet(ua_override); + }); } void WebContentsImpl::SetRendererInitiatedUserAgentOverrideOption( @@ -1689,9 +1703,9 @@ GetAudioStreamFactory()->SetMuted(mute); - for (auto& observer : observers_) - observer.DidUpdateAudioMutingState(mute); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidUpdateAudioMutingState(mute); + }); // Notification for UI updates in response to the changed muting state. NotifyNavigationStateChanged(INVALIDATE_TYPE_AUDIO); } @@ -1731,8 +1745,9 @@ return; has_picture_in_picture_video_ = has_picture_in_picture_video; NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB); - for (auto& observer : observers_) - observer.MediaPictureInPictureChanged(has_picture_in_picture_video_); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->MediaPictureInPictureChanged(has_picture_in_picture_video_); + }); } bool WebContentsImpl::IsCrashed() { @@ -1808,8 +1823,9 @@ void WebContentsImpl::OnVerticalScrollDirectionChanged( viz::VerticalScrollDirection scroll_direction) { - for (auto& observer : observers_) - observer.DidChangeVerticalScrollDirection(scroll_direction); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidChangeVerticalScrollDirection(scroll_direction); + }); } void WebContentsImpl::OnAudioStateChanged() { @@ -1848,8 +1864,9 @@ if (GetOuterWebContents()) GetOuterWebContents()->OnAudioStateChanged(); - for (auto& observer : observers_) - observer.OnAudioStateChanged(is_currently_audible_); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnAudioStateChanged(is_currently_audible_); + }); } base::TimeTicks WebContentsImpl::GetLastActiveTime() { @@ -2032,10 +2049,10 @@ inner_web_contents_impl->SetAsFocusedWebContentsIfNecessary(); } - for (auto& observer : observers_) { - observer.InnerWebContentsAttached(inner_web_contents_impl, - render_frame_host, is_full_page); - } + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->InnerWebContentsAttached(inner_web_contents_impl, + render_frame_host, is_full_page); + }); } std::unique_ptr<WebContents> WebContentsImpl::DetachFromOuterWebContents() { @@ -2087,8 +2104,10 @@ GetMainFrame()->UpdateAXTreeData(); // Invoke on the *outer* web contents observers for symmetry. - for (auto& observer : outer_web_contents->observers_) - observer.InnerWebContentsDetached(this); + outer_web_contents->observers_.ForEachObserver( + [&](WebContentsObserver* observer) { + observer->InnerWebContentsDetached(this); + }); return web_contents; } @@ -2132,9 +2151,9 @@ base::TimeTicks activation_time) { DCHECK(predecessor_web_contents); NotifyInsidePortal(false); - for (auto& observer : observers_) - observer.DidActivatePortal(predecessor_web_contents, activation_time); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidActivatePortal(predecessor_web_contents, activation_time); + }); GetDelegate()->WebContentsBecamePortal(predecessor_web_contents); } @@ -2150,8 +2169,9 @@ void WebContentsImpl::DidChangeVisibleSecurityState() { if (delegate_) delegate_->VisibleSecurityStateChanged(this); - for (auto& observer : observers_) - observer.DidChangeVisibleSecurityState(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidChangeVisibleSecurityState(); + }); } const WebPreferences WebContentsImpl::ComputeWebPreferences() { @@ -2407,23 +2427,23 @@ void WebContentsImpl::OnCookiesAccessed(NavigationHandle* navigation, const CookieAccessDetails& details) { - for (auto& observer : observers_) { - observer.OnCookiesAccessed(navigation, details); - } + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnCookiesAccessed(navigation, details); + }); } void WebContentsImpl::OnCookiesAccessed(RenderFrameHostImpl* rfh, const CookieAccessDetails& details) { - for (auto& observer : observers_) { - observer.OnCookiesAccessed(rfh, details); - } + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnCookiesAccessed(rfh, details); + }); } void WebContentsImpl::Stop() { for (FrameTreeNode* node : frame_tree_.Nodes()) node->StopLoading(); - for (auto& observer : observers_) - observer.NavigationStopped(); + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->NavigationStopped(); }); } void WebContentsImpl::SetPageFrozen(bool frozen) { @@ -2447,8 +2467,9 @@ std::unique_ptr<WebContentsImpl> tc = CreateWithOpener(create_params, opener_rfh); tc->GetController().CopyStateFrom(&controller_, true); - for (auto& observer : observers_) - observer.DidCloneToNewWebContents(this, tc.get()); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidCloneToNewWebContents(this, tc.get()); + }); return tc; } @@ -2709,8 +2730,9 @@ fullscreen_widget_process_id_) { if (delegate_ && delegate_->EmbedsFullscreenWidget()) delegate_->ExitFullscreenModeForTab(this); - for (auto& observer : observers_) - observer.DidDestroyFullscreenWidget(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidDestroyFullscreenWidget(); + }); fullscreen_widget_process_id_ = ChildProcessHost::kInvalidUniqueID; fullscreen_widget_routing_id_ = MSG_ROUTING_NONE; if (fullscreen_widget_had_focus_at_shutdown_) @@ -2748,8 +2770,9 @@ if (!rfh || render_widget_host != rfh->GetRenderWidgetHost()) return; - for (auto& observer : observers_) - observer.MainFrameWasResized(width_changed); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->MainFrameWasResized(width_changed); + }); } KeyboardEventProcessingResult WebContentsImpl::PreHandleKeyboardEvent( @@ -2910,9 +2933,9 @@ delegate_->RequestKeyboardLock(this, esc_key_locked_); } - for (auto& observer : observers_) - observer.DidToggleFullscreenModeForTab(IsFullscreen(), false); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidToggleFullscreenModeForTab(IsFullscreen(), false); + }); FullscreenContentsSet(GetBrowserContext())->insert(this); } @@ -2949,9 +2972,9 @@ current_fullscreen_frame_ = nullptr; - for (auto& observer : observers_) { - observer.DidToggleFullscreenModeForTab(IsFullscreen(), will_cause_resize); - } + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidToggleFullscreenModeForTab(IsFullscreen(), will_cause_resize); + }); if (display_cutout_host_impl_) display_cutout_host_impl_->DidExitFullscreen(); @@ -3000,9 +3023,9 @@ return; current_fullscreen_frame_ = new_fullscreen_frame; - for (auto& observer : observers_) - observer.DidAcquireFullscreen(new_fullscreen_frame); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidAcquireFullscreen(new_fullscreen_frame); + }); if (display_cutout_host_impl_) display_cutout_host_impl_->DidAcquireFullscreen(new_fullscreen_frame); } @@ -3374,13 +3397,13 @@ params.target_url, new_contents_impl); } - for (auto& observer : observers_) { - observer.DidOpenRequestedURL(new_contents_impl, opener, params.target_url, - params.referrer.To<Referrer>(), - params.disposition, ui::PAGE_TRANSITION_LINK, - false, // started_from_context_menu - true); // renderer_initiated - } + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidOpenRequestedURL(new_contents_impl, opener, params.target_url, + params.referrer.To<Referrer>(), + params.disposition, ui::PAGE_TRANSITION_LINK, + false, // started_from_context_menu + true); // renderer_initiated + }); // Any new WebContents opened while this WebContents is in fullscreen can be // used to confuse the user, so drop fullscreen. @@ -3601,8 +3624,9 @@ } else { widget_host_view->InitAsFullscreen(view); } - for (auto& observer : observers_) - observer.DidShowFullscreenWidget(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidShowFullscreenWidget(); + }); if (!widget_host_view->HasFocus()) widget_host_view->Focus(); } else { @@ -3748,20 +3772,23 @@ if (rwhv) rwhv->SetMainFrameAXTreeID(GetMainFrame()->GetAXTreeID()); - for (auto& observer : observers_) - observer.AXTreeIDForMainFrameHasChanged(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->AXTreeIDForMainFrameHasChanged(); + }); } void WebContentsImpl::AccessibilityEventReceived( const AXEventNotificationDetails& details) { - for (auto& observer : observers_) - observer.AccessibilityEventReceived(details); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->AccessibilityEventReceived(details); + }); } void WebContentsImpl::AccessibilityLocationChangesReceived( const std::vector<AXLocationChangeNotificationDetails>& details) { - for (auto& observer : observers_) - observer.AccessibilityLocationChangesReceived(details); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->AccessibilityLocationChangesReceived(details); + }); } base::string16 WebContentsImpl::DumpAccessibilityTree( @@ -3848,8 +3875,8 @@ waiting_for_response_ = false; if (delegate_) delegate_->LoadingStateChanged(this, is_load_to_different_document_); - for (auto& observer : observers_) - observer.DidReceiveResponse(); + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->DidReceiveResponse(); }); } void WebContentsImpl::SendScreenRects() { @@ -3990,12 +4017,12 @@ } if (new_contents && source_render_frame_host && new_contents != this) { - for (auto& observer : observers_) { - observer.DidOpenRequestedURL( + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidOpenRequestedURL( new_contents, source_render_frame_host, params.url, params.referrer, params.disposition, params.transition, params.started_from_context_menu, params.is_renderer_initiated); - } + }); } return new_contents; @@ -4077,8 +4104,8 @@ return; input_handler->Paste(); - for (auto& observer : observers_) - observer.OnPaste(); + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->OnPaste(); }); RecordAction(base::UserMetricsAction("Paste")); } @@ -4088,8 +4115,8 @@ return; input_handler->PasteAndMatchStyle(); - for (auto& observer : observers_) - observer.OnPaste(); + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->OnPaste(); }); RecordAction(base::UserMetricsAction("PasteAndMatchStyle")); } @@ -4418,21 +4445,24 @@ // for the first time. if (visibility != previous_visibility || (visibility == Visibility::VISIBLE && !did_first_set_visible_)) { - for (auto& observer : observers_) - observer.OnVisibilityChanged(visibility); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnVisibilityChanged(visibility); + }); } } void WebContentsImpl::NotifyWebContentsFocused( RenderWidgetHost* render_widget_host) { - for (auto& observer : observers_) - observer.OnWebContentsFocused(render_widget_host); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnWebContentsFocused(render_widget_host); + }); } void WebContentsImpl::NotifyWebContentsLostFocus( RenderWidgetHost* render_widget_host) { - for (auto& observer : observers_) - observer.OnWebContentsLostFocus(render_widget_host); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnWebContentsLostFocus(render_widget_host); + }); } void WebContentsImpl::SystemDragEnded(RenderWidgetHost* source_rwh) { @@ -4723,9 +4753,9 @@ if (navigation_handle->IsInMainFrame()) favicon_urls_.clear(); - for (auto& observer : observers_) - observer.DidStartNavigation(navigation_handle); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidStartNavigation(navigation_handle); + }); if (navigation_handle->IsInMainFrame()) { // When the browser is started with about:blank as the startup URL, focus // the location bar (which will also select its contents) so people can @@ -4749,9 +4779,9 @@ NavigationHandle* navigation_handle) { TRACE_EVENT1("navigation", "WebContentsImpl::DidRedirectNavigation", "navigation_handle", navigation_handle); - for (auto& observer : observers_) - observer.DidRedirectNavigation(navigation_handle); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidRedirectNavigation(navigation_handle); + }); // Notify accessibility if this is a reload. This has to called on the // BrowserAccessibilityManager associated with the old RFHI. if (navigation_handle->GetReloadType() != ReloadType::NONE) { @@ -4769,9 +4799,9 @@ NavigationHandle* navigation_handle) { TRACE_EVENT1("navigation", "WebContentsImpl::ReadyToCommitNavigation", "navigation_handle", navigation_handle); - for (auto& observer : observers_) - observer.ReadyToCommitNavigation(navigation_handle); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->ReadyToCommitNavigation(navigation_handle); + }); // If any domains are blocked from accessing 3D APIs because they may // have caused the GPU to reset recently, unblock them here if the user // initiated this navigation. This implies that the user was involved in @@ -4820,9 +4850,9 @@ TRACE_EVENT1("navigation", "WebContentsImpl::DidFinishNavigation", "navigation_handle", navigation_handle); - for (auto& observer : observers_) - observer.DidFinishNavigation(navigation_handle); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidFinishNavigation(navigation_handle); + }); if (display_cutout_host_impl_) display_cutout_host_impl_->DidFinishNavigation(navigation_handle); @@ -4905,9 +4935,9 @@ RenderFrameHostImpl* render_frame_host, const GURL& url, int error_code) { - for (auto& observer : observers_) { - observer.DidFailLoad(render_frame_host, url, error_code); - } + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidFailLoad(render_frame_host, url, error_code); + }); } void WebContentsImpl::NotifyChangedNavigationState( @@ -5014,9 +5044,9 @@ void WebContentsImpl::OnThemeColorChanged(RenderViewHostImpl* source) { if (source->did_first_visually_non_empty_paint() && last_sent_theme_color_ != source->theme_color()) { - for (auto& observer : observers_) - observer.DidChangeThemeColor(); - last_sent_theme_color_ = source->theme_color(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidChangeThemeColor(); + }); } } @@ -5026,9 +5056,10 @@ const std::string& http_method, const std::string& mime_type, network::mojom::RequestDestination request_destination) { - for (auto& observer : observers_) - observer.DidLoadResourceFromMemoryCache(url, mime_type, - request_destination); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidLoadResourceFromMemoryCache(url, mime_type, + request_destination); + }); if (url.is_valid() && url.SchemeIsHTTPOrHTTPS()) { StoragePartition* partition = source->GetProcess()->GetStoragePartition(); @@ -5046,8 +5077,9 @@ } void WebContentsImpl::DocumentAvailableInMainFrame() { - for (auto& observer : observers_) - observer.DocumentAvailableInMainFrame(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DocumentAvailableInMainFrame(); + }); } void WebContentsImpl::OnDidRunInsecureContent(RenderFrameHostImpl* source, @@ -5179,10 +5211,10 @@ RenderFrameHost* render_frame_host, const GlobalRequestID& request_id, blink::mojom::ResourceLoadInfoPtr resource_load_info) { - for (auto& observer : observers_) { - observer.ResourceLoadComplete(render_frame_host, request_id, - *resource_load_info); - } + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->ResourceLoadComplete(render_frame_host, request_id, + *resource_load_info); + }); } const WebPreferences& WebContentsImpl::GetOrCreateWebPreferences() { @@ -5281,8 +5313,9 @@ } void WebContentsImpl::DOMContentLoaded(RenderFrameHost* render_frame_host) { - for (auto& observer : observers_) - observer.DOMContentLoaded(render_frame_host); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DOMContentLoaded(render_frame_host); + }); } void WebContentsImpl::OnDidFinishLoad(RenderFrameHost* render_frame_host, @@ -5290,9 +5323,9 @@ GURL validated_url(url); render_frame_host->GetProcess()->FilterURL(false, &validated_url); - for (auto& observer : observers_) - observer.DidFinishLoad(render_frame_host, validated_url); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidFinishLoad(render_frame_host, validated_url); + }); size_t tree_size = frame_tree_.root()->GetFrameTreeSize(); if (max_loaded_frame_count_ < tree_size) max_loaded_frame_count_ = tree_size; @@ -5348,8 +5381,9 @@ } #endif // !defined(OS_ANDROID) - for (auto& observer : observers_) - observer.OnPageScaleFactorChanged(page_scale_factor); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnPageScaleFactorChanged(page_scale_factor); + }); } void WebContentsImpl::OnTextAutosizerPageInfoChanged( @@ -5434,8 +5468,9 @@ // |manifest_url|? // Notify observers about navigation. - for (auto& observer : observers_) - observer.AppCacheAccessed(manifest_url, blocked_by_policy); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->AppCacheAccessed(manifest_url, blocked_by_policy); + }); } void WebContentsImpl::DomOperationResponse(const std::string& json_string) { @@ -5466,18 +5501,18 @@ RenderFrameHost* render_frame_host, const GURL& scope, AllowServiceWorkerResult allowed) { - for (auto& observer : observers_) { - observer.OnServiceWorkerAccessed(render_frame_host, scope, allowed); - } + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnServiceWorkerAccessed(render_frame_host, scope, allowed); + }); } void WebContentsImpl::OnServiceWorkerAccessed( NavigationHandle* navigation, const GURL& scope, AllowServiceWorkerResult allowed) { - for (auto& observer : observers_) { - observer.OnServiceWorkerAccessed(navigation, scope, allowed); - } + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnServiceWorkerAccessed(navigation, scope, allowed); + }); } void WebContentsImpl::OnColorChooserFactoryReceiver( @@ -5504,15 +5539,17 @@ #if BUILDFLAG(ENABLE_PLUGINS) void WebContentsImpl::OnPepperInstanceCreated(RenderFrameHostImpl* source, int32_t pp_instance) { - for (auto& observer : observers_) - observer.PepperInstanceCreated(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->PepperInstanceCreated(); + }); pepper_playback_observer_->PepperInstanceCreated(source, pp_instance); } void WebContentsImpl::OnPepperInstanceDeleted(RenderFrameHostImpl* source, int32_t pp_instance) { - for (auto& observer : observers_) - observer.PepperInstanceDeleted(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->PepperInstanceDeleted(); + }); pepper_playback_observer_->PepperInstanceDeleted(source, pp_instance); } @@ -5522,8 +5559,9 @@ bool is_hung) { UMA_HISTOGRAM_COUNTS_1M("Pepper.PluginHung", 1); - for (auto& observer : observers_) - observer.PluginHungStatusChanged(plugin_child_id, path, is_hung); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->PluginHungStatusChanged(plugin_child_id, path, is_hung); + }); } void WebContentsImpl::OnPepperStartsPlayback(RenderFrameHostImpl* source, @@ -5541,8 +5579,9 @@ base::ProcessId plugin_pid) { // TODO(nick): Eliminate the |plugin_pid| parameter, which can't be trusted, // and is only used by WebTestControlHost. - for (auto& observer : observers_) - observer.PluginCrashed(plugin_path, plugin_pid); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->PluginCrashed(plugin_path, plugin_pid); + }); } void WebContentsImpl::OnRequestPpapiBrokerPermission( @@ -5593,8 +5632,9 @@ favicon_urls_ = std::move(candidates); - for (auto& observer : observers_) - observer.DidUpdateFaviconURL(source, favicon_urls_); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidUpdateFaviconURL(source, favicon_urls_); + }); } void WebContentsImpl::SetIsOverlayContent(bool is_overlay_content) { @@ -5605,13 +5645,14 @@ RenderViewHostImpl* source) { // TODO(nick): When this is ported to FrameHostMsg_, we should only listen if // |source| is the main frame. - for (auto& observer : observers_) - observer.DidFirstVisuallyNonEmptyPaint(); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidFirstVisuallyNonEmptyPaint(); + }); if (source->theme_color() != last_sent_theme_color_) { // Theme color should have updated by now if there was one. - for (auto& observer : observers_) - observer.DidChangeThemeColor(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidChangeThemeColor(); + }); last_sent_theme_color_ = source->theme_color(); } } @@ -5625,8 +5666,9 @@ } void WebContentsImpl::NotifyBeforeFormRepostWarningShow() { - for (auto& observer : observers_) - observer.BeforeFormRepostWarningShow(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->BeforeFormRepostWarningShow(); + }); } void WebContentsImpl::ActivateAndShowRepostFormWarningDialog() { @@ -5665,9 +5707,8 @@ // Lastly, set the title for the view. view_->SetPageTitle(final_title); - for (auto& observer : observers_) - observer.TitleWasSet(entry); - + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->TitleWasSet(entry); }); // Broadcast notifications when the UI should be updated. if (entry == controller_.GetEntryAtOffset(0)) NotifyNavigationStateChanged(INVALIDATE_TYPE_TITLE); @@ -5675,8 +5716,9 @@ void WebContentsImpl::SendChangeLoadProgress() { loading_last_progress_update_ = base::TimeTicks::Now(); - for (auto& observer : observers_) - observer.LoadProgressChanged(frame_tree_.load_progress()); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->LoadProgressChanged(frame_tree_.load_progress()); + }); } void WebContentsImpl::ResetLoadProgressState() { @@ -5716,13 +5758,13 @@ TRACE_EVENT_ASYNC_BEGIN2("browser,navigation", "WebContentsImpl Loading", this, "URL", url, "Main FrameTreeNode id", GetFrameTree()->root()->frame_tree_node_id()); - for (auto& observer : observers_) - observer.DidStartLoading(); + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->DidStartLoading(); }); } else { TRACE_EVENT_ASYNC_END1("browser,navigation", "WebContentsImpl Loading", this, "URL", url); - for (auto& observer : observers_) - observer.DidStopLoading(); + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->DidStopLoading(); }); } // TODO(avi): Remove. http://crbug.com/170921 @@ -5741,9 +5783,9 @@ // notification so that clients that pick up a pointer to |this| can NULL the // pointer. See Bug 1230284. notify_disconnection_ = true; - for (auto& observer : observers_) - observer.RenderViewHostChanged(old_view, new_view); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->RenderViewHostChanged(old_view, new_view); + }); view_->RenderViewHostChanged(old_view, new_view); // If this is an inner WebContents that has swapped views, we need to reattach @@ -5770,8 +5812,9 @@ new_widget->SetImportance(old_widget->importance()); } #endif - for (auto& observer : observers_) - observer.RenderFrameHostChanged(old_frame, new_frame); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->RenderFrameHostChanged(old_frame, new_frame); + }); } // TODO(avi): Remove this entire function because this notification is already @@ -5789,25 +5832,29 @@ void WebContentsImpl::NotifyNavigationEntryCommitted( const LoadCommittedDetails& load_details) { - for (auto& observer : observers_) - observer.NavigationEntryCommitted(load_details); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->NavigationEntryCommitted(load_details); + }); } void WebContentsImpl::NotifyNavigationEntryChanged( const EntryChangedDetails& change_details) { - for (auto& observer : observers_) - observer.NavigationEntryChanged(change_details); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->NavigationEntryChanged(change_details); + }); } void WebContentsImpl::NotifyNavigationListPruned( const PrunedDetails& pruned_details) { - for (auto& observer : observers_) - observer.NavigationListPruned(pruned_details); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->NavigationListPruned(pruned_details); + }); } void WebContentsImpl::NotifyNavigationEntriesDeleted() { - for (auto& observer : observers_) - observer.NavigationEntriesDeleted(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->NavigationEntriesDeleted(); + }); } void WebContentsImpl::OnAssociatedInterfaceRequest( @@ -5823,7 +5870,7 @@ RenderFrameHost* render_frame_host, const std::string& interface_name, mojo::ScopedMessagePipeHandle* interface_pipe) { - for (auto& observer : observers_) { + for (auto& observer : observers_.observer_list()) { observer.OnInterfaceRequestFromFrame(render_frame_host, interface_name, interface_pipe); if (!interface_pipe->is_valid()) @@ -5844,8 +5891,9 @@ } void WebContentsImpl::RenderFrameCreated(RenderFrameHost* render_frame_host) { - for (auto& observer : observers_) - observer.RenderFrameCreated(render_frame_host); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->RenderFrameCreated(render_frame_host); + }); UpdateAccessibilityModeOnFrame(render_frame_host); if (display_cutout_host_impl_) @@ -5877,10 +5925,9 @@ RecordMaxFrameCountUMA(max_loaded_frame_count_); } - is_notifying_observers_ = true; - for (auto& observer : observers_) - observer.RenderFrameDeleted(render_frame_host); - is_notifying_observers_ = false; + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->RenderFrameDeleted(render_frame_host); + }); #if BUILDFLAG(ENABLE_PLUGINS) pepper_playback_observer_->RenderFrameDeleted(render_frame_host); #endif @@ -6259,8 +6306,9 @@ } void WebContentsImpl::InnerWebContentsCreated(WebContents* inner_web_contents) { - for (auto& observer : observers_) - observer.InnerWebContentsCreated(inner_web_contents); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->InnerWebContentsCreated(inner_web_contents); + }); } void WebContentsImpl::InnerWebContentsAttached( @@ -6284,8 +6332,9 @@ Source<WebContents>(this), Details<RenderViewHost>(render_view_host)); - for (auto& observer : observers_) - observer.RenderViewCreated(render_view_host); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->RenderViewCreated(render_view_host); + }); if (delegate_) RenderFrameDevToolsAgentHost::WebContentsCreated(this); } @@ -6314,9 +6363,8 @@ view_->Focus(); } - for (auto& observer : observers_) - observer.RenderViewReady(); - + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->RenderViewReady(); }); view_->RenderViewReady(); } @@ -6351,13 +6399,22 @@ NotifyDisconnected(); SetIsCrashed(status, error_code); - for (auto& observer : observers_) - observer.RenderProcessGone(GetCrashedStatus()); + TRACE_EVENT0("content", "Dispatching WebContentsObserver::RenderProcessGone"); + // Some observers might destroy WebContents in RenderViewTerminated. + base::WeakPtr<WebContentsImpl> weak_ptr = weak_factory_.GetWeakPtr(); + auto crashed_status = GetCrashedStatus(); + for (auto& observer : observers_.observer_list()) { + observer.RenderProcessGone(crashed_status); + if (!weak_ptr) + return; + } + + // |this| might have been deleted. Do not add code here. } void WebContentsImpl::RenderViewDeleted(RenderViewHost* rvh) { - for (auto& observer : observers_) - observer.RenderViewDeleted(rvh); + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->RenderViewDeleted(rvh); }); } void WebContentsImpl::UpdateTargetURL(RenderViewHost* render_view_host, @@ -6549,26 +6606,30 @@ void WebContentsImpl::DidChangeName(RenderFrameHost* render_frame_host, const std::string& name) { - for (auto& observer : observers_) - observer.FrameNameChanged(render_frame_host, name); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->FrameNameChanged(render_frame_host, name); + }); } void WebContentsImpl::DidReceiveFirstUserActivation( RenderFrameHost* render_frame_host) { - for (auto& observer : observers_) - observer.FrameReceivedFirstUserActivation(render_frame_host); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->FrameReceivedFirstUserActivation(render_frame_host); + }); } void WebContentsImpl::DidChangeDisplayState(RenderFrameHost* render_frame_host, bool is_display_none) { - for (auto& observer : observers_) - observer.FrameDisplayStateChanged(render_frame_host, is_display_none); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->FrameDisplayStateChanged(render_frame_host, is_display_none); + }); } void WebContentsImpl::FrameSizeChanged(RenderFrameHost* render_frame_host, const gfx::Size& frame_size) { - for (auto& observer : observers_) - observer.FrameSizeChanged(render_frame_host, frame_size); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->FrameSizeChanged(render_frame_host, frame_size); + }); } void WebContentsImpl::DocumentOnLoadCompleted( @@ -6577,10 +6638,9 @@ GetRenderViewHost()->DocumentOnLoadCompletedInMainFrame(); - is_notifying_observers_ = true; - for (auto& observer : observers_) - observer.DocumentOnLoadCompletedInMainFrame(); - is_notifying_observers_ = false; + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DocumentOnLoadCompletedInMainFrame(); + }); // TODO(avi): Remove. http://crbug.com/170921 NotificationService::current()->Notify( @@ -6819,8 +6879,9 @@ Source<RenderViewHost>(GetRenderViewHost()), Details<FocusedNodeDetails>(&details)); - for (auto& observer : observers_) - observer.OnFocusChangedInPage(&details); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnFocusChangedInPage(&details); + }); } bool WebContentsImpl::DidAddMessageToConsole( @@ -6828,9 +6889,9 @@ const base::string16& message, int32_t line_no, const base::string16& source_id) { - for (auto& observer : observers_) - observer.OnDidAddMessageToConsole(log_level, message, line_no, source_id); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnDidAddMessageToConsole(log_level, message, line_no, source_id); + }); if (!delegate_) return false; return delegate_->DidAddMessageToConsole(this, log_level, message, line_no, @@ -6850,8 +6911,9 @@ if (event.GetType() != blink::WebInputEvent::Type::kGestureScrollBegin) last_interactive_input_event_time_ = ui::EventTimeForNow(); - for (auto& observer : observers_) - observer.DidGetUserInteraction(event); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->DidGetUserInteraction(event); + }); } bool WebContentsImpl::ShouldIgnoreInputEvents() { @@ -6881,8 +6943,8 @@ void WebContentsImpl::OnIgnoredUIEvent() { // Notify observers. - for (auto& observer : observers_) - observer.DidGetIgnoredUIEvent(); + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->DidGetIgnoredUIEvent(); }); } void WebContentsImpl::RendererUnresponsive( @@ -6901,9 +6963,9 @@ if (!render_widget_host->renderer_initialized()) return; - for (auto& observer : observers_) - observer.OnRendererUnresponsive(render_widget_host->GetProcess()); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnRendererUnresponsive(render_widget_host->GetProcess()); + }); if (delegate_) delegate_->RendererUnresponsive(this, render_widget_host, std::move(hang_monitor_restarter)); @@ -6911,9 +6973,9 @@ void WebContentsImpl::RendererResponsive( RenderWidgetHostImpl* render_widget_host) { - for (auto& observer : observers_) - observer.OnRendererResponsive(render_widget_host->GetProcess()); - + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnRendererResponsive(render_widget_host->GetProcess()); + }); if (delegate_) delegate_->RendererResponsive(this, render_widget_host); } @@ -6944,8 +7006,9 @@ void WebContentsImpl::BeforeUnloadFiredFromRenderManager( bool proceed, const base::TimeTicks& proceed_time, bool* proceed_to_fire_unload) { - for (auto& observer : observers_) - observer.BeforeUnloadFired(proceed, proceed_time); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->BeforeUnloadFired(proceed, proceed_time); + }); if (delegate_) delegate_->BeforeUnloadFired(this, proceed, proceed_to_fire_unload); // Note: |this| might be deleted at this point. @@ -7186,8 +7249,9 @@ // Update the URL display either way, to avoid showing a stale URL. NotifyNavigationStateChanged(INVALIDATE_TYPE_URL); - for (auto& observer : observers_) - observer.BeforeUnloadDialogCancelled(); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->BeforeUnloadDialogCancelled(); + }); } std::move(response_callback).Run(success, user_input); @@ -7291,8 +7355,9 @@ } void WebContentsImpl::OnFrameRemoved(RenderFrameHost* render_frame_host) { - for (auto& observer : observers_) - observer.FrameDeleted(render_frame_host); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->FrameDeleted(render_frame_host); + }); } void WebContentsImpl::OnPreferredSizeChanged(const gfx::Size& old_size) { @@ -7396,10 +7461,10 @@ void WebContentsImpl::OnIsConnectedToBluetoothDeviceChanged( bool is_connected_to_bluetooth_device) { NotifyNavigationStateChanged(INVALIDATE_TYPE_TAB); - for (auto& observer : observers_) { - observer.OnIsConnectedToBluetoothDeviceChanged( + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnIsConnectedToBluetoothDeviceChanged( is_connected_to_bluetooth_device); - } + }); } void WebContentsImpl::IncrementBluetoothScanningSessionsCount() { @@ -7613,8 +7678,9 @@ if (media_info.has_video) currently_playing_video_count_++; - for (auto& observer : observers_) - observer.MediaStartedPlaying(media_info, id); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->MediaStartedPlaying(media_info, id); + }); } void WebContentsImpl::MediaStoppedPlaying( @@ -7624,26 +7690,29 @@ if (media_info.has_video) currently_playing_video_count_--; - for (auto& observer : observers_) - observer.MediaStoppedPlaying(media_info, id, reason); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->MediaStoppedPlaying(media_info, id, reason); + }); } void WebContentsImpl::MediaResized(const gfx::Size& size, const MediaPlayerId& id) { cached_video_sizes_[id] = size; - for (auto& observer : observers_) - observer.MediaResized(size, id); + observers_.ForEachObserver( + [&](WebContentsObserver* observer) { observer->MediaResized(size, id); }); } void WebContentsImpl::MediaBufferUnderflow(const MediaPlayerId& id) { - for (auto& observer : observers_) - observer.MediaBufferUnderflow(id); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->MediaBufferUnderflow(id); + }); } void WebContentsImpl::MediaEffectivelyFullscreenChanged(bool is_fullscreen) { - for (auto& observer : observers_) - observer.MediaEffectivelyFullscreenChanged(is_fullscreen); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->MediaEffectivelyFullscreenChanged(is_fullscreen); + }); } base::Optional<gfx::Size> WebContentsImpl::GetFullscreenVideoSize() { @@ -7661,21 +7730,24 @@ void WebContentsImpl::AudioContextPlaybackStarted(RenderFrameHost* host, int context_id) { WebContentsObserver::AudioContextId audio_context_id(host, context_id); - for (auto& observer : observers_) - observer.AudioContextPlaybackStarted(audio_context_id); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->AudioContextPlaybackStarted(audio_context_id); + }); } void WebContentsImpl::AudioContextPlaybackStopped(RenderFrameHost* host, int context_id) { WebContentsObserver::AudioContextId audio_context_id(host, context_id); - for (auto& observer : observers_) - observer.AudioContextPlaybackStopped(audio_context_id); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->AudioContextPlaybackStopped(audio_context_id); + }); } void WebContentsImpl::OnFrameAudioStateChanged(RenderFrameHost* host, bool is_audible) { - for (auto& observer : observers_) - observer.OnFrameAudioStateChanged(host, is_audible); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->OnFrameAudioStateChanged(host, is_audible); + }); } media::MediaMetricsProvider::RecordAggregateWatchTimeCallback @@ -7755,7 +7827,7 @@ std::vector<blink::mojom::MenuItemPtr>* menu_items, bool right_aligned, bool allow_multiple_selection) { - for (auto& observer : observers_) { + for (auto& observer : observers_.observer_list()) { if (observer.ShowPopupMenu(render_frame_host, popup_client, bounds, item_height, font_size, selected_item, menu_items, right_aligned, @@ -7886,8 +7958,9 @@ void WebContentsImpl::MediaMutedStatusChanged(const MediaPlayerId& id, bool muted) { - for (auto& observer : observers_) - observer.MediaMutedStatusChanged(id, muted); + observers_.ForEachObserver([&](WebContentsObserver* observer) { + observer->MediaMutedStatusChanged(id, muted); + }); } void WebContentsImpl::SetVisibilityForChildViews(bool visible) {
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 7562784..f219f9a 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -1395,6 +1395,40 @@ WebContentsImpl* focused_web_contents_; }; + // Container for WebContentsObservers, which knows when we are iterating over + // observer set. + class WebContentsObserverList { + public: + WebContentsObserverList(); + ~WebContentsObserverList(); + + void AddObserver(WebContentsObserver* observer); + void RemoveObserver(WebContentsObserver* observer); + + template <class ForEachCallable> + void ForEachObserver(const ForEachCallable& callable) { + TRACE_EVENT0("content", "Iterating over WebContentsObservers"); + base::AutoReset<bool> scope(&is_notifying_observers_, true); + for (WebContentsObserver& observer : observers_) { + TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("content.verbose"), + "Dispatching WebContentsObserver callback"); + callable(&observer); + } + } + + bool is_notifying_observers() { return is_notifying_observers_; } + + // Exposed to deal with IPC message handlers which need to stop iteration + // early. + const base::ObserverList<WebContentsObserver>::Unchecked& observer_list() { + return observers_; + } + + private: + bool is_notifying_observers_ = false; + base::ObserverList<WebContentsObserver>::Unchecked observers_; + }; + // See WebContents::Create for a description of these parameters. explicit WebContentsImpl(BrowserContext* browser_context); @@ -1719,7 +1753,7 @@ // This MUST be listed above frame_tree_ since at destruction time the // latter might cause RenderViewHost's destructor to call us and we might use // the observer list then. - base::ObserverList<WebContentsObserver>::Unchecked observers_; + WebContentsObserverList observers_; // Associated interface receiver sets attached to this WebContents. std::map<std::string, WebContentsReceiverSet*> receiver_sets_;
diff --git a/content/browser/worker_host/dedicated_worker_host.cc b/content/browser/worker_host/dedicated_worker_host.cc index 1b5d534..e6fb77c 100644 --- a/content/browser/worker_host/dedicated_worker_host.cc +++ b/content/browser/worker_host/dedicated_worker_host.cc
@@ -59,7 +59,6 @@ cross_origin_embedder_policy_(cross_origin_embedder_policy), coep_reporter_(std::move(coep_reporter)) { DCHECK_CURRENTLY_ON(BrowserThread::UI); - DCHECK(!token_.is_empty()); DCHECK(worker_process_host_); DCHECK(worker_process_host_->IsInitializedAndNotDead()); DCHECK(coep_reporter_); @@ -191,8 +190,8 @@ storage_partition_impl); WorkerScriptFetchInitiator::Start( - worker_process_host_->GetID(), token_, blink::SharedWorkerToken::Null(), - script_url, creator_render_frame_host, + worker_process_host_->GetID(), token_, script_url, + creator_render_frame_host, nearest_ancestor_render_frame_host->ComputeSiteForCookies(), creator_origin_, nearest_ancestor_render_frame_host->GetIsolationInfoForSubresources(),
diff --git a/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc index f96f57aa..225797e 100644 --- a/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc +++ b/content/browser/worker_host/dedicated_worker_service_impl_unittest.cc
@@ -48,14 +48,14 @@ if (base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker)) { factory_->CreateWorkerHostAndStartScriptLoad( - blink::DedicatedWorkerToken::Create(), + blink::DedicatedWorkerToken(), /*script_url=*/GURL(), network::mojom::CredentialsMode::kSameOrigin, blink::mojom::FetchClientSettingsObject::New(), mojo::PendingRemote<blink::mojom::BlobURLToken>(), receiver_.BindNewPipeAndPassRemote()); } else { factory_->CreateWorkerHost( - blink::DedicatedWorkerToken::Create(), + blink::DedicatedWorkerToken(), browser_interface_broker_.BindNewPipeAndPassReceiver(), base::BindOnce([](const network::CrossOriginEmbedderPolicy&) {})); }
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc index a4da8a45..2ff1240 100644 --- a/content/browser/worker_host/shared_worker_host.cc +++ b/content/browser/worker_host/shared_worker_host.cc
@@ -105,7 +105,7 @@ const SharedWorkerInstance& instance, RenderProcessHost* worker_process_host) : service_(service), - token_(blink::SharedWorkerToken::Create()), + token_(blink::SharedWorkerToken()), instance_(instance), worker_process_host_(worker_process_host), scoped_process_host_ref_(
diff --git a/content/browser/worker_host/shared_worker_service_impl.cc b/content/browser/worker_host/shared_worker_service_impl.cc index 795a4d4..5cc3fb6 100644 --- a/content/browser/worker_host/shared_worker_service_impl.cc +++ b/content/browser/worker_host/shared_worker_service_impl.cc
@@ -322,9 +322,8 @@ // data across NetworkIsolationKeys and allow same-site cookies to be sent in // cross-site contexts. Fix this. WorkerScriptFetchInitiator::Start( - worker_process_host->GetID(), blink::DedicatedWorkerToken::Null(), - host->token(), host->instance().url(), creator_render_frame_host, - net::SiteForCookies::FromOrigin(worker_origin), + worker_process_host->GetID(), host->token(), host->instance().url(), + creator_render_frame_host, net::SiteForCookies::FromOrigin(worker_origin), host->instance().constructor_origin(), net::IsolationInfo::Create( net::IsolationInfo::RedirectMode::kUpdateNothing, worker_origin,
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.cc b/content/browser/worker_host/worker_script_fetch_initiator.cc index 6f639056..9f3bbcf 100644 --- a/content/browser/worker_host/worker_script_fetch_initiator.cc +++ b/content/browser/worker_host/worker_script_fetch_initiator.cc
@@ -64,8 +64,7 @@ // static void WorkerScriptFetchInitiator::Start( int worker_process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, const GURL& initial_request_url, RenderFrameHost* creator_render_frame_host, const net::SiteForCookies& site_for_cookies, @@ -177,8 +176,8 @@ AddAdditionalRequestHeaders(resource_request.get(), browser_context); CreateScriptLoader( - worker_process_id, dedicated_worker_token, shared_worker_token, - initial_request_url, creator_render_frame_host, trusted_isolation_info, + worker_process_id, worker_token, initial_request_url, + creator_render_frame_host, trusted_isolation_info, std::move(resource_request), std::move(factory_bundle_for_browser), std::move(subresource_loader_factories), std::move(service_worker_context), service_worker_handle, @@ -281,8 +280,7 @@ void WorkerScriptFetchInitiator::CreateScriptLoader( int worker_process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, const GURL& initial_request_url, RenderFrameHost* creator_render_frame_host, const net::IsolationInfo& trusted_isolation_info, @@ -375,9 +373,9 @@ WorkerScriptFetcher::CreateAndStart( std::make_unique<WorkerScriptLoaderFactory>( - worker_process_id, dedicated_worker_token, shared_worker_token, - service_worker_handle, std::move(appcache_host), - browser_context_getter, std::move(url_loader_factory)), + worker_process_id, worker_token, service_worker_handle, + std::move(appcache_host), browser_context_getter, + std::move(url_loader_factory)), std::move(throttles), std::move(resource_request), base::BindOnce(WorkerScriptFetchInitiator::DidCreateScriptLoader, std::move(callback),
diff --git a/content/browser/worker_host/worker_script_fetch_initiator.h b/content/browser/worker_host/worker_script_fetch_initiator.h index 712f2ff..d7984c8 100644 --- a/content/browser/worker_host/worker_script_fetch_initiator.h +++ b/content/browser/worker_host/worker_script_fetch_initiator.h
@@ -14,6 +14,7 @@ #include "base/macros.h" #include "content/common/content_export.h" #include "content/public/browser/browser_thread.h" +#include "content/public/browser/service_worker_client_info.h" #include "services/network/public/mojom/fetch_api.mojom.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" #include "services/network/public/mojom/url_response_head.mojom.h" @@ -67,8 +68,7 @@ // thread. |callback| will be called with the result on the UI thread. static void Start( int worker_process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, const GURL& initial_request_url, RenderFrameHost* creator_render_frame_host, const net::SiteForCookies& site_for_cookies, @@ -112,8 +112,7 @@ static void CreateScriptLoader( int worker_process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, const GURL& initial_request_url, RenderFrameHost* creator_render_frame_host, const net::IsolationInfo& trusted_isolation_info,
diff --git a/content/browser/worker_host/worker_script_loader.cc b/content/browser/worker_host/worker_script_loader.cc index 795615b..d1d1faae 100644 --- a/content/browser/worker_host/worker_script_loader.cc +++ b/content/browser/worker_host/worker_script_loader.cc
@@ -21,8 +21,7 @@ WorkerScriptLoader::WorkerScriptLoader( int process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, int32_t routing_id, int32_t request_id, uint32_t options, @@ -51,8 +50,7 @@ } auto service_worker_interceptor = ServiceWorkerMainResourceLoaderInterceptor::CreateForWorker( - resource_request_, process_id, dedicated_worker_token, - shared_worker_token, service_worker_handle_); + resource_request_, process_id, worker_token, service_worker_handle_); if (service_worker_interceptor) interceptors_.push_back(std::move(service_worker_interceptor));
diff --git a/content/browser/worker_host/worker_script_loader.h b/content/browser/worker_host/worker_script_loader.h index 257d3ba..cf66c353 100644 --- a/content/browser/worker_host/worker_script_loader.h +++ b/content/browser/worker_host/worker_script_loader.h
@@ -14,6 +14,7 @@ #include "base/optional.h" #include "content/browser/loader/single_request_url_loader_factory.h" #include "content/browser/navigation_subresource_loader_params.h" +#include "content/public/browser/service_worker_client_info.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -69,8 +70,7 @@ // chrome-extension:// URL. WorkerScriptLoader( int process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, int32_t routing_id, int32_t request_id, uint32_t options,
diff --git a/content/browser/worker_host/worker_script_loader_factory.cc b/content/browser/worker_host/worker_script_loader_factory.cc index 74ff2bf..ca56530 100644 --- a/content/browser/worker_host/worker_script_loader_factory.cc +++ b/content/browser/worker_host/worker_script_loader_factory.cc
@@ -22,15 +22,13 @@ WorkerScriptLoaderFactory::WorkerScriptLoaderFactory( int process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, ServiceWorkerMainResourceHandle* service_worker_handle, base::WeakPtr<AppCacheHost> appcache_host, const BrowserContextGetter& browser_context_getter, scoped_refptr<network::SharedURLLoaderFactory> loader_factory) : process_id_(process_id), - dedicated_worker_token_(dedicated_worker_token), - shared_worker_token_(shared_worker_token), + worker_token_(worker_token), appcache_host_(std::move(appcache_host)), browser_context_getter_(browser_context_getter), loader_factory_(std::move(loader_factory)) { @@ -63,10 +61,10 @@ // Create a WorkerScriptLoader to load the script. auto script_loader = std::make_unique<WorkerScriptLoader>( - process_id_, dedicated_worker_token_, shared_worker_token_, routing_id, - request_id, options, resource_request, std::move(client), - service_worker_handle_, appcache_host_, browser_context_getter_, - loader_factory_, traffic_annotation); + process_id_, worker_token_, routing_id, request_id, options, + resource_request, std::move(client), service_worker_handle_, + appcache_host_, browser_context_getter_, loader_factory_, + traffic_annotation); script_loader_ = script_loader->GetWeakPtr(); mojo::MakeSelfOwnedReceiver(std::move(script_loader), std::move(receiver)); }
diff --git a/content/browser/worker_host/worker_script_loader_factory.h b/content/browser/worker_host/worker_script_loader_factory.h index 9347730..e2850d7a 100644 --- a/content/browser/worker_host/worker_script_loader_factory.h +++ b/content/browser/worker_host/worker_script_loader_factory.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "content/browser/navigation_subresource_loader_params.h" +#include "content/public/browser/service_worker_client_info.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "services/network/public/mojom/url_loader_factory.mojom.h" @@ -49,8 +50,7 @@ // factories used for non-http(s) URLs, e.g., a chrome-extension:// URL. WorkerScriptLoaderFactory( int process_id, - const blink::DedicatedWorkerToken& dedicated_worker_token, - const blink::SharedWorkerToken& shared_worker_token, + const DedicatedOrSharedWorkerToken& worker_token, ServiceWorkerMainResourceHandle* service_worker_handle, base::WeakPtr<AppCacheHost> appcache_host, const BrowserContextGetter& browser_context_getter, @@ -74,8 +74,7 @@ private: const int process_id_; - const blink::DedicatedWorkerToken dedicated_worker_token_; - const blink::SharedWorkerToken shared_worker_token_; + const DedicatedOrSharedWorkerToken worker_token_; base::WeakPtr<ServiceWorkerMainResourceHandle> service_worker_handle_; base::WeakPtr<AppCacheHost> appcache_host_; BrowserContextGetter browser_context_getter_;
diff --git a/content/browser/worker_host/worker_script_loader_factory_unittest.cc b/content/browser/worker_host/worker_script_loader_factory_unittest.cc index 1daba9d3..8af70181 100644 --- a/content/browser/worker_host/worker_script_loader_factory_unittest.cc +++ b/content/browser/worker_host/worker_script_loader_factory_unittest.cc
@@ -95,8 +95,7 @@ TEST_F(WorkerScriptLoaderFactoryTest, ServiceWorkerContainerHost) { // Make the factory. auto factory = std::make_unique<WorkerScriptLoaderFactory>( - kProcessId, blink::DedicatedWorkerToken::Null(), - blink::SharedWorkerToken::Null(), service_worker_handle_.get(), + kProcessId, DedicatedOrSharedWorkerToken(), service_worker_handle_.get(), /*appcache_host=*/nullptr, browser_context_getter_, network_loader_factory_); @@ -121,8 +120,7 @@ TEST_F(WorkerScriptLoaderFactoryTest, NullServiceWorkerHandle) { // Make the factory. auto factory = std::make_unique<WorkerScriptLoaderFactory>( - kProcessId, blink::DedicatedWorkerToken::Null(), - blink::SharedWorkerToken::Null(), service_worker_handle_.get(), + kProcessId, DedicatedOrSharedWorkerToken(), service_worker_handle_.get(), nullptr /* appcache_host */, browser_context_getter_, network_loader_factory_); @@ -146,8 +144,7 @@ TEST_F(WorkerScriptLoaderFactoryTest, NullBrowserContext) { // Make the factory. auto factory = std::make_unique<WorkerScriptLoaderFactory>( - kProcessId, blink::DedicatedWorkerToken::Null(), - blink::SharedWorkerToken::Null(), service_worker_handle_.get(), + kProcessId, DedicatedOrSharedWorkerToken(), service_worker_handle_.get(), nullptr /* appcache_host */, browser_context_getter_, network_loader_factory_);
diff --git a/content/public/browser/service_worker_client_info.cc b/content/public/browser/service_worker_client_info.cc index b46da1d..46d567f 100644 --- a/content/public/browser/service_worker_client_info.cc +++ b/content/public/browser/service_worker_client_info.cc
@@ -9,14 +9,27 @@ ServiceWorkerClientInfo::ServiceWorkerClientInfo(int frame_tree_node_id) : type_(blink::mojom::ServiceWorkerClientType::kWindow), frame_tree_node_id_(frame_tree_node_id) {} + ServiceWorkerClientInfo::ServiceWorkerClientInfo( const blink::DedicatedWorkerToken& dedicated_worker_token) : type_(blink::mojom::ServiceWorkerClientType::kDedicatedWorker), - dedicated_worker_token_(dedicated_worker_token) {} + worker_token_(dedicated_worker_token) {} + ServiceWorkerClientInfo::ServiceWorkerClientInfo( const blink::SharedWorkerToken& shared_worker_token) : type_(blink::mojom::ServiceWorkerClientType::kSharedWorker), - shared_worker_token_(shared_worker_token) {} + worker_token_(shared_worker_token) {} + +ServiceWorkerClientInfo::ServiceWorkerClientInfo( + const DedicatedOrSharedWorkerToken& worker_token) + : worker_token_(worker_token) { + if (worker_token.Is<blink::DedicatedWorkerToken>()) { + type_ = blink::mojom::ServiceWorkerClientType::kDedicatedWorker; + } else { + DCHECK(worker_token.Is<blink::SharedWorkerToken>()); + type_ = blink::mojom::ServiceWorkerClientType::kSharedWorker; + } +} ServiceWorkerClientInfo::ServiceWorkerClientInfo( const ServiceWorkerClientInfo& other) = default; @@ -31,16 +44,15 @@ return frame_tree_node_id_; } -const blink::DedicatedWorkerToken& -ServiceWorkerClientInfo::GetDedicatedWorkerToken() const { +blink::DedicatedWorkerToken ServiceWorkerClientInfo::GetDedicatedWorkerToken() + const { DCHECK_EQ(type_, blink::mojom::ServiceWorkerClientType::kDedicatedWorker); - return dedicated_worker_token_; + return worker_token_->GetAs<blink::DedicatedWorkerToken>(); } -const blink::SharedWorkerToken& ServiceWorkerClientInfo::GetSharedWorkerToken() - const { +blink::SharedWorkerToken ServiceWorkerClientInfo::GetSharedWorkerToken() const { DCHECK_EQ(type_, blink::mojom::ServiceWorkerClientType::kSharedWorker); - return shared_worker_token_; + return worker_token_->GetAs<blink::SharedWorkerToken>(); } } // namespace content
diff --git a/content/public/browser/service_worker_client_info.h b/content/public/browser/service_worker_client_info.h index 217f2f2d..03a13fc 100644 --- a/content/public/browser/service_worker_client_info.h +++ b/content/public/browser/service_worker_client_info.h
@@ -7,11 +7,15 @@ #include "content/common/content_export.h" #include "content/public/browser/render_frame_host.h" +#include "third_party/blink/public/common/tokens/multi_token.h" #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/service_worker/service_worker_client.mojom.h" namespace content { +using DedicatedOrSharedWorkerToken = + blink::MultiToken<blink::DedicatedWorkerToken, blink::SharedWorkerToken>; + // Holds information about a single service worker client: // https://w3c.github.io/ServiceWorker/#client class CONTENT_EXPORT ServiceWorkerClientInfo { @@ -21,6 +25,8 @@ const blink::DedicatedWorkerToken& dedicated_worker_token); explicit ServiceWorkerClientInfo( const blink::SharedWorkerToken& shared_worker_token); + explicit ServiceWorkerClientInfo( + const DedicatedOrSharedWorkerToken& worker_token); ServiceWorkerClientInfo(const ServiceWorkerClientInfo& other); ServiceWorkerClientInfo& operator=(const ServiceWorkerClientInfo& other); @@ -31,21 +37,24 @@ blink::mojom::ServiceWorkerClientType type() const { return type_; } int GetFrameTreeNodeId() const; - const blink::DedicatedWorkerToken& GetDedicatedWorkerToken() const; - const blink::SharedWorkerToken& GetSharedWorkerToken() const; + + // Returns the corresponding DedicatedWorkerToken. This should only be called + // if "type() == blink::mojom::ServiceWorkerClientType::kDedicatedWorker". + blink::DedicatedWorkerToken GetDedicatedWorkerToken() const; + + // Returns the corresponding SharedWorkerToken. This should only be called + // if "type() == blink::mojom::ServiceWorkerClientType::kSharedWorker". + blink::SharedWorkerToken GetSharedWorkerToken() const; private: // The client type. blink::mojom::ServiceWorkerClientType type_; - // The frame tree node ID, if this is a window client. + // The frame tree node ID, if it is a window client. int frame_tree_node_id_ = content::RenderFrameHost::kNoFrameTreeNodeId; - // The ID of the client, if this is a dedicated worker client. - blink::DedicatedWorkerToken dedicated_worker_token_; - - // The ID of the client, if this is a shared worker client. - blink::SharedWorkerToken shared_worker_token_; + // The ID of the client, if it is a worker. + base::Optional<DedicatedOrSharedWorkerToken> worker_token_; }; } // namespace content
diff --git a/content/renderer/worker/dedicated_worker_host_factory_client.cc b/content/renderer/worker/dedicated_worker_host_factory_client.cc index 75e7ef8..b1e96b4 100644 --- a/content/renderer/worker/dedicated_worker_host_factory_client.cc +++ b/content/renderer/worker/dedicated_worker_host_factory_client.cc
@@ -41,7 +41,6 @@ base::OnceCallback<void(const network::CrossOriginEmbedderPolicy&)> callback) { DCHECK(!base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker)); - DCHECK(!dedicated_worker_token.is_empty()); mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> browser_interface_broker; factory_->CreateWorkerHost( @@ -59,7 +58,6 @@ blink::CrossVariantMojoRemote<blink::mojom::BlobURLTokenInterfaceBase> blob_url_token) { DCHECK(base::FeatureList::IsEnabled(blink::features::kPlzDedicatedWorker)); - DCHECK(!dedicated_worker_token.is_empty()); factory_->CreateWorkerHostAndStartScriptLoad( dedicated_worker_token, script_url, credentials_mode, FetchClientSettingsObjectFromWebToMojom(fetch_client_settings_object),
diff --git a/content/renderer/worker/embedded_shared_worker_stub.cc b/content/renderer/worker/embedded_shared_worker_stub.cc index c8ce967..0d1b9d71 100644 --- a/content/renderer/worker/embedded_shared_worker_stub.cc +++ b/content/renderer/worker/embedded_shared_worker_stub.cc
@@ -57,7 +57,6 @@ ukm::SourceId ukm_source_id, const std::vector<std::string>& cors_exempt_header_list) : receiver_(this, std::move(receiver)) { - DCHECK(token); DCHECK(main_script_load_params); DCHECK(pending_subresource_loader_factory_bundle);
diff --git a/content/renderer/worker/shared_worker_factory_impl.cc b/content/renderer/worker/shared_worker_factory_impl.cc index 2fe549bc..d67764c 100644 --- a/content/renderer/worker/shared_worker_factory_impl.cc +++ b/content/renderer/worker/shared_worker_factory_impl.cc
@@ -48,7 +48,6 @@ mojo::PendingRemote<blink::mojom::BrowserInterfaceBroker> browser_interface_broker, ukm::SourceId ukm_source_id) { - DCHECK(token); // Bound to the lifetime of the underlying blink::WebSharedWorker instance. new EmbeddedSharedWorkerStub( std::move(info), token, constructor_origin, user_agent, ua_metadata,
diff --git a/content/test/data/accessibility/event/aria-sort-changed-expected-auralinux.txt b/content/test/data/accessibility/event/aria-sort-changed-expected-auralinux.txt index aa3c875..0a782f1 100644 --- a/content/test/data/accessibility/event/aria-sort-changed-expected-auralinux.txt +++ b/content/test/data/accessibility/event/aria-sort-changed-expected-auralinux.txt
@@ -1 +1,5 @@ -#<skip -- TODO(crbug.com/1074380)> \ No newline at end of file +COLUMN-REORDERED role=ROLE_TABLE name='(null)' ENABLED,SENSITIVE,SHOWING,VISIBLE +ROW-REORDERED role=ROLE_TABLE name='(null)' ENABLED,SENSITIVE,SHOWING,VISIBLE +ROW-REORDERED role=ROLE_TABLE name='(null)' ENABLED,SENSITIVE,SHOWING,VISIBLE +ROW-REORDERED role=ROLE_TABLE name='(null)' ENABLED,SENSITIVE,SHOWING,VISIBLE +ROW-REORDERED role=ROLE_TABLE name='(null)' ENABLED,SENSITIVE,SHOWING,VISIBLE
diff --git a/content/test/data/accessibility/event/aria-sort-changed-expected-uia-win.txt b/content/test/data/accessibility/event/aria-sort-changed-expected-uia-win.txt index 7b55295..7570f20 100644 --- a/content/test/data/accessibility/event/aria-sort-changed-expected-uia-win.txt +++ b/content/test/data/accessibility/event/aria-sort-changed-expected-uia-win.txt
@@ -2,3 +2,4 @@ AriaProperties changed on role=columnheader, name=columnheader3 AriaProperties changed on role=columnheader, name=columnheader4 AriaProperties changed on role=columnheader, name=columnheader5 +AriaProperties changed on role=rowheader, name=rowheader1
diff --git a/content/test/data/accessibility/event/aria-sort-changed-expected-win.txt b/content/test/data/accessibility/event/aria-sort-changed-expected-win.txt index 1a34b2a..6a69170a8 100644 --- a/content/test/data/accessibility/event/aria-sort-changed-expected-win.txt +++ b/content/test/data/accessibility/event/aria-sort-changed-expected-win.txt
@@ -1,4 +1,5 @@ +IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED on <div#ch0> role=ROLE_SYSTEM_ROWHEADER name="rowheader1" IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED on <div#ch2> role=ROLE_SYSTEM_COLUMNHEADER name="columnheader2" IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED on <div#ch3> role=ROLE_SYSTEM_COLUMNHEADER name="columnheader3" IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED on <div#ch4> role=ROLE_SYSTEM_COLUMNHEADER name="columnheader4" -IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED on <div#ch5> role=ROLE_SYSTEM_COLUMNHEADER name="columnheader5" \ No newline at end of file +IA2_EVENT_OBJECT_ATTRIBUTE_CHANGED on <div#ch5> role=ROLE_SYSTEM_COLUMNHEADER name="columnheader5"
diff --git a/content/test/data/accessibility/event/aria-sort-changed.html b/content/test/data/accessibility/event/aria-sort-changed.html index 93d8bae..e98e80c 100644 --- a/content/test/data/accessibility/event/aria-sort-changed.html +++ b/content/test/data/accessibility/event/aria-sort-changed.html
@@ -3,6 +3,7 @@ <body> <div role="grid"> <div role="row"> + <div id="ch0" aria-label="rowheader1" role="rowheader" aria-sort="descending"></div> <div id="ch1" aria-label="columnheader1" role="columnheader"></div> <div id="ch2" aria-label="columnheader2" role="columnheader"></div> <div id="ch3" aria-label="columnheader3" role="columnheader"></div> @@ -12,6 +13,9 @@ </div> <script> function go() { + // Set aria-sort from 'descending'->'ascending'; should fire an event. + document.getElementById('ch0').setAttribute('aria-sort', 'ascending'); + // Set aria-sort from default 'none'->'none'; should not fire an event. document.getElementById('ch1').setAttribute('aria-sort', 'none');
diff --git a/content/test/gpu/gpu_tests/gpu_helper.py b/content/test/gpu/gpu_tests/gpu_helper.py index 5c40e6d..92def1da 100644 --- a/content/test/gpu/gpu_tests/gpu_helper.py +++ b/content/test/gpu/gpu_tests/gpu_helper.py
@@ -109,6 +109,8 @@ retval = 'opengles' elif 'OpenGL' in gl_renderer: retval = 'opengl' + elif 'Metal' in gl_renderer: + retval = 'metal' # SwiftShader first because it also contains Vulkan elif 'SwiftShader' in gl_renderer: retval = 'swiftshader'
diff --git a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py index f6c8e63..93634b2 100644 --- a/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py +++ b/content/test/gpu/gpu_tests/webgl_conformance_integration_test.py
@@ -241,6 +241,7 @@ 'd3d9': ['d3d9'], 'opengl': ['gl'], 'opengles': ['gles'], + 'metal': ['metal'], 'vulkan': ['vulkan'], # Support setting VK_ICD_FILENAMES for swiftshader when requesting # the 'vulkan' backend.
diff --git a/content/test/test_render_frame.cc b/content/test/test_render_frame.cc index 4d3c9512..49b353a 100644 --- a/content/test/test_render_frame.cc +++ b/content/test/test_render_frame.cc
@@ -160,8 +160,8 @@ mojo::PendingAssociatedRemote<blink::mojom::PortalClient>, CreatePortalCallback callback) override { std::move(callback).Run(MSG_ROUTING_NONE, FrameReplicationState(), - blink::PortalToken::Null(), - base::UnguessableToken(), base::UnguessableToken()); + blink::PortalToken(), base::UnguessableToken(), + base::UnguessableToken()); } void AdoptPortal(const blink::PortalToken&,
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h index ff5e8ee..e5ef8ee 100644 --- a/gpu/command_buffer/service/feature_info.h +++ b/gpu/command_buffer/service/feature_info.h
@@ -39,7 +39,7 @@ GpuMemoryBufferFormatSet gpu_memory_buffer_formats = { gfx::BufferFormat::BGR_565, gfx::BufferFormat::RGBA_4444, gfx::BufferFormat::RGBA_8888, gfx::BufferFormat::RGBX_8888, - gfx::BufferFormat::YVU_420, + gfx::BufferFormat::YVU_420, gfx::BufferFormat::YUV_420_BIPLANAR, }; // Use glBlitFramebuffer() and glRenderbufferStorageMultisample() with // GL_EXT_framebuffer_multisample-style semantics (as opposed to
diff --git a/gpu/ipc/service/gpu_init.cc b/gpu/ipc/service/gpu_init.cc index 0a65628..027eac2 100644 --- a/gpu/ipc/service/gpu_init.cc +++ b/gpu/ipc/service/gpu_init.cc
@@ -360,13 +360,14 @@ // On MacOS, the default texture target for native GpuMemoryBuffers is // GL_TEXTURE_RECTANGLE_ARB. This is due to CGL's requirements for creating - // a GL surface. However, when ANGLE is used on top of SwiftShader, it's - // necessary to use GL_TEXTURE_2D instead. + // a GL surface. However, when ANGLE is used on top of SwiftShader or Metal, + // it's necessary to use GL_TEXTURE_2D instead. // TODO(crbug.com/1056312): The proper behavior is to check the config // parameter set by the EGL_ANGLE_iosurface_client_buffer extension #if defined(OS_MAC) if (gl::GetGLImplementation() == gl::kGLImplementationEGLANGLE && - gl::GetANGLEImplementation() == gl::ANGLEImplementation::kSwiftShader) { + (gl::GetANGLEImplementation() == gl::ANGLEImplementation::kSwiftShader || + gl::GetANGLEImplementation() == gl::ANGLEImplementation::kMetal)) { SetMacOSSpecificTextureTarget(GL_TEXTURE_2D); } #endif // defined(OS_MAC)
diff --git a/headless/lib/headless_web_contents_browsertest.cc b/headless/lib/headless_web_contents_browsertest.cc index ac4a3e55..5f5d22e0 100644 --- a/headless/lib/headless_web_contents_browsertest.cc +++ b/headless/lib/headless_web_contents_browsertest.cc
@@ -370,7 +370,8 @@ EXPECT_TRUE(chrome_pdf::RenderPDFPageToBitmap( pdf_span, i, page_bitmap_data.data(), settings.area.size().width(), settings.area.size().height(), settings.dpi.width(), - settings.dpi.height(), settings.autorotate, settings.use_color)); + settings.dpi.height(), /*stretch_to_bounds=*/false, + /*keep_aspect_ratio=*/true, settings.autorotate, settings.use_color)); EXPECT_EQ(0x56, page_bitmap_data[0]); // B EXPECT_EQ(0x34, page_bitmap_data[1]); // G EXPECT_EQ(0x12, page_bitmap_data[2]); // R
diff --git a/ios/chrome/app/application_delegate/user_activity_handler.mm b/ios/chrome/app/application_delegate/user_activity_handler.mm index b726e745..5d0a1f0 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler.mm
@@ -208,11 +208,11 @@ base::mac::ObjCCastStrict<OpenInChromeIncognitoIntent>( userActivity.interaction.intent); - if (!intent.urls || intent.urls.count == 0) { + if (!intent.url || intent.url.count == 0) { return NO; } - std::vector<GURL> URLs = createGURLVectorFromIntentURLs(intent.urls); + std::vector<GURL> URLs = createGURLVectorFromIntentURLs(intent.url); AppStartupParameters* startupParams = [[AppStartupParameters alloc] initWithURLs: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 74d6bbe5..26b6bcc 100644 --- a/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm +++ b/ios/chrome/app/application_delegate/user_activity_handler_unittest.mm
@@ -465,7 +465,7 @@ OpenInChromeIncognitoIntent* intent = [[OpenInChromeIncognitoIntent alloc] init]; - intent.urls = urls; + intent.url = urls; INInteraction* interaction = [[INInteraction alloc] initWithIntent:intent response:nil]; @@ -487,8 +487,8 @@ AppStartupParameters* startupParameters = (AppStartupParameters*)value; const GURL calledURL = startupParameters.externalURL; - EXPECT_TRUE((int)[intent.urls count] == 3); - return [intent.urls containsObject:(net::NSURLWithGURL(calledURL))]; + EXPECT_TRUE((int)[intent.url count] == 3); + return [intent.url containsObject:(net::NSURLWithGURL(calledURL))]; } else { return YES; } @@ -576,7 +576,7 @@ OpenInChromeIncognitoIntent* intent = [[OpenInChromeIncognitoIntent alloc] init]; - intent.urls = urls; + intent.url = urls; INInteraction* interaction = [[INInteraction alloc] initWithIntent:intent response:nil]; @@ -598,8 +598,8 @@ AppStartupParameters* startupParameters = (AppStartupParameters*)value; const GURL calledURL = startupParameters.externalURL; - EXPECT_TRUE((int)[intent.urls count] == 3); - return [intent.urls containsObject:(net::NSURLWithGURL(calledURL))]; + EXPECT_TRUE((int)[intent.url count] == 3); + return [intent.url containsObject:(net::NSURLWithGURL(calledURL))]; } else { return YES; }
diff --git a/ios/chrome/app/intents/Intents.intentdefinition b/ios/chrome/app/intents/Intents.intentdefinition index 2537829..667ed615 100644 --- a/ios/chrome/app/intents/Intents.intentdefinition +++ b/ios/chrome/app/intents/Intents.intentdefinition
@@ -215,17 +215,17 @@ <key>INIntentIneligibleForSuggestions</key> <true/> <key>INIntentInput</key> - <string>urls</string> + <string>url</string> <key>INIntentLastParameterTag</key> <integer>4</integer> <key>INIntentManagedParameterCombinations</key> <dict> - <key>urls</key> + <key>url</key> <dict> <key>INIntentParameterCombinationSupportsBackgroundExecution</key> <true/> <key>INIntentParameterCombinationTitle</key> - <string>Open ${urls} in Incognito</string> + <string>Open ${url} in Incognito</string> <key>INIntentParameterCombinationTitleID</key> <string>6TwrYB</string> <key>INIntentParameterCombinationUpdatesLinked</key> @@ -240,20 +240,20 @@ <key>INIntentParameterConfigurable</key> <true/> <key>INIntentParameterDisplayName</key> - <string>URLs</string> + <string>URL</string> <key>INIntentParameterDisplayNameID</key> <string>C8MCpv</string> <key>INIntentParameterDisplayPriority</key> <integer>1</integer> <key>INIntentParameterName</key> - <string>urls</string> + <string>url</string> <key>INIntentParameterPromptDialogs</key> <array> <dict> <key>INIntentParameterPromptDialogCustom</key> <true/> <key>INIntentParameterPromptDialogFormatString</key> - <string>What URLs?</string> + <string>What URL?</string> <key>INIntentParameterPromptDialogFormatStringID</key> <string>sNz7Cu</string> <key>INIntentParameterPromptDialogType</key>
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 4a930bd1..2ac28d2 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -717,6 +717,14 @@ // Unregister the observer before the service is destroyed. _localStatePrefChangeRegistrar.RemoveAll(); + // Under the UIScene API, the scene delegate does not receive + // sceneDidDisconnect: notifications on app termination. We mark remaining + // connected scene states as diconnected in order to allow services to + // properly unregister their observers and tear down remaining UI. + for (SceneState* sceneState in self.appState.connectedScenes) { + sceneState.activationLevel = SceneActivationLevelUnattached; + } + _chromeMain.reset(); }
diff --git a/ios/chrome/app/strings/ios_chromium_strings.grd b/ios/chrome/app/strings/ios_chromium_strings.grd index 06d694a..7e8a11c5 100644 --- a/ios/chrome/app/strings/ios_chromium_strings.grd +++ b/ios/chrome/app/strings/ios_chromium_strings.grd
@@ -331,6 +331,9 @@ <message name="IDS_IOS_PASSWORD_CHECK_ERROR" desc="Description of the password check cell, explaining that Password Check failed. [iOS only]" meaning="Password Check failed due to some error."> Chromium can't check your passwords </message> + <message name="IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS" desc="Description text for when password check cannot be run because the user has no saved passwords"> + No saved passwords. Chromium can check your passwords when you save them. + </message> <message name="IDS_IOS_PASSWORD_CHECK_ERROR_OFFLINE" desc="Text inside popover which is shown when the user wants to see detailed information about the error. [iOS only]" meaning="The user has no internet connection and can't check passwords."> Chromium couldn't check your passwords. Try checking your internet connection. </message>
diff --git a/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS.png.sha1 b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS.png.sha1 new file mode 100644 index 0000000..ce9926ee --- /dev/null +++ b/ios/chrome/app/strings/ios_chromium_strings_grd/IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS.png.sha1
@@ -0,0 +1 @@ +79dd83f5a48633878501b3b1cc8eebd4123017b6 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings.grd b/ios/chrome/app/strings/ios_google_chrome_strings.grd index f7398a5cb..fc0c231 100644 --- a/ios/chrome/app/strings/ios_google_chrome_strings.grd +++ b/ios/chrome/app/strings/ios_google_chrome_strings.grd
@@ -331,6 +331,9 @@ <message name="IDS_IOS_PASSWORD_CHECK_ERROR" desc="Description of the password check cell, explaining that Password Check failed. [iOS only]" meaning="Password Check failed due to some error."> Chrome can't check your passwords </message> + <message name="IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS" desc="Description text for when password check cannot be run because the user has no saved passwords"> + No saved passwords. Chrome can check your passwords when you save them. + </message> <message name="IDS_IOS_PASSWORD_CHECK_ERROR_OFFLINE" desc="Text inside popover which is shown when the user wants to see detailed information about the error. [iOS only]" meaning="The user has no internet connection and can't check passwords."> Chrome couldn't check your passwords. Try checking your internet connection. </message>
diff --git a/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS.png.sha1 b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS.png.sha1 new file mode 100644 index 0000000..7fd7ba4 --- /dev/null +++ b/ios/chrome/app/strings/ios_google_chrome_strings_grd/IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS.png.sha1
@@ -0,0 +1 @@ +d99952b13e0ed23d807a36be7f1b5bbf521a0412 \ No newline at end of file
diff --git a/ios/chrome/app/strings/ios_strings.grd b/ios/chrome/app/strings/ios_strings.grd index 64ac300e..e8bc22e5 100644 --- a/ios/chrome/app/strings/ios_strings.grd +++ b/ios/chrome/app/strings/ios_strings.grd
@@ -955,7 +955,7 @@ Opens the inputted URLs in Google Chrome in Incognito. </message> <message name="IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE" desc="Apple Shortcuts.app format for displaying the URL input [iOS only]."> - Open ${urls} in Incognito + Open ${url} in Incognito </message> <message name="IDS_IOS_INTENTS_SEARCH_IN_CHROME_DESCRIPTION" desc="Siri Shortcut for search in chrome description [iOS only]."> Start a search in a new Chrome tab.
diff --git a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE.png.sha1 b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE.png.sha1 index 61446bf..160b123d 100644 --- a/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE.png.sha1 +++ b/ios/chrome/app/strings/ios_strings_grd/IDS_IOS_INTENTS_OPEN_IN_CHROME_INCOGNITO_PARAMETER_COMBINATION_TITLE.png.sha1
@@ -1 +1 @@ -6bd0e2112cf7b407cc5ea7adee64a55981d83751 \ No newline at end of file +d2895617942b5b046ac5584ed3ebe037448c3288 \ No newline at end of file
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index b9655929..3211c6e 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS
@@ -61,6 +61,7 @@ "+components/policy/core/browser", "+components/policy/core/common", "+components/policy/policy_constants.h", + "+components/policy/proto/device_management_backend.pb.h", "+components/pref_registry", "+components/prefs", "+components/profile_metrics",
diff --git a/ios/chrome/browser/ios_chrome_io_thread.mm b/ios/chrome/browser/ios_chrome_io_thread.mm index 09a6cd74..f70fbdb 100644 --- a/ios/chrome/browser/ios_chrome_io_thread.mm +++ b/ios/chrome/browser/ios_chrome_io_thread.mm
@@ -53,6 +53,7 @@ network::mojom::URLLoaderFactoryParams::New(); url_loader_factory_params->process_id = network::mojom::kBrowserProcessId; url_loader_factory_params->is_corb_enabled = false; + url_loader_factory_params->is_trusted = true; GetSystemNetworkContext()->CreateURLLoaderFactory( url_loader_factory_.BindNewPipeAndPassReceiver(), std::move(url_loader_factory_params));
diff --git a/ios/chrome/browser/ios_chrome_main_parts.mm b/ios/chrome/browser/ios_chrome_main_parts.mm index d8b4536..cf898da3 100644 --- a/ios/chrome/browser/ios_chrome_main_parts.mm +++ b/ios/chrome/browser/ios_chrome_main_parts.mm
@@ -49,6 +49,7 @@ #include "ios/chrome/browser/install_time_util.h" #include "ios/chrome/browser/metrics/ios_expired_histograms_array.h" #include "ios/chrome/browser/open_from_clipboard/create_clipboard_recent_content.h" +#include "ios/chrome/browser/policy/browser_policy_connector_ios.h" #include "ios/chrome/browser/pref_names.h" #include "ios/chrome/browser/safe_browsing/safe_browsing_service.h" #include "ios/chrome/browser/translate/translate_service_ios.h" @@ -252,6 +253,14 @@ variations_service->PerformPreMainMessageLoopStartup(); } + // Initialize Chrome Browser Cloud Management. + auto* policy_connector = application_context_->GetBrowserPolicyConnector(); + if (policy_connector) { + policy_connector->chrome_browser_cloud_management_controller()->Init( + application_context_->GetLocalState(), + application_context_->GetSharedURLLoaderFactory()); + } + if (base::FeatureList::IsEnabled( safe_browsing::kSafeBrowsingAvailableOnIOS)) { // Ensure that Safe Browsing is initialized.
diff --git a/ios/chrome/browser/policy/BUILD.gn b/ios/chrome/browser/policy/BUILD.gn index fad91653..fca8a07 100644 --- a/ios/chrome/browser/policy/BUILD.gn +++ b/ios/chrome/browser/policy/BUILD.gn
@@ -20,6 +20,14 @@ "device_management_service_configuration_ios.mm", "policy_conversions_client_ios.h", "policy_conversions_client_ios.mm", + "reporting/browser_report_generator_ios.h", + "reporting/browser_report_generator_ios.mm", + "reporting/profile_report_generator_ios.h", + "reporting/profile_report_generator_ios.mm", + "reporting/report_generator_ios.h", + "reporting/report_generator_ios.mm", + "reporting/report_scheduler_ios.h", + "reporting/report_scheduler_ios.mm", "reporting/reporting_delegate_factory_ios.h", "reporting/reporting_delegate_factory_ios.mm", "schema_registry_factory.h", @@ -35,6 +43,7 @@ "//components/password_manager/core/common", "//components/policy:generated", "//components/policy/core/common", + "//components/policy/proto", "//components/safe_browsing/core/common:safe_browsing_policy_handler", "//components/safe_browsing/core/common:safe_browsing_prefs", "//components/search_engines", @@ -45,6 +54,9 @@ "//ios/chrome/browser", "//ios/chrome/browser:pref_names", "//ios/chrome/browser/browser_state", + "//ios/chrome/browser/signin", + "//ios/chrome/common", + "//ios/public/provider/chrome/browser/signin", "//services/network/public/cpp", ]
diff --git a/ios/chrome/browser/policy/browser_dm_token_storage_ios.mm b/ios/chrome/browser/policy/browser_dm_token_storage_ios.mm index 662d59e..5aa3940e 100644 --- a/ios/chrome/browser/policy/browser_dm_token_storage_ios.mm +++ b/ios/chrome/browser/policy/browser_dm_token_storage_ios.mm
@@ -4,13 +4,20 @@ #include "ios/chrome/browser/policy/browser_dm_token_storage_ios.h" +#import <Foundation/Foundation.h> + #include "base/base64url.h" #include "base/files/file_util.h" #include "base/files/important_file_writer.h" #include "base/hash/sha1.h" +#include "base/ios/device_util.h" #include "base/path_service.h" +#include "base/strings/string_util.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" #include "base/task/post_task.h" #include "base/task/thread_pool.h" +#import "components/policy/core/common/policy_loader_ios_constants.h" #include "ios/chrome/browser/file_metadata_util.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -23,6 +30,7 @@ const char kDmTokenBaseDir[] = FILE_PATH_LITERAL("Google/Chrome Cloud Enrollment/"); +const char kEnrollmentTokenPolicyName[] = "CloudManagementEnrollmentToken"; bool GetDmTokenFilePath(base::FilePath* token_file_path, const std::string& client_id, @@ -67,18 +75,34 @@ BrowserDMTokenStorageIOS::~BrowserDMTokenStorageIOS() {} std::string BrowserDMTokenStorageIOS::InitClientId() { - // TODO(crbug.com/1066495): Finish iOS CBCM implementation. - return ""; + return ios::device_util::GetDeviceIdentifier(nullptr); } std::string BrowserDMTokenStorageIOS::InitEnrollmentToken() { - // TODO(crbug.com/1066495): Finish iOS CBCM implementation. - return ""; + NSDictionary* raw_policies = [[NSUserDefaults standardUserDefaults] + dictionaryForKey:kPolicyLoaderIOSConfigurationKey]; + NSString* token = + raw_policies[base::SysUTF8ToNSString(kEnrollmentTokenPolicyName)]; + + if (token) { + return base::TrimWhitespaceASCII(base::SysNSStringToUTF8(token), + base::TRIM_ALL) + .as_string(); + } + + return std::string(); } std::string BrowserDMTokenStorageIOS::InitDMToken() { - // TODO(crbug.com/1066495): Finish iOS CBCM implementation. - return ""; + base::FilePath token_file_path; + if (!GetDmTokenFilePath(&token_file_path, InitClientId(), false)) + return std::string(); + + std::string token; + if (!base::ReadFileToString(token_file_path, &token)) + return std::string(); + + return base::TrimWhitespaceASCII(token, base::TRIM_ALL).as_string(); } bool BrowserDMTokenStorageIOS::InitEnrollmentErrorOption() {
diff --git a/ios/chrome/browser/policy/chrome_browser_cloud_management_controller_ios.mm b/ios/chrome/browser/policy/chrome_browser_cloud_management_controller_ios.mm index dad73f4..b2e2b55c 100644 --- a/ios/chrome/browser/policy/chrome_browser_cloud_management_controller_ios.mm +++ b/ios/chrome/browser/policy/chrome_browser_cloud_management_controller_ios.mm
@@ -5,6 +5,8 @@ #include "ios/chrome/browser/policy/chrome_browser_cloud_management_controller_ios.h" #include "base/bind.h" +#include "components/enterprise/browser/reporting/report_generator.h" +#include "components/enterprise/browser/reporting/report_scheduler.h" #include "components/policy/core/common/cloud/machine_level_user_cloud_policy_manager.h" #include "components/policy/core/common/features.h" #include "ios/chrome/browser/application_context.h"
diff --git a/ios/chrome/browser/policy/reporting/browser_report_generator_ios.h b/ios/chrome/browser/policy/reporting/browser_report_generator_ios.h new file mode 100644 index 0000000..106b4b98 --- /dev/null +++ b/ios/chrome/browser/policy/reporting/browser_report_generator_ios.h
@@ -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. + +#ifndef IOS_CHROME_BROWSER_POLICY_REPORTING_BROWSER_REPORT_GENERATOR_IOS_H_ +#define IOS_CHROME_BROWSER_POLICY_REPORTING_BROWSER_REPORT_GENERATOR_IOS_H_ + +#include "components/enterprise/browser/reporting/browser_report_generator.h" + +#include <memory> + +#include "base/callback.h" +#include "components/policy/proto/device_management_backend.pb.h" +#include "components/version_info/channel.h" + +namespace em = ::enterprise_management; + +namespace enterprise_reporting { + +// iOS implementation of platform-specific info fetching for Enterprise browser +// report generation. +class BrowserReportGeneratorIOS : public BrowserReportGenerator::Delegate { + public: + using ReportCallback = base::OnceCallback<void( + std::unique_ptr<enterprise_management::BrowserReport>)>; + + BrowserReportGeneratorIOS(); + BrowserReportGeneratorIOS(const BrowserReportGeneratorIOS&) = delete; + BrowserReportGeneratorIOS& operator=(const BrowserReportGeneratorIOS&) = + delete; + ~BrowserReportGeneratorIOS() override; + + // BrowserReportGenerator::Delegate implementation. + std::string GetExecutablePath() override; + version_info::Channel GetChannel() override; + void GenerateBuildStateInfo(em::BrowserReport* report) override; + void GenerateProfileInfo(em::BrowserReport* report) override; + void GeneratePluginsIfNeeded( + ReportCallback callback, + std::unique_ptr<em::BrowserReport> report) override; +}; + +} // namespace enterprise_reporting + +#endif // IOS_CHROME_BROWSER_POLICY_REPORTING_BROWSER_REPORT_GENERATOR_IOS_H_
diff --git a/ios/chrome/browser/policy/reporting/browser_report_generator_ios.mm b/ios/chrome/browser/policy/reporting/browser_report_generator_ios.mm new file mode 100644 index 0000000..cd57038 --- /dev/null +++ b/ios/chrome/browser/policy/reporting/browser_report_generator_ios.mm
@@ -0,0 +1,65 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/policy/reporting/browser_report_generator_ios.h" + +#include "base/mac/bundle_locations.h" +#include "base/mac/foundation_util.h" +#include "base/strings/sys_string_conversions.h" +#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h" +#include "ios/chrome/common/channel_info.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace em = ::enterprise_management; + +namespace enterprise_reporting { + +BrowserReportGeneratorIOS::BrowserReportGeneratorIOS() = default; + +BrowserReportGeneratorIOS::~BrowserReportGeneratorIOS() = default; + +std::string BrowserReportGeneratorIOS::GetExecutablePath() { + NSBundle* baseBundle = base::mac::OuterBundle(); + return base::SysNSStringToUTF8([baseBundle bundleIdentifier]); +} + +version_info::Channel BrowserReportGeneratorIOS::GetChannel() { + return ::GetChannel(); +} + +void BrowserReportGeneratorIOS::GenerateBuildStateInfo( + em::BrowserReport* report) { + // Not used on iOS because there is no in-app auto-update. +} + +void BrowserReportGeneratorIOS::GenerateProfileInfo(em::BrowserReport* report) { + for (const auto* entry : GetApplicationContext() + ->GetChromeBrowserStateManager() + ->GetLoadedBrowserStates()) { + // Skip off-the-record profile. + if (entry->IsOffTheRecord()) { + continue; + } + + em::ChromeUserProfileInfo* profile = + report->add_chrome_user_profile_infos(); + profile->set_id(entry->GetStatePath().AsUTF8Unsafe()); + profile->set_name(entry->GetStatePath().BaseName().AsUTF8Unsafe()); + profile->set_is_full_report(false); + } +} + +void BrowserReportGeneratorIOS::GeneratePluginsIfNeeded( + ReportCallback callback, + std::unique_ptr<em::BrowserReport> report) { + // There are no plugins on iOS. + std::move(callback).Run(std::move(report)); +} + +} // namespace enterprise_reporting
diff --git a/ios/chrome/browser/policy/reporting/profile_report_generator_ios.h b/ios/chrome/browser/policy/reporting/profile_report_generator_ios.h new file mode 100644 index 0000000..782e24d --- /dev/null +++ b/ios/chrome/browser/policy/reporting/profile_report_generator_ios.h
@@ -0,0 +1,57 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_POLICY_REPORTING_PROFILE_REPORT_GENERATOR_IOS_H_ +#define IOS_CHROME_BROWSER_POLICY_REPORTING_PROFILE_REPORT_GENERATOR_IOS_H_ + +#include "components/enterprise/browser/reporting/profile_report_generator.h" + +#include <memory> + +#include "base/macros.h" +#include "components/policy/core/browser/policy_conversions_client.h" +#include "components/policy/proto/device_management_backend.pb.h" + +namespace base { +class FilePath; +} + +namespace policy { +class MachineLevelUserCloudPolicyManager; +} + +class ChromeBrowserState; + +namespace enterprise_reporting { + +/** + * iOS implementation of the profile reporting delegate. + */ +class ProfileReportGeneratorIOS : public ProfileReportGenerator::Delegate { + public: + ProfileReportGeneratorIOS(); + ProfileReportGeneratorIOS(const ProfileReportGeneratorIOS&) = delete; + ProfileReportGeneratorIOS& operator=(const ProfileReportGeneratorIOS&) = + delete; + ~ProfileReportGeneratorIOS() override; + + // ProfileReportGenerator::Delegate implementation. + bool Init(const base::FilePath& path) override; + void GetSigninUserInfo( + enterprise_management::ChromeUserProfileInfo* report) override; + void GetExtensionInfo( + enterprise_management::ChromeUserProfileInfo* report) override; + void GetExtensionRequest( + enterprise_management::ChromeUserProfileInfo* report) override; + std::unique_ptr<policy::PolicyConversionsClient> MakePolicyConversionsClient() + override; + policy::MachineLevelUserCloudPolicyManager* GetCloudPolicyManager() override; + + private: + ChromeBrowserState* browser_state_; +}; + +} // namespace enterprise_reporting + +#endif // IOS_CHROME_BROWSER_POLICY_REPORTING_PROFILE_REPORT_GENERATOR_IOS_H_
diff --git a/ios/chrome/browser/policy/reporting/profile_report_generator_ios.mm b/ios/chrome/browser/policy/reporting/profile_report_generator_ios.mm new file mode 100644 index 0000000..cbaf954 --- /dev/null +++ b/ios/chrome/browser/policy/reporting/profile_report_generator_ios.mm
@@ -0,0 +1,79 @@ +// 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 "ios/chrome/browser/policy/reporting/profile_report_generator_ios.h" + +#include "base/strings/sys_string_conversions.h" +#include "components/policy/core/browser/policy_conversions.h" +#include "ios/chrome/browser/application_context.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#include "ios/chrome/browser/browser_state/chrome_browser_state_manager.h" +#include "ios/chrome/browser/policy/browser_policy_connector_ios.h" +#include "ios/chrome/browser/policy/policy_conversions_client_ios.h" +#include "ios/chrome/browser/signin/authentication_service.h" +#include "ios/chrome/browser/signin/authentication_service_factory.h" +#include "ios/public/provider/chrome/browser/signin/chrome_identity.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace enterprise_reporting { + +ProfileReportGeneratorIOS::ProfileReportGeneratorIOS() = default; + +ProfileReportGeneratorIOS::~ProfileReportGeneratorIOS() = default; + +bool ProfileReportGeneratorIOS::Init(const base::FilePath& path) { + browser_state_ = + GetApplicationContext()->GetChromeBrowserStateManager()->GetBrowserState( + path); + + if (!browser_state_) { + return false; + } + + return true; +} + +void ProfileReportGeneratorIOS::GetSigninUserInfo( + enterprise_management::ChromeUserProfileInfo* report) { + if (!AuthenticationServiceFactory::GetForBrowserState(browser_state_) + ->IsAuthenticated()) { + return; + } + + ChromeIdentity* account_info = + AuthenticationServiceFactory::GetForBrowserState(browser_state_) + ->GetAuthenticatedIdentity(); + auto* signed_in_user_info = report->mutable_chrome_signed_in_user(); + signed_in_user_info->set_email( + base::SysNSStringToUTF8(account_info.userEmail)); + signed_in_user_info->set_obfudscated_gaia_id( + base::SysNSStringToUTF8(account_info.hashedGaiaID)); +} + +void ProfileReportGeneratorIOS::GetExtensionInfo( + enterprise_management::ChromeUserProfileInfo* report) { + // Extensions aren't supported on iOS. +} + +void ProfileReportGeneratorIOS::GetExtensionRequest( + enterprise_management::ChromeUserProfileInfo* report) { + // Extensions aren't supported on iOS. +} + +std::unique_ptr<policy::PolicyConversionsClient> +ProfileReportGeneratorIOS::MakePolicyConversionsClient() { + return std::make_unique<PolicyConversionsClientIOS>(browser_state_); +} + +policy::MachineLevelUserCloudPolicyManager* +ProfileReportGeneratorIOS::GetCloudPolicyManager() { + return GetApplicationContext() + ->GetBrowserPolicyConnector() + ->machine_level_user_cloud_policy_manager(); +} + +} // namespace enterprise_reporting
diff --git a/ios/chrome/browser/policy/reporting/report_generator_ios.h b/ios/chrome/browser/policy/reporting/report_generator_ios.h new file mode 100644 index 0000000..3ef85d2 --- /dev/null +++ b/ios/chrome/browser/policy/reporting/report_generator_ios.h
@@ -0,0 +1,29 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_POLICY_REPORTING_REPORT_GENERATOR_IOS_H_ +#define IOS_CHROME_BROWSER_POLICY_REPORTING_REPORT_GENERATOR_IOS_H_ + +#include "components/enterprise/browser/reporting/report_generator.h" + +namespace enterprise_reporting { + +/** + * iOS implementation of the report generator delegate. + */ +class ReportGeneratorIOS : public ReportGenerator::Delegate { + public: + ReportGeneratorIOS() = default; + ReportGeneratorIOS(const ReportGeneratorIOS&) = delete; + ReportGeneratorIOS& operator=(const ReportGeneratorIOS&) = delete; + ~ReportGeneratorIOS() override = default; + + // ReportGenerator::Delegate implementation. + void SetAndroidAppInfos( + ReportGenerator::ReportRequest* basic_request) override; +}; + +} // namespace enterprise_reporting + +#endif // IOS_CHROME_BROWSER_POLICY_REPORTING_REPORT_GENERATOR_IOS_H_
diff --git a/ios/chrome/browser/policy/reporting/report_generator_ios.mm b/ios/chrome/browser/policy/reporting/report_generator_ios.mm new file mode 100644 index 0000000..4a00eee --- /dev/null +++ b/ios/chrome/browser/policy/reporting/report_generator_ios.mm
@@ -0,0 +1,18 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "ios/chrome/browser/policy/reporting/report_generator_ios.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace enterprise_reporting { + +void ReportGeneratorIOS::SetAndroidAppInfos( + ReportGenerator::ReportRequest* basic_request) { + // Not used on iOS. +} + +} // namespace enterprise_reporting
diff --git a/ios/chrome/browser/policy/reporting/report_scheduler_ios.h b/ios/chrome/browser/policy/reporting/report_scheduler_ios.h new file mode 100644 index 0000000..823426c1 --- /dev/null +++ b/ios/chrome/browser/policy/reporting/report_scheduler_ios.h
@@ -0,0 +1,35 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_POLICY_REPORTING_REPORT_SCHEDULER_IOS_H_ +#define IOS_CHROME_BROWSER_POLICY_REPORTING_REPORT_SCHEDULER_IOS_H_ + +#include "components/enterprise/browser/reporting/report_scheduler.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace enterprise_reporting { + +// Desktop implementation of the ReportScheduler delegate. +class ReportSchedulerIOS : public ReportScheduler::Delegate { + public: + ReportSchedulerIOS(); + ReportSchedulerIOS(const ReportSchedulerIOS&) = delete; + ReportSchedulerIOS& operator=(const ReportSchedulerIOS&) = delete; + + ~ReportSchedulerIOS() override; + + // ReportScheduler::Delegate implementation. + PrefService* GetLocalState() override; + void StartWatchingUpdatesIfNeeded(base::Time last_upload, + base::TimeDelta upload_interval) override; + void StopWatchingUpdates() override; + void SaveLastUploadVersion() override; +}; + +} // namespace enterprise_reporting + +#endif // IOS_CHROME_BROWSER_POLICY_REPORTING_REPORT_SCHEDULER_IOS_H_
diff --git a/ios/chrome/browser/policy/reporting/report_scheduler_ios.mm b/ios/chrome/browser/policy/reporting/report_scheduler_ios.mm new file mode 100644 index 0000000..fc8f4b27 --- /dev/null +++ b/ios/chrome/browser/policy/reporting/report_scheduler_ios.mm
@@ -0,0 +1,37 @@ +// 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 "ios/chrome/browser/policy/reporting/report_scheduler_ios.h" + +#include "ios/chrome/browser/application_context.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace enterprise_reporting { + +ReportSchedulerIOS::ReportSchedulerIOS() = default; + +ReportSchedulerIOS::~ReportSchedulerIOS() = default; + +PrefService* ReportSchedulerIOS::GetLocalState() { + return GetApplicationContext()->GetLocalState(); +} + +void ReportSchedulerIOS::StartWatchingUpdatesIfNeeded( + base::Time last_upload, + base::TimeDelta upload_interval) { + // Not used on iOS because there is no in-app auto-update. +} + +void ReportSchedulerIOS::StopWatchingUpdates() { + // Not used on iOS because there is no in-app auto-update. +} + +void ReportSchedulerIOS::SaveLastUploadVersion() { + // Not used on iOS because there is no in-app auto-update. +} + +} // namespace enterprise_reporting
diff --git a/ios/chrome/browser/policy/reporting/reporting_delegate_factory_ios.mm b/ios/chrome/browser/policy/reporting/reporting_delegate_factory_ios.mm index 00d8957..4b9a34b 100644 --- a/ios/chrome/browser/policy/reporting/reporting_delegate_factory_ios.mm +++ b/ios/chrome/browser/policy/reporting/reporting_delegate_factory_ios.mm
@@ -4,6 +4,11 @@ #include "ios/chrome/browser/policy/reporting/reporting_delegate_factory_ios.h" +#include "ios/chrome/browser/policy/reporting/browser_report_generator_ios.h" +#include "ios/chrome/browser/policy/reporting/profile_report_generator_ios.h" +#include "ios/chrome/browser/policy/reporting/report_generator_ios.h" +#include "ios/chrome/browser/policy/reporting/report_scheduler_ios.h" + #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @@ -12,26 +17,22 @@ std::unique_ptr<BrowserReportGenerator::Delegate> ReportingDelegateFactoryIOS::GetBrowserReportGeneratorDelegate() { - // TODO(crbug.com/1066495): Finish iOS CBCM implementation. - return nullptr; + return std::make_unique<BrowserReportGeneratorIOS>(); } std::unique_ptr<ProfileReportGenerator::Delegate> ReportingDelegateFactoryIOS::GetProfileReportGeneratorDelegate() { - // TODO(crbug.com/1066495): Finish iOS CBCM implementation. - return nullptr; + return std::make_unique<ProfileReportGeneratorIOS>(); } std::unique_ptr<ReportGenerator::Delegate> ReportingDelegateFactoryIOS::GetReportGeneratorDelegate() { - // TODO(crbug.com/1066495): Finish iOS CBCM implementation. - return nullptr; + return std::make_unique<ReportGeneratorIOS>(); } std::unique_ptr<ReportScheduler::Delegate> ReportingDelegateFactoryIOS::GetReportSchedulerDelegate() { - // TODO(crbug.com/1066495): Finish iOS CBCM implementation. - return nullptr; + return std::make_unique<ReportSchedulerIOS>(); } } // namespace enterprise_reporting
diff --git a/ios/chrome/browser/reading_list/offline_page_tab_helper.mm b/ios/chrome/browser/reading_list/offline_page_tab_helper.mm index 6962a17..26acfe80 100644 --- a/ios/chrome/browser/reading_list/offline_page_tab_helper.mm +++ b/ios/chrome/browser/reading_list/offline_page_tab_helper.mm
@@ -224,12 +224,17 @@ void OfflinePageTabHelper::ReadingListModelBeingDeleted( const ReadingListModel* model) { DCHECK(reading_list_model_ == nullptr || reading_list_model_ == model); + + // Detach will nullify web_state_, this keeps it local a bit longer + // to allow removing user data below. + web::WebState* webState = web_state_; + Detach(); // The call to RemoveUserData cause the destruction of the current instance, // so nothing should be done after that point (this is like "delete this;"). // Unregistration as an observer happens in the destructor. - web_state_->RemoveUserData(UserDataKey()); + webState->RemoveUserData(UserDataKey()); } void OfflinePageTabHelper::PresentOfflinePageForOnlineUrl(const GURL& url) {
diff --git a/ios/chrome/browser/screenshot/screenshot_delegate_unittest.mm b/ios/chrome/browser/screenshot/screenshot_delegate_unittest.mm index e8f43be..7aa4e35 100644 --- a/ios/chrome/browser/screenshot/screenshot_delegate_unittest.mm +++ b/ios/chrome/browser/screenshot/screenshot_delegate_unittest.mm
@@ -45,7 +45,7 @@ // Tests that ScreenshotDelegate can be init with browserInterfaceProvider can // be set and that data can be generated from it. -TEST_F(ScreenshotDelegateTest, screenshotService) { +TEST_F(ScreenshotDelegateTest, ScreenshotService) { // Expected: Empty NSData. if (@available(iOS 13, *)) { auto web_state = std::make_unique<web::TestWebState>(); @@ -80,7 +80,7 @@ // Tests that when ScreenshotDelegate's browserInterfaceProvider has a nil // Browser screenshotService will return nil. -TEST_F(ScreenshotDelegateTest, nilBrowser) { +TEST_F(ScreenshotDelegateTest, NilBrowser) { // Expected: nil NSData. if (@available(iOS 13, *)) { // Add the StubBrowserInterface with no set Browser to @@ -104,7 +104,7 @@ // Tests that when ScreenshotDelegate's browserInterfaceProvider has a nil // WebSatate screenshotService will return nil. -TEST_F(ScreenshotDelegateTest, nilWebState) { +TEST_F(ScreenshotDelegateTest, NilWebState) { // Expected: nil NSData. if (@available(iOS 13, *)) { TestBrowser browser;
diff --git a/ios/chrome/browser/ui/activity_services/activity_scenario.h b/ios/chrome/browser/ui/activity_services/activity_scenario.h index 56702da..f41a87af 100644 --- a/ios/chrome/browser/ui/activity_services/activity_scenario.h +++ b/ios/chrome/browser/ui/activity_services/activity_scenario.h
@@ -14,8 +14,10 @@ HistoryEntry = 2, ReadingListEntry = 3, BookmarkEntry = 4, + MostVisitedEntry = 5, + RecentTabsEntry = 6, // Highest enumerator. Recommended by Histogram metrics best practices. - kMaxValue = BookmarkEntry + kMaxValue = RecentTabsEntry }; #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 d8bd253c..0df053e4 100644 --- a/ios/chrome/browser/ui/activity_services/activity_service_histograms.mm +++ b/ios/chrome/browser/ui/activity_services/activity_service_histograms.mm
@@ -26,6 +26,10 @@ "Mobile.Share.ReadingListEntry.Actions"; const char kShareBookmarkEntryActionsHistogram[] = "Mobile.Share.BookmarkEntry.Actions"; +const char kShareMostVisitedEntryActionsHistogram[] = + "Mobile.Share.MostVisitedEntry.Actions"; +const char kShareRecentTabsEntryActionsHistogram[] = + "Mobile.Share.RecentTabsEntry.Actions"; // Enum representing an aggregation of the |ActivityType| enum values in a way // that is relevant for metric collection. Current values should not @@ -143,6 +147,12 @@ case ActivityScenario::BookmarkEntry: histogramName = kShareBookmarkEntryActionsHistogram; break; + case ActivityScenario::MostVisitedEntry: + histogramName = kShareMostVisitedEntryActionsHistogram; + break; + case ActivityScenario::RecentTabsEntry: + histogramName = kShareRecentTabsEntryActionsHistogram; + break; } base::UmaHistogramEnumeration(histogramName, actionType); }
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index dfcc64a3..bd39910 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -60,6 +60,7 @@ "//ios/chrome/browser/signin", "//ios/chrome/browser/tabs", "//ios/chrome/browser/ui:feature_flags", + "//ios/chrome/browser/ui/activity_services", "//ios/chrome/browser/ui/alert_coordinator", "//ios/chrome/browser/ui/collection_view/cells", "//ios/chrome/browser/ui/commands", @@ -77,6 +78,7 @@ "//ios/chrome/browser/ui/overscroll_actions", "//ios/chrome/browser/ui/reading_list", "//ios/chrome/browser/ui/settings/utils:utils", + "//ios/chrome/browser/ui/sharing", "//ios/chrome/browser/ui/toolbar/public", "//ios/chrome/browser/ui/util", "//ios/chrome/browser/ui/util:multiwindow_util",
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 0623e19..576373e4 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -29,6 +29,7 @@ #import "ios/chrome/browser/signin/authentication_service.h" #import "ios/chrome/browser/signin/authentication_service_factory.h" #include "ios/chrome/browser/signin/identity_manager_factory.h" +#import "ios/chrome/browser/ui/activity_services/activity_params.h" #import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" @@ -58,6 +59,7 @@ #import "ios/chrome/browser/ui/ntp/notification_promo_whats_new.h" #import "ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h" #import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h" +#import "ios/chrome/browser/ui/sharing/sharing_coordinator.h" #import "ios/chrome/browser/ui/util/multi_window_support.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/url_loading/url_loading_browser_agent.h" @@ -109,6 +111,8 @@ @property(nonatomic) CGFloat discoverFeedHeight; // Authentication Service for the user's signed-in state. @property(nonatomic, assign) AuthenticationService* authService; +// Coordinator in charge of handling sharing use cases. +@property(nonatomic, strong) SharingCoordinator* sharingCoordinator; @end @@ -175,6 +179,7 @@ FakeboxFocuser>>(self.browser->GetCommandDispatcher()); self.headerController.commandHandler = self.NTPMediator; self.headerController.delegate = self.NTPMediator; + self.headerController.readingListModel = ReadingListModelFactory::GetForBrowserState( self.browser->GetBrowserState()); @@ -294,6 +299,8 @@ self.NTPMediator = nil; [self.contentSuggestionsMediator disconnect]; self.contentSuggestionsMediator = nil; + [self.sharingCoordinator stop]; + self.sharingCoordinator = nil; self.headerController = nil; _visible = NO; } @@ -532,7 +539,9 @@ #pragma mark - ContentSuggestionsMenuProvider - (UIContextMenuConfiguration*)contextMenuConfigurationForItem: - (ContentSuggestionsMostVisitedItem*)item API_AVAILABLE(ios(13.0)) { + (ContentSuggestionsMostVisitedItem*)item + fromView:(UIView*)view + API_AVAILABLE(ios(13.0)) { __weak __typeof(self) weakSelf = self; UIContextMenuActionProvider actionProvider = @@ -585,6 +594,12 @@ [menuElements addObject:[actionFactory actionToCopyURL:item.URL]]; + [menuElements addObject:[actionFactory actionToShareWithBlock:^{ + [weakSelf shareURL:item.URL + title:item.title + fromView:view]; + }]]; + [menuElements addObject:[actionFactory actionToRemoveWithBlock:^{ [weakSelf.NTPMediator removeMostVisited:item]; }]]; @@ -620,4 +635,21 @@ return discoverFeed; } +// 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::MostVisitedEntry]; + self.sharingCoordinator = + [[SharingCoordinator alloc] initWithBaseViewController:self.viewController + browser:self.browser + params:params + originView:view]; + [self.sharingCoordinator start]; +} + @end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm index df143d7..319c2994 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -40,12 +40,24 @@ using base::UserMetricsAction; +namespace { + +const NSString* kScribbleFakeboxElementId = @"fakebox"; + +} // namespace + #if defined(__IPHONE_13_4) @interface ContentSuggestionsHeaderViewController (Pointer) < UIPointerInteractionDelegate> @end #endif // defined(__IPHONE_13_4) +#if defined(__IPHONE_14_0) +@interface ContentSuggestionsHeaderViewController (Scribble) < + UIIndirectScribbleInteractionDelegate> +@end +#endif // defined(__IPHONE14_0) + @interface ContentSuggestionsHeaderViewController () < UserAccountImageUpdateDelegate> @@ -314,6 +326,14 @@ [self.headerView addViewsToSearchField:self.fakeOmnibox]; +#if defined(__IPHONE_14_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0 + if (@available(iOS 14, *)) { + UIIndirectScribbleInteraction* scribbleInteraction = + [[UIIndirectScribbleInteraction alloc] initWithDelegate:self]; + [self.fakeOmnibox addInteraction:scribbleInteraction]; + } +#endif // defined(__IPHONE_14_0) + [self.headerView.voiceSearchButton addTarget:self action:@selector(loadVoiceSearch:) forControlEvents:UIControlEventTouchUpInside]; @@ -574,6 +594,61 @@ return self.parentViewController.view.safeAreaInsets.top; } +#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(@[ kScribbleFakeboxElementId ]); +} + +- (BOOL)indirectScribbleInteraction:(UIIndirectScribbleInteraction*)interaction + isElementFocused: + (UIScribbleElementIdentifier)elementIdentifier + API_AVAILABLE(ios(14.0)) { + DCHECK(elementIdentifier == kScribbleFakeboxElementId); + return self.toolbarDelegate.fakeboxScribbleForwardingTarget.isFirstResponder; +} + +- (CGRect) + indirectScribbleInteraction:(UIIndirectScribbleInteraction*)interaction + frameForElement:(UIScribbleElementIdentifier)elementIdentifier + API_AVAILABLE(ios(14.0)) { + DCHECK(elementIdentifier == kScribbleFakeboxElementId); + + // Imitate the entire location bar being scribblable. + return interaction.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.toolbarDelegate.fakeboxScribbleForwardingTarget.isFirstResponder) { + [self.toolbarDelegate.fakeboxScribbleForwardingTarget becomeFirstResponder]; + } + + completion(self.toolbarDelegate.fakeboxScribbleForwardingTarget); +} + +- (BOOL)indirectScribbleInteraction:(UIIndirectScribbleInteraction*)interaction + shouldDelayFocusForElement: + (UIScribbleElementIdentifier)elementIdentifier + API_AVAILABLE(ios(14.0)) { + DCHECK(elementIdentifier == kScribbleFakeboxElementId); + return YES; +} + +#endif // defined(__IPHONE_14_0) + #pragma mark - LogoAnimationControllerOwnerOwner - (id<LogoAnimationControllerOwner>)logoAnimationControllerOwner {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_menu_provider.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_menu_provider.h index 042c1af..fa610d9 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_menu_provider.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_menu_provider.h
@@ -14,7 +14,9 @@ // Creates a context menu configuration instance for the given |item|, which is // represented on the UI by |view|. - (UIContextMenuConfiguration*)contextMenuConfigurationForItem: - (ContentSuggestionsMostVisitedItem*)item API_AVAILABLE(ios(13.0)); + (ContentSuggestionsMostVisitedItem*)item + fromView:(UIView*)view + API_AVAILABLE(ios(13.0)); @end
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 0b89460..241901ad 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
@@ -496,7 +496,9 @@ base::mac::ObjCCastStrict<ContentSuggestionsMostVisitedItem>(item); return [self.menuProvider - contextMenuConfigurationForItem:contentSuggestionsItem]; + contextMenuConfigurationForItem:contentSuggestionsItem + fromView:[self.collectionView + cellForItemAtIndexPath:indexPath]]; } #pragma mark - UICollectionViewDataSource
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h index c8758c4..43fd16c9 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h +++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.h
@@ -45,6 +45,9 @@ // Returns the edit view animatee. - (id<EditViewAnimatee>)editViewAnimatee; +// Target to forward omnibox-related scribble events to. +- (UIResponder<UITextInput>*)omniboxScribbleForwardingTarget; + @end #endif // IOS_CHROME_BROWSER_UI_LOCATION_BAR_LOCATION_BAR_COORDINATOR_H_
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 8c5d3b2..6baecc20 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_coordinator.mm
@@ -262,6 +262,10 @@ return self.omniboxCoordinator.animatee; } +- (UIResponder<UITextInput>*)omniboxScribbleForwardingTarget { + return self.omniboxCoordinator.scribbleInput; +} + #pragma mark - LoadQueryCommands - (void)loadQuery:(NSString*)query immediately:(BOOL)immediately { @@ -373,10 +377,6 @@ return [self.delegate locationBarModel]; } -- (UIResponder<UITextInput>*)scribbleForwardingTarget { - return self.omniboxCoordinator.scribbleInput; -} - - (void)locationBarRequestScribbleTargetFocus { [self.omniboxCoordinator focusOmniboxForScribble]; }
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.h b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.h index 9c4f046..1a9600b 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.h +++ b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.h
@@ -49,6 +49,9 @@ // appropriately. - (void)enableTrailingButton:(BOOL)enabled; +// The view containing the location label, and (sometimes) the location image +// view. +@property(nonatomic, strong) UIView* locationContainerView; // The tappable button representing the location bar. @property(nonatomic, strong) UIButton* locationButton; // The label displaying the current location URL.
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm index 868a0ba0..95da842 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
@@ -47,10 +47,6 @@ // The image view displaying the current location icon (i.e. http[s] status). @property(nonatomic, strong) UIImageView* locationIconImageView; -// The view containing the location label, and (sometimes) the location image -// view. -@property(nonatomic, strong) UIView* locationContainerView; - // Leading constraint for locationContainerView when there is no BadgeView to // its left. @property(nonatomic, strong)
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 16d06a1..8f811a09 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
@@ -31,7 +31,7 @@ - (void)locationBarCopyTapped; // Returns the target that location bar scribble events should be forwarded to. -- (UIResponder<UITextInput>*)scribbleForwardingTarget; +- (UIResponder<UITextInput>*)omniboxScribbleForwardingTarget; // Request the scribble target to be focused. - (void)locationBarRequestScribbleTargetFocus;
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 f54a3df..5652580 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
@@ -273,8 +273,23 @@ progress <= kFullscreenProgressBadgeViewThreshold; [self.locationBarSteadyView setFullScreenCollapsedMode:badgeViewShouldCollapse]; - self.locationBarSteadyView.transform = + + CGAffineTransform transform = CGAffineTransformMakeScale(scaleValue, scaleValue); + self.locationBarSteadyView.locationContainerView.transform = transform; + self.locationBarSteadyView.trailingButton.transform = transform; + + UIView* badgeView = self.locationBarSteadyView.badgeView; + badgeView.transform = transform; + // The translation value is added in order to move badgeView for |dx| created + // by the difference of the separate animation of the locationbar's views. + if (badgeViewShouldCollapse) { + CGFloat dx = + self.locationBarSteadyView.locationContainerView.frame.origin.x - + badgeView.frame.origin.x - badgeView.frame.size.width; + badgeView.transform = + CGAffineTransformTranslate(badgeView.transform, dx, 0); + } } - (void)updateForFullscreenEnabled:(BOOL)enabled { @@ -422,7 +437,7 @@ (UIScribbleElementIdentifier)elementIdentifier API_AVAILABLE(ios(14.0)) { DCHECK(elementIdentifier == kScribbleOmniboxElementId); - return self.delegate.scribbleForwardingTarget.isFirstResponder; + return self.delegate.omniboxScribbleForwardingTarget.isFirstResponder; } - (CGRect) @@ -442,11 +457,11 @@ completion: (void (^)(UIResponder<UITextInput>* focusedInput)) completion API_AVAILABLE(ios(14.0)) { - if (!self.delegate.scribbleForwardingTarget.isFirstResponder) { + if (!self.delegate.omniboxScribbleForwardingTarget.isFirstResponder) { [self.delegate locationBarRequestScribbleTargetFocus]; } - completion(self.delegate.scribbleForwardingTarget); + completion(self.delegate.omniboxScribbleForwardingTarget); } #endif // defined(__IPHONE_14_0)
diff --git a/ios/chrome/browser/ui/main/BUILD.gn b/ios/chrome/browser/ui/main/BUILD.gn index 20cd3e2..5fe967b5 100644 --- a/ios/chrome/browser/ui/main/BUILD.gn +++ b/ios/chrome/browser/ui/main/BUILD.gn
@@ -95,6 +95,7 @@ "//ios/chrome/browser/ui/util:multiwindow_util", "//ios/chrome/browser/url_loading", "//ios/chrome/browser/web_state_list", + "//ios/chrome/browser/web_state_list:agents", "//ios/chrome/browser/window_activities", "//ios/chrome/common/ui/util", "//ios/public/provider/chrome/browser",
diff --git a/ios/chrome/browser/ui/main/scene_controller.h b/ios/chrome/browser/ui/main/scene_controller.h index ebe9b87..eb260ff9 100644 --- a/ios/chrome/browser/ui/main/scene_controller.h +++ b/ios/chrome/browser/ui/main/scene_controller.h
@@ -13,7 +13,6 @@ #import "ios/chrome/browser/ui/main/connection_information.h" #import "ios/chrome/browser/ui/main/scene_controller_guts.h" #import "ios/chrome/browser/ui/main/scene_state.h" -#import "ios/chrome/browser/ui/tab_grid/tab_switcher.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" @protocol MainControllerGuts; @@ -21,7 +20,6 @@ // The controller object for a scene. Reacts to scene state changes. @interface SceneController : NSObject <SceneStateObserver, ApplicationCommands, - TabSwitcherDelegate, TabSwitching, SceneControllerGuts, ConnectionInformation,
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index e8b7f58c..b1e8bde7 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -64,6 +64,7 @@ #import "ios/chrome/browser/ui/scoped_ui_blocker/scoped_ui_blocker.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #include "ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h" +#include "ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_delegate.h" #import "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/multi_window_support.h" #import "ios/chrome/browser/ui/util/top_view_controller.h" @@ -71,6 +72,7 @@ #import "ios/chrome/browser/url_loading/scene_url_loading_service.h" #import "ios/chrome/browser/url_loading/url_loading_browser_agent.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" +#import "ios/chrome/browser/web_state_list/tab_insertion_browser_agent.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" #import "ios/chrome/browser/window_activities/window_activity_helpers.h" @@ -128,6 +130,7 @@ UserFeedbackDataSource, SettingsNavigationControllerDelegate, SceneURLLoadingServiceDelegate, + TabGridCoordinatorDelegate, WebStateListObserving> { std::unique_ptr<WebStateListObserverBridge> _webStateListForwardingObserver; } @@ -177,9 +180,6 @@ @property(nonatomic, readwrite) NTPTabOpeningPostOpeningAction NTPActionAfterTabSwitcherDismissal; -// TabSwitcher object -- the tab grid. -@property(nonatomic, strong, readonly) id<TabSwitcher> tabSwitcher; - // The main coordinator, lazily created the first time it is accessed. Manages // the main view controller. This property should not be accessed before the // browser has started up to the FOREGROUND stage. @@ -238,12 +238,12 @@ - (TabGridCoordinator*)mainCoordinator { if (!_mainCoordinator) { // Lazily create the main coordinator. - TabGridCoordinator* tabGridCoordinator = - [[TabGridCoordinator alloc] initWithWindow:self.sceneState.window - applicationCommandEndpoint:self - browsingDataCommandEndpoint:self.mainController]; - tabGridCoordinator.regularBrowser = self.mainInterface.browser; - tabGridCoordinator.incognitoBrowser = self.incognitoInterface.browser; + TabGridCoordinator* tabGridCoordinator = [[TabGridCoordinator alloc] + initWithWindow:self.sceneState.window + applicationCommandEndpoint:self + browsingDataCommandEndpoint:self.mainController + regularBrowser:self.mainInterface.browser + incognitoBrowser:self.incognitoInterface.browser]; _mainCoordinator = tabGridCoordinator; } return _mainCoordinator; @@ -270,10 +270,6 @@ self.signinCoordinator.isSettingsViewPresented; } -- (id<TabSwitcher>)tabSwitcher { - return self.mainCoordinator; -} - #pragma mark - SceneStateObserver - (void)sceneState:(SceneState*)sceneState @@ -588,11 +584,7 @@ // Lazy init of mainCoordinator. [self.mainCoordinator start]; - // Call -restoreInternalState so that the grid shows the correct panel. - [self.tabSwitcher - restoreInternalStateWithMainBrowser:self.mainInterface.browser - otrBrowser:self.incognitoInterface.browser - activeBrowser:self.currentInterface.browser]; + [self.mainCoordinator setActivePage:[self activePage]]; // Decide if the First Run UI needs to run. const bool firstRun = ShouldPresentFirstRunExperience(); @@ -818,7 +810,7 @@ snapshotResult); }); } - [self.mainCoordinator prepareToShowTabSwitcher:self.tabSwitcher]; + [self.mainCoordinator prepareToShowTabGrid]; } - (void)displayTabSwitcher { @@ -1241,16 +1233,16 @@ self.mainInterface.browser->GetCommandDispatcher()); } -#pragma mark - TabSwitcherDelegate +#pragma mark - TabGridCoordinatorDelegate -- (void)tabSwitcher:(id<TabSwitcher>)tabSwitcher +- (void)tabGrid:(TabGridCoordinator*)tabGrid shouldFinishWithBrowser:(Browser*)browser focusOmnibox:(BOOL)focusOmnibox { [self beginDismissingTabSwitcherWithCurrentBrowser:browser focusOmnibox:focusOmnibox]; } -- (void)tabSwitcherDismissTransitionDidEnd:(id<TabSwitcher>)tabSwitcher { +- (void)tabGridDismissTransitionDidEnd:(TabGridCoordinator*)tabGrid { [self finishDismissingTabSwitcher]; } @@ -1367,18 +1359,15 @@ #pragma mark - TabSwitching - (BOOL)openNewTabFromTabSwitcher { - if (!self.tabSwitcher) + if (!self.mainCoordinator) return NO; UrlLoadParams urlLoadParams = UrlLoadParams::InNewTab(GURL(kChromeUINewTabURL)); urlLoadParams.web_params.transition_type = ui::PAGE_TRANSITION_TYPED; - Browser* mainBrowser = self.mainInterface.browser; - WebStateList* webStateList = mainBrowser->GetWebStateList(); - [self.tabSwitcher dismissWithNewTabAnimationToBrowser:mainBrowser - withUrlLoadParams:urlLoadParams - atIndex:webStateList->count()]; + [self addANewTabAndPresentBrowser:self.mainInterface.browser + withURLLoadParams:urlLoadParams]; return YES; } @@ -1495,13 +1484,13 @@ // If the tabSwitcher is contained, check if the parent container is // presenting another view controller. - if ([[self.tabSwitcher viewController] + if ([self.mainCoordinator.baseViewController .parentViewController presentedViewController]) { return NO; } // Check if the tabSwitcher is directly presenting another view controller. - if ([self.tabSwitcher viewController].presentedViewController) { + if (self.mainCoordinator.baseViewController.presentedViewController) { return NO; } @@ -1693,7 +1682,6 @@ targetMode == ApplicationMode::NORMAL ? self.interfaceProvider.mainInterface : self.interfaceProvider.incognitoInterface; - NSUInteger tabIndex = NSNotFound; ProceduralBlock startupCompletion = [self completionBlockForTriggeringAction:[self.startupParameters postOpeningAction]]; @@ -1734,10 +1722,9 @@ self.NTPActionAfterTabSwitcherDismissal = [self.startupParameters postOpeningAction]; [self setStartupParameters:nil]; - [self.tabSwitcher - dismissWithNewTabAnimationToBrowser:targetInterface.browser - withUrlLoadParams:urlLoadParams - atIndex:tabIndex]; + + [self addANewTabAndPresentBrowser:targetInterface.browser + withURLLoadParams:urlLoadParams]; // In this particular usage, there should be no postOpeningAction, // as triggering voice search while there are multiple windows opened is probably // a bad idea both technically and as a user experience. @@ -1937,7 +1924,7 @@ // TODO(crbug.com/754642): Implement TopPresentedViewControllerFrom() // privately. return top_view_controller::TopPresentedViewControllerFrom( - self.mainCoordinator.viewController); + self.mainCoordinator.baseViewController); } // Interrupts the sign-in coordinator actions and dismisses its views either @@ -2073,17 +2060,12 @@ } - (void)showTabSwitcher { - DCHECK(self.tabSwitcher); - // Tab switcher implementations may need to rebuild state before being - // displayed. - [self.tabSwitcher - restoreInternalStateWithMainBrowser:self.mainInterface.browser - otrBrowser:self.incognitoInterface.browser - activeBrowser:self.currentInterface.browser]; + DCHECK(self.mainCoordinator); + [self.mainCoordinator setActivePage:[self activePage]]; self.tabSwitcherIsActive = YES; - [self.tabSwitcher setDelegate:self]; + self.mainCoordinator.delegate = self; - [self.mainCoordinator showTabSwitcher:self.tabSwitcher]; + [self.mainCoordinator showTabGrid]; } - (void)openURLContexts:(NSSet<UIOpenURLContext*>*)URLContexts @@ -2145,6 +2127,25 @@ return targetInterface; } +#pragma mark - TabGrid helpers + +// Returns the page that should be active in the TabGrid. +- (TabGridPage)activePage { + if (self.currentInterface.browser == self.incognitoInterface.browser) + return TabGridPageIncognitoTabs; + return TabGridPageRegularTabs; +} + +// Adds a new tab to the |browser| based on |urlLoadParams| and then presents +// it. +- (void)addANewTabAndPresentBrowser:(Browser*)browser + withURLLoadParams:(const UrlLoadParams&)urlLoadParams { + TabInsertionBrowserAgent::FromBrowser(browser)->InsertWebState( + urlLoadParams.web_params, nil, false, browser->GetWebStateList()->count(), + false); + [self beginDismissingTabSwitcherWithCurrentBrowser:browser focusOmnibox:NO]; +} + #pragma mark - Handling of destroying the incognito BrowserState // The incognito BrowserState should be closed when the last incognito tab is @@ -2224,9 +2225,9 @@ } - (void)willDestroyIncognitoBrowserState { - // Clear the Incognito Browser and notify the _tabSwitcher that its otrBrowser + // Clear the Incognito Browser and notify the TabGrid that its otrBrowser // will be destroyed. - [self.tabSwitcher setOtrBrowser:nil]; + self.mainCoordinator.incognitoBrowser = nil; if (base::FeatureList::IsEnabled(kLogBreadcrumbs)) { BreadcrumbManagerBrowserAgent::FromBrowser(self.incognitoInterface.browser) @@ -2253,7 +2254,7 @@ } // Always set the new otr Browser for the tablet or grid switcher. - // Notify the _tabSwitcher with the new Incognito Browser. - [self.tabSwitcher setOtrBrowser:self.incognitoInterface.browser]; + // Notify the TabGrid with the new Incognito Browser. + self.mainCoordinator.incognitoBrowser = self.incognitoInterface.browser; } @end
diff --git a/ios/chrome/browser/ui/main/scene_controller_testing.h b/ios/chrome/browser/ui/main/scene_controller_testing.h index e8522db..9376b273 100644 --- a/ios/chrome/browser/ui/main/scene_controller_testing.h +++ b/ios/chrome/browser/ui/main/scene_controller_testing.h
@@ -7,16 +7,18 @@ #import "ios/chrome/browser/procedural_block_types.h" -@protocol TabSwitcher; +class Browser; +struct UrlLoadParams; // Methods exposed for testing. This is terrible and should be rewritten. @interface SceneController () - (void)showFirstRunUI; -- (void)setTabSwitcher:(id<TabSwitcher>)switcher; -- (id<TabSwitcher>)tabSwitcher; - (BOOL)isTabSwitcherActive; +- (void)addANewTabAndPresentBrowser:(Browser*)browser + withURLLoadParams:(const UrlLoadParams&)urlLoadParams; + // Dismisses all modal dialogs, excluding the omnibox if |dismissOmnibox| is // NO, then call |completion|. - (void)dismissModalDialogsWithCompletion:(ProceduralBlock)completion
diff --git a/ios/chrome/browser/ui/menu/action_factory.mm b/ios/chrome/browser/ui/menu/action_factory.mm index 13bb8ee..822b6f5 100644 --- a/ios/chrome/browser/ui/menu/action_factory.mm +++ b/ios/chrome/browser/ui/menu/action_factory.mm
@@ -176,7 +176,7 @@ UIAction* action = [self actionWithTitle:l10n_util::GetNSString( IDS_IOS_RECENT_TABS_HIDE_MENU_OPTION) - image:nil + image:[UIImage imageNamed:@"remove"] type:MenuActionType::Hide block:block]; action.attributes = UIMenuElementAttributesDestructive;
diff --git a/ios/chrome/browser/ui/menu/action_factory_unittest.mm b/ios/chrome/browser/ui/menu/action_factory_unittest.mm index de02bf6a..e82c646 100644 --- a/ios/chrome/browser/ui/menu/action_factory_unittest.mm +++ b/ios/chrome/browser/ui/menu/action_factory_unittest.mm
@@ -284,6 +284,7 @@ [[ActionFactory alloc] initWithBrowser:test_browser_.get() scenario:kTestMenuScenario]; + UIImage* expectedImage = [UIImage imageNamed:@"remove"]; NSString* expectedTitle = l10n_util::GetNSString(IDS_IOS_RECENT_TABS_HIDE_MENU_OPTION); @@ -291,7 +292,7 @@ }]; EXPECT_TRUE([expectedTitle isEqualToString:action.title]); - EXPECT_EQ(nil, action.image); + EXPECT_EQ(expectedImage, action.image); } }
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h b/ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h index e2ac4d9..9e9cf32 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h +++ b/ios/chrome/browser/ui/ntp/new_tab_page_controller_delegate.h
@@ -9,6 +9,10 @@ @protocol NewTabPageControllerDelegate // Sets the toolbar location bar alpha and vertical offset based on |progress|. - (void)setScrollProgressForTabletOmnibox:(CGFloat)progress; + +// The target for scribble events as forwarded by the NTP fakebox. +- (UIResponder<UITextInput>*)fakeboxScribbleForwardingTarget; + @end #endif // IOS_CHROME_BROWSER_UI_NTP_NEW_TAB_PAGE_CONTROLLER_PROTOCOL_H_
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm index 732cd252..a691a20 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -77,6 +77,7 @@ browser:self.browser]; self.contentSuggestionsCoordinator.webState = self.webState; self.contentSuggestionsCoordinator.toolbarDelegate = self.toolbarDelegate; + [self.contentSuggestionsCoordinator start]; base::RecordAction(base::UserMetricsAction("MobileNTPShowMostVisited")); }
diff --git a/ios/chrome/browser/ui/recent_tabs/BUILD.gn b/ios/chrome/browser/ui/recent_tabs/BUILD.gn index e1525a07..51c8c46 100644 --- a/ios/chrome/browser/ui/recent_tabs/BUILD.gn +++ b/ios/chrome/browser/ui/recent_tabs/BUILD.gn
@@ -28,10 +28,12 @@ "//ios/chrome/browser/sessions", "//ios/chrome/browser/signin", "//ios/chrome/browser/sync", + "//ios/chrome/browser/ui/activity_services", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/menu", "//ios/chrome/browser/ui/ntp", + "//ios/chrome/browser/ui/sharing", "//ios/chrome/browser/ui/table_view", "//ios/chrome/browser/ui/table_view:feature_flags", "//ios/chrome/browser/ui/util",
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 90d51bf..5a73ee43 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.mm
@@ -11,6 +11,7 @@ #include "base/metrics/user_metrics_action.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/main/browser.h" +#import "ios/chrome/browser/ui/activity_services/activity_params.h" #include "ios/chrome/browser/ui/commands/application_commands.h" #include "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/menu/action_factory.h" @@ -21,6 +22,7 @@ #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/sharing/sharing_coordinator.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" @@ -50,6 +52,8 @@ @property(nonatomic, strong) RecentTabsTableViewController* recentTabsTableViewController; +@property(nonatomic, strong) SharingCoordinator* sharingCoordinator; + @end @implementation RecentTabsCoordinator @@ -160,6 +164,23 @@ [self openAllTabsFromSession:session]; } +// 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::RecentTabsEntry]; + self.sharingCoordinator = [[SharingCoordinator alloc] + initWithBaseViewController:self.recentTabsTableViewController + browser:self.browser + params:params + originView:view]; + [self.sharingCoordinator start]; +} + #pragma mark - RecentTabsPresentationDelegate - (void)openAllTabsFromSession:(const synced_sessions::DistantSession*)session { @@ -208,7 +229,9 @@ #pragma mark - RecentTabsMenuProvider - (UIContextMenuConfiguration*)contextMenuConfigurationForItem: - (TableViewURLItem*)item API_AVAILABLE(ios(13.0)) { + (TableViewURLItem*)item + fromView:(UIView*)view + API_AVAILABLE(ios(13.0)) { __weak __typeof(self) weakSelf = self; UIContextMenuActionProvider actionProvider = ^( @@ -254,6 +277,12 @@ [menuElements addObject:[actionFactory actionToCopyURL:item.URL]]; + [menuElements addObject:[actionFactory actionToShareWithBlock:^{ + [strongSelf shareURL:item.URL + title:item.title + fromView:view]; + }]]; + return [UIMenu menuWithTitle:@"" children:menuElements]; };
diff --git a/ios/chrome/browser/ui/recent_tabs/recent_tabs_menu_provider.h b/ios/chrome/browser/ui/recent_tabs/recent_tabs_menu_provider.h index 185db46..4020cedc 100644 --- a/ios/chrome/browser/ui/recent_tabs/recent_tabs_menu_provider.h +++ b/ios/chrome/browser/ui/recent_tabs/recent_tabs_menu_provider.h
@@ -5,14 +5,19 @@ #ifndef IOS_CHROME_BROWSER_UI_RECENT_TABS_RECENT_TABS_MENU_PROVIDER_H_ #define IOS_CHROME_BROWSER_UI_RECENT_TABS_RECENT_TABS_MENU_PROVIDER_H_ +#import <UIKit/UIKit.h> + @class TableViewURLItem; // Protocol for instances that will provide menus to RecentTabs components. @protocol RecentTabsMenuProvider -// Creates a context menu configuration instance for the given |item|. +// Creates a context menu configuration instance for the given |item| and its +// associated |view|. - (UIContextMenuConfiguration*)contextMenuConfigurationForItem: - (TableViewURLItem*)item API_AVAILABLE(ios(13.0)); + (TableViewURLItem*)item + fromView:(UIView*)view + API_AVAILABLE(ios(13.0)); // Creates a context menu configuration instance for the header of the given // |sectionIdentifier|.
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 182567b67..b5e49cb2f 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
@@ -929,7 +929,10 @@ TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath]; TableViewURLItem* URLItem = base::mac::ObjCCastStrict<TableViewURLItem>(item); - return [self.menuProvider contextMenuConfigurationForItem:URLItem]; + return [self.menuProvider + contextMenuConfigurationForItem:URLItem + fromView:[tableView + cellForRowAtIndexPath:indexPath]]; } #pragma mark - UIContextMenuInteractionDelegate
diff --git a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm index 5574681..eccaf2c 100644 --- a/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm +++ b/ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.mm
@@ -148,7 +148,8 @@ browser:self.browser title:nil message:message - barButtonItem:nil]; + barButtonItem:self.viewController.navigationItem + .rightBarButtonItem]; __weak __typeof(self) weakSelf = self; @@ -177,7 +178,8 @@ browser:self.browser title:nil message:message - barButtonItem:nil]; + barButtonItem:self.viewController.navigationItem + .rightBarButtonItem]; __weak __typeof(self) weakSelf = self;
diff --git a/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm b/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm index bb651e3..c61923b3 100644 --- a/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm +++ b/ios/chrome/browser/ui/settings/password/password_issues_coordinator.mm
@@ -6,6 +6,8 @@ #include "base/mac/foundation_util.h" #import "ios/chrome/browser/main/browser.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" +#import "ios/chrome/browser/ui/commands/command_dispatcher.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator.h" #import "ios/chrome/browser/ui/settings/password/password_details/password_details_coordinator_delegate.h" #import "ios/chrome/browser/ui/settings/password/password_issue_with_form.h" @@ -52,6 +54,8 @@ if (self) { _baseNavigationController = navigationController; _manager = manager; + _dispatcher = HandlerForProtocol(self.browser->GetCommandDispatcher(), + ApplicationCommands); } return self; }
diff --git a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm index 5666765f..1c289c8 100644 --- a/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/password/passwords_table_view_controller.mm
@@ -716,12 +716,18 @@ - (void)setPasswordCheckUIState:(PasswordCheckUIState)state { _passwordCheckState = state; - if (_checkForProblemsItem) { - [self updatePasswordCheckButtonWithState:state]; - [self reconfigureCellsForItems:@[ _checkForProblemsItem ]]; + [self updatePasswordCheckButtonWithState:state]; + [self updatePasswordCheckStatusLabelWithState:state]; + + // During searching Password Check section is hidden so cells should not be + // reconfigured. + if (self.navigationItem.searchController.active) { + return; } + + if (_checkForProblemsItem) + [self reconfigureCellsForItems:@[ _checkForProblemsItem ]]; if (_passwordProblemsItem) { - [self updatePasswordCheckStatusLabelWithState:state]; [self reconfigureCellsForItems:@[ _passwordProblemsItem ]]; } } @@ -800,9 +806,15 @@ - (void)willPresentSearchController:(UISearchController*)searchController { [self showScrim]; - // Remove save passwords switch section. + // Remove save passwords switch section and password check section. [self performBatchTableViewUpdates:^{ + if (base::FeatureList::IsEnabled( + password_manager::features::kPasswordCheck)) { + [self clearSectionWithIdentifier:SectionIdentifierPasswordCheck + withRowAnimation:UITableViewRowAnimationTop]; + } + [self clearSectionWithIdentifier:SectionIdentifierSavePasswordsSwitch withRowAnimation:UITableViewRowAnimationTop]; } @@ -829,11 +841,34 @@ [model addItem:_managedSavePasswordItem toSectionWithIdentifier:SectionIdentifierSavePasswordsSwitch]; } + NSInteger switchSection = [model + sectionForSectionIdentifier:SectionIdentifierSavePasswordsSwitch]; + NSMutableArray<NSIndexPath*>* rowsIndexPaths = [NSMutableArray + arrayWithObjects:[NSIndexPath indexPathForRow:0 + inSection:switchSection], + nil]; - [self.tableView - insertRowsAtIndexPaths:@[ [NSIndexPath indexPathForRow:0 - inSection:0] ] - withRowAnimation:UITableViewRowAnimationTop]; + if (base::FeatureList::IsEnabled( + password_manager::features::kPasswordCheck)) { + [model insertSectionWithIdentifier:SectionIdentifierPasswordCheck + atIndex:1]; + NSInteger checkSection = [model + sectionForSectionIdentifier:SectionIdentifierPasswordCheck]; + + [self.tableView insertSections:[NSIndexSet indexSetWithIndex:1] + withRowAnimation:UITableViewRowAnimationTop]; + [model addItem:_passwordProblemsItem + toSectionWithIdentifier:SectionIdentifierPasswordCheck]; + [model addItem:_checkForProblemsItem + toSectionWithIdentifier:SectionIdentifierPasswordCheck]; + [rowsIndexPaths addObject:[NSIndexPath indexPathForRow:0 + inSection:checkSection]]; + [rowsIndexPaths addObject:[NSIndexPath indexPathForRow:1 + inSection:checkSection]]; + } + + [self.tableView insertRowsAtIndexPaths:rowsIndexPaths + withRowAnimation:UITableViewRowAnimationTop]; } completion:nil]; } @@ -1282,7 +1317,6 @@ browser:_browser passwordCheckManager:_passwordCheck.get()]; _passwordIssuesCoordinator.delegate = self; - _passwordIssuesCoordinator.dispatcher = self.dispatcher; _passwordIssuesCoordinator.reauthModule = _reauthenticationModule; [_passwordIssuesCoordinator start]; }
diff --git a/ios/chrome/browser/ui/settings/safety_check/BUILD.gn b/ios/chrome/browser/ui/settings/safety_check/BUILD.gn index 546903a..2ff8bd6 100644 --- a/ios/chrome/browser/ui/settings/safety_check/BUILD.gn +++ b/ios/chrome/browser/ui/settings/safety_check/BUILD.gn
@@ -16,6 +16,8 @@ "//ios/chrome/app/strings", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/settings:settings_root", + "//ios/chrome/browser/ui/settings/cells", + "//ios/chrome/browser/ui/settings/cells:public", "//ios/chrome/browser/ui/settings/utils", "//ios/chrome/browser/ui/table_view", "//ui/base", @@ -43,16 +45,22 @@ "//ios/chrome/browser/content_settings", "//ios/chrome/browser/main:public", "//ios/chrome/browser/passwords", + "//ios/chrome/browser/signin", + "//ios/chrome/browser/sync", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands", "//ios/chrome/browser/ui/coordinators:chrome_coordinators", "//ios/chrome/browser/ui/settings:settings_root", "//ios/chrome/browser/ui/settings/cells", "//ios/chrome/browser/ui/settings/cells:public", + "//ios/chrome/browser/ui/settings/password", "//ios/chrome/browser/ui/settings/utils", "//ios/chrome/browser/ui/table_view", "//ios/chrome/browser/ui/table_view/cells:cells_constants", "//ios/chrome/browser/ui/util", + "//ios/chrome/common", + "//ios/chrome/common/ui/colors", + "//ios/chrome/common/ui/elements:popover_label_view_controller", "//ui/base", ] frameworks = [ "UIKit.framework" ]
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.h b/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.h index 5001ff94..08fa972 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.h +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.h
@@ -7,6 +7,7 @@ #import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" +@protocol ApplicationCommands; @class SafetyCheckCoordinator; // Delegate that allows to dereference the SafetyCheckCoordinator. @@ -20,6 +21,7 @@ // The coordinator for the Safety Check screen. @interface SafetyCheckCoordinator : ChromeCoordinator +// Delegate to pass user interactions to the mediator. @property(nonatomic, weak) id<SafetyCheckCoordinatorDelegate> delegate; - (instancetype)initWithBaseViewController:(UIViewController*)viewController
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.mm index 7af06c58..c72673d 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.mm +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.mm
@@ -5,20 +5,32 @@ #import "ios/chrome/browser/ui/settings/safety_check/safety_check_coordinator.h" #include "base/mac/foundation_util.h" +#include "base/memory/scoped_refptr.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" #include "ios/chrome/browser/main/browser.h" #include "ios/chrome/browser/passwords/ios_chrome_password_check_manager.h" #include "ios/chrome/browser/passwords/ios_chrome_password_check_manager_factory.h" +#include "ios/chrome/browser/passwords/ios_chrome_password_store_factory.h" +#import "ios/chrome/browser/signin/authentication_service_factory.h" +#include "ios/chrome/browser/sync/profile_sync_service_factory.h" +#import "ios/chrome/browser/sync/sync_setup_service.h" +#import "ios/chrome/browser/sync/sync_setup_service_factory.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" +#import "ios/chrome/browser/ui/commands/browser_commands.h" +#import "ios/chrome/browser/ui/commands/command_dispatcher.h" +#import "ios/chrome/browser/ui/settings/password/password_issues_coordinator.h" #import "ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.h" #import "ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h" #import "ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" +#import "ios/chrome/common/ui/elements/popover_label_view_controller.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif @interface SafetyCheckCoordinator () < + PasswordIssuesCoordinatorDelegate, SafetyCheckNavigationCommands, SafetyCheckTableViewControllerPresentationDelegate> @@ -28,6 +40,13 @@ // The container view controller. @property(nonatomic, strong) SafetyCheckTableViewController* viewController; +// Coordinator for passwords issues screen. +@property(nonatomic, strong) + PasswordIssuesCoordinator* passwordIssuesCoordinator; + +// Dispatcher which can handle changing passwords on sites. +@property(nonatomic, strong) id<ApplicationCommands> handler; + @end @implementation SafetyCheckCoordinator @@ -41,6 +60,8 @@ browser:browser]; if (self) { _baseNavigationController = navigationController; + _handler = HandlerForProtocol(self.browser->GetCommandDispatcher(), + ApplicationCommands); } return self; } @@ -53,12 +74,18 @@ initWithStyle:UITableViewStylePlain]; self.viewController = viewController; + scoped_refptr<IOSChromePasswordCheckManager> passwordCheckManager = + IOSChromePasswordCheckManagerFactory::GetForBrowserState( + self.browser->GetBrowserState()); self.mediator = [[SafetyCheckMediator alloc] initWithUserPrefService:self.browser->GetBrowserState()->GetPrefs() - passwordCheckManager:IOSChromePasswordCheckManagerFactory:: - GetForBrowserState( - self.browser->GetBrowserState())]; + passwordCheckManager:passwordCheckManager + authService:AuthenticationServiceFactory::GetForBrowserState( + self.browser->GetBrowserState()) + syncService:SyncSetupServiceFactory::GetForBrowserState( + self.browser->GetBrowserState())]; self.mediator.consumer = self.viewController; + self.mediator.handler = self; self.viewController.serviceDelegate = self.mediator; self.viewController.presentationDelegate = self; @@ -75,4 +102,57 @@ [self.delegate safetyCheckCoordinatorDidRemove:self]; } +#pragma mark - SafetyCheckNavigationCommands + +- (void)showPasswordIssuesPage { + IOSChromePasswordCheckManager* passwordCheckManager = + IOSChromePasswordCheckManagerFactory::GetForBrowserState( + self.browser->GetBrowserState()) + .get(); + self.passwordIssuesCoordinator = [[PasswordIssuesCoordinator alloc] + initWithBaseNavigationController:self.baseNavigationController + browser:self.browser + passwordCheckManager:passwordCheckManager]; + self.passwordIssuesCoordinator.delegate = self; + self.passwordIssuesCoordinator.reauthModule = nil; + [self.passwordIssuesCoordinator start]; +} + +- (void)showErrorInfoFrom:(UIButton*)buttonView + withText:(NSAttributedString*)text { + PopoverLabelViewController* errorInfoPopover = + [[PopoverLabelViewController alloc] initWithPrimaryAttributedString:text + secondaryAttributedString:nil]; + + errorInfoPopover.popoverPresentationController.sourceView = buttonView; + errorInfoPopover.popoverPresentationController.sourceRect = buttonView.bounds; + errorInfoPopover.popoverPresentationController.permittedArrowDirections = + UIPopoverArrowDirectionAny; + [self.viewController presentViewController:errorInfoPopover + animated:YES + completion:nil]; +} + +- (void)showUpdateOnAppStorePage { + // TODO(crbug.com/1078782): Add navigation to App Store Chrome page. +} + +- (void)showSafeBrowsingPreferencePage { + // TODO(crbug.com/1078782): Add navigation to Safe Browsing preference page. +} + +#pragma mark - PasswordIssuesCoordinatorDelegate + +- (void)passwordIssuesCoordinatorDidRemove: + (PasswordIssuesCoordinator*)coordinator { + DCHECK_EQ(self.passwordIssuesCoordinator, coordinator); + [self.passwordIssuesCoordinator stop]; + self.passwordIssuesCoordinator.delegate = nil; + self.passwordIssuesCoordinator = nil; +} + +- (BOOL)willHandlePasswordDeletion:(const autofill::PasswordForm&)password { + return NO; +} + @end
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.h b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.h index 86b6f6d..74b72b9 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.h +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.h
@@ -11,9 +11,12 @@ #import <UIKit/UIKit.h> +class AuthenticationService; class IOSChromePasswordCheckManager; class PrefService; @protocol SafetyCheckConsumer; +@protocol SafetyCheckNavigationCommands; +class SyncSetupService; @class SafetyCheckTableViewController; @@ -27,13 +30,19 @@ - (instancetype)initWithUserPrefService:(PrefService*)userPrefService passwordCheckManager: (scoped_refptr<IOSChromePasswordCheckManager>) - passwordCheckManager NS_DESIGNATED_INITIALIZER; + passwordCheckManager + authService:(AuthenticationService*)authService + syncService:(SyncSetupService*)syncService + NS_DESIGNATED_INITIALIZER; - (instancetype)init NS_UNAVAILABLE; // The consumer for the Safety Check mediator. @property(nonatomic, weak) id<SafetyCheckConsumer> consumer; +// Handler used to navigate inside the safety check. +@property(nonatomic, weak) id<SafetyCheckNavigationCommands> handler; + @end #endif // IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_MEDIATOR_H_
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm index d3857fb..ff65023 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.mm
@@ -5,6 +5,10 @@ #import "ios/chrome/browser/ui/settings/safety_check/safety_check_mediator.h" #include "base/mac/foundation_util.h" +#include "base/numerics/safe_conversions.h" +#include "base/strings/sys_string_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "components/password_manager/core/browser/leak_detection_dialog_utils.h" #include "components/password_manager/core/common/password_manager_features.h" #include "components/prefs/pref_service.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" @@ -14,18 +18,26 @@ #include "ios/chrome/browser/passwords/password_check_observer_bridge.h" #include "ios/chrome/browser/passwords/password_store_observer_bridge.h" #include "ios/chrome/browser/pref_names.h" +#import "ios/chrome/browser/signin/authentication_service.h" +#include "ios/chrome/browser/sync/sync_setup_service.h" #import "ios/chrome/browser/ui/settings/cells/settings_check_item.h" -#import "ios/chrome/browser/ui/settings/cells/settings_multiline_detail_item.h" #import "ios/chrome/browser/ui/settings/safety_check/safety_check_consumer.h" +#import "ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h" #import "ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.h" #import "ios/chrome/browser/ui/settings/utils/observable_boolean.h" #import "ios/chrome/browser/ui/settings/utils/pref_backed_boolean.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_text_item.h" #import "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" +#import "ios/chrome/common/string_util.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" +#import "ios/chrome/common/ui/colors/semantic_color_names.h" #include "ios/chrome/grit/ios_chromium_strings.h" #include "ios/chrome/grit/ios_strings.h" +#import "net/base/mac/url_conversions.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." @@ -132,7 +144,7 @@ @property(nonatomic, assign) PasswordCheckRowStates passwordCheckRowState; // Row button to start the safety check. -@property(nonatomic, strong) SettingsMultilineDetailItem* checkStartItem; +@property(nonatomic, strong) TableViewTextItem* checkStartItem; // Current state of the start safety check row button. @property(nonatomic, assign) CheckStartStates checkStartState; @@ -151,6 +163,12 @@ // How many safety check items are still running (max 3). @property(nonatomic, assign) int checkRunningRemaining; +// Service used to check if user is signed in. +@property(nonatomic, assign) AuthenticationService* authService; + +// Service to check if passwords are synced. +@property(nonatomic, assign) SyncSetupService* syncService; + @end @implementation SafetyCheckMediator @@ -158,11 +176,18 @@ - (instancetype)initWithUserPrefService:(PrefService*)userPrefService passwordCheckManager: (scoped_refptr<IOSChromePasswordCheckManager>) - passwordCheckManager { + passwordCheckManager + authService:(AuthenticationService*)authService + syncService:(SyncSetupService*)syncService { self = [super init]; if (self) { DCHECK(userPrefService); DCHECK(passwordCheckManager); + DCHECK(authService); + DCHECK(syncService); + + _authService = authService; + _syncService = syncService; _passwordCheckManager = passwordCheckManager; _currentPasswordCheckState = _passwordCheckManager->GetPasswordCheckState(); @@ -196,8 +221,9 @@ _checkStartState = CheckStartStateDefault; _checkStartItem = - [[SettingsMultilineDetailItem alloc] initWithType:CheckStartItemType]; + [[TableViewTextItem alloc] initWithType:CheckStartItemType]; _checkStartItem.text = GetNSString(IDS_IOS_CHECK_PASSWORDS_NOW_BUTTON); + _checkStartItem.textColor = [UIColor colorNamed:kBlueColor]; } return self; } @@ -261,13 +287,10 @@ case PasswordCheckRowStateSafe: // No tap action. break; case PasswordCheckRowStateUnSafe: - // Link to compromised password page. + [self.handler showPasswordIssuesPage]; break; - case PasswordCheckRowStateDisabled: - // Popover for no passwords. - break; - case PasswordCheckRowStateError: - // Various popover states + case PasswordCheckRowStateDisabled: // Popover handled by cellitem. + case PasswordCheckRowStateError: // Popover handled by cellitem. break; } break; @@ -295,6 +318,23 @@ } } +- (BOOL)isItemWithErrorInfo:(TableViewItem*)item { + ItemType type = static_cast<ItemType>(item.type); + return (type != CheckStartItemType); +} + +- (void)infoButtonWasTapped:(UIButton*)buttonView + usingItemType:(NSInteger)itemType { + NSAttributedString* info = [self getPopoverInfoForType:itemType]; + + // If |info| is empty there is no popover to display. + if (!info) + return; + + // Push popover to coordinator. + [self.handler showErrorInfoFrom:buttonView withText:info]; +} + #pragma mark - BooleanObserver - (void)booleanDidChange:(id<ObservableBoolean>)observableBoolean { @@ -305,6 +345,19 @@ #pragma mark - Private methods +// Computes the text needed for a popover on |itemType| if available. +- (NSAttributedString*)getPopoverInfoForType:(NSInteger)itemType { + ItemType type = static_cast<ItemType>(itemType); + switch (type) { + case PasswordItemType: + return [self passwordCheckErrorInfo]; + case SafeBrowsingItemType: + case UpdateItemType: + case CheckStartItemType: + return nil; + } +} + // Computes the appropriate display state of the password check row based on // currentPasswordCheckState. - (PasswordCheckRowStates)computePasswordCheckRowState: @@ -317,7 +370,7 @@ case PasswordCheckState::kRunning: return PasswordCheckRowStateRunning; case PasswordCheckState::kNoPasswords: - return PasswordCheckRowStateDisabled; + return PasswordCheckRowStateDefault; case PasswordCheckState::kSignedOut: case PasswordCheckState::kOffline: case PasswordCheckState::kQuotaLimit: @@ -340,6 +393,84 @@ } } +// Computes the appropriate error info to be displayed in the passwords popover. +- (NSAttributedString*)passwordCheckErrorInfo { + if (!self.passwordCheckManager->GetCompromisedCredentials().empty()) + return nil; + + NSString* message; + GURL linkURL; + + switch (self.currentPasswordCheckState) { + case PasswordCheckState::kRunning: + case PasswordCheckState::kNoPasswords: + message = + l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_NO_PASSWORDS); + break; + case PasswordCheckState::kCanceled: + case PasswordCheckState::kIdle: + return nil; + case PasswordCheckState::kSignedOut: + message = l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_SIGNED_OUT); + break; + case PasswordCheckState::kOffline: + message = l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_OFFLINE); + break; + case PasswordCheckState::kQuotaLimit: + if ([self canUseAccountPasswordCheckup]) { + message = l10n_util::GetNSString( + IDS_IOS_PASSWORD_CHECK_ERROR_QUOTA_LIMIT_VISIT_GOOGLE); + linkURL = password_manager::GetPasswordCheckupURL( + password_manager::PasswordCheckupReferrer::kPasswordCheck); + } else { + message = + l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_QUOTA_LIMIT); + } + break; + case PasswordCheckState::kOther: + message = l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR_OTHER); + break; + } + return [self attributedStringWithText:message link:linkURL]; +} + +// Computes whether user is capable to run password check in Google Account. +- (BOOL)canUseAccountPasswordCheckup { + return (self.authService->IsAuthenticated() && + self.authService->GetAuthenticatedIdentity()) && + (self.syncService->IsSyncEnabled() && + !self.syncService->IsEncryptEverythingEnabled()); +} + +// Configures check passwords error info with a link. +- (NSAttributedString*)attributedStringWithText:(NSString*)text + link:(GURL)link { + NSRange range; + + NSString* strippedText = ParseStringWithLink(text, &range); + + NSRange fullRange = NSMakeRange(0, strippedText.length); + NSMutableAttributedString* attributedText = + [[NSMutableAttributedString alloc] initWithString:strippedText]; + [attributedText addAttribute:NSForegroundColorAttributeName + value:[UIColor colorNamed:kTextSecondaryColor] + range:fullRange]; + + [attributedText + addAttribute:NSFontAttributeName + value:[UIFont preferredFontForTextStyle:UIFontTextStyleSubheadline] + range:fullRange]; + + if (range.location != NSNotFound && range.length != 0) { + NSURL* URL = net::NSURLWithGURL(link); + id linkValue = URL ? URL : @""; + [attributedText addAttribute:NSLinkAttributeName + value:linkValue + range:range]; + } + return attributedText; +} + // Upon a tap of checkStartItem either starts or cancels a safety check. - (void)checkStartOrCancel { // If a check is already running cancel it. @@ -355,6 +486,9 @@ // Set remaining check running counter to 0. self.checkRunningRemaining = 0; + // Stop any running checks. + self.passwordCheckManager->StopPasswordCheck(); + } else { // Otherwise start a check. @@ -375,6 +509,27 @@ [self reconfigurePasswordCheckItem]; [self reconfigureSafeBrowsingCheckItem]; [self reconfigureCheckStartSection]; + + // The display should be changed to loading icons before any checks are + // started. + if (self.checkRunningRemaining > 0) { + // This handles a discrepancy between password check and safety check. In + // password check a user cannot start a check if they have no passwords, but + // in safety check they can, but the |passwordCheckManager| won't even start + // a check. This if block below allows safety check to push the disabled + // state after check now is pressed. + if (self.currentPasswordCheckState == PasswordCheckState::kNoPasswords) { + self.passwordCheckRowState = PasswordCheckRowStateDisabled; + // Want to show the loading wheel momentarily. + dispatch_after( + dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), + dispatch_get_main_queue(), ^{ + [self reconfigurePasswordCheckItem]; + }); + } else { + self.passwordCheckManager->StartPasswordCheck(); + } + } } // Reconfigures the display of the |updateCheckItem| based on current state of @@ -386,12 +541,11 @@ self.updateCheckItem.infoButtonHidden = YES; self.updateCheckItem.detailText = nil; self.updateCheckItem.trailingImage = nil; + self.updateCheckItem.trailingImageTintColor = nil; switch (self.updateCheckRowState) { - case UpdateCheckRowStateDefault: { - self.updateCheckItem.enabled = NO; + case UpdateCheckRowStateDefault: break; - } case UpdateCheckRowStateRunning: { self.updateCheckItem.indicatorHidden = NO; break; @@ -414,21 +568,49 @@ self.passwordCheckItem.infoButtonHidden = YES; self.passwordCheckItem.detailText = nil; self.passwordCheckItem.trailingImage = nil; + self.passwordCheckItem.trailingImageTintColor = nil; + self.passwordCheckItem.accessoryType = UITableViewCellAccessoryNone; switch (self.passwordCheckRowState) { - case PasswordCheckRowStateDefault: { - self.passwordCheckItem.enabled = NO; + case PasswordCheckRowStateDefault: break; - } case PasswordCheckRowStateRunning: { self.passwordCheckItem.indicatorHidden = NO; break; } - case PasswordCheckRowStateSafe: - case PasswordCheckRowStateUnSafe: - case PasswordCheckRowStateDisabled: - case PasswordCheckRowStateError: + case PasswordCheckRowStateSafe: { + DCHECK(self.passwordCheckManager->GetCompromisedCredentials().empty()); + UIImage* safeIconImage = [[UIImage imageNamed:@"settings_safe_state"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + self.passwordCheckItem.detailText = + base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16( + IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT, 0)); + self.passwordCheckItem.trailingImage = safeIconImage; + self.passwordCheckItem.trailingImageTintColor = + [UIColor colorNamed:kGreenColor]; break; + } + case PasswordCheckRowStateUnSafe: { + self.passwordCheckItem.detailText = + base::SysUTF16ToNSString(l10n_util::GetPluralStringFUTF16( + IDS_IOS_CHECK_PASSWORDS_COMPROMISED_COUNT, + self.passwordCheckManager->GetCompromisedCredentials().size())); + UIImage* unSafeIconImage = [[UIImage imageNamed:@"settings_unsafe_state"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + self.passwordCheckItem.trailingImage = unSafeIconImage; + self.passwordCheckItem.trailingImageTintColor = + [UIColor colorNamed:kRedColor]; + self.passwordCheckItem.accessoryType = + UITableViewCellAccessoryDisclosureIndicator; + break; + } + case PasswordCheckRowStateDisabled: + case PasswordCheckRowStateError: { + self.passwordCheckItem.detailText = + l10n_util::GetNSString(IDS_IOS_PASSWORD_CHECK_ERROR); + self.passwordCheckItem.infoButtonHidden = NO; + break; + } } [self.consumer reconfigureCellsForItems:@[ self.passwordCheckItem ]]; @@ -443,12 +625,11 @@ self.safeBrowsingCheckItem.infoButtonHidden = YES; self.safeBrowsingCheckItem.detailText = nil; self.safeBrowsingCheckItem.trailingImage = nil; + self.safeBrowsingCheckItem.trailingImageTintColor = nil; switch (self.safeBrowsingCheckRowState) { - case SafeBrowsingCheckRowStateDefault: { - self.safeBrowsingCheckItem.enabled = NO; + case SafeBrowsingCheckRowStateDefault: break; - } case SafeBrowsingCheckRowStateRunning: { self.safeBrowsingCheckItem.indicatorHidden = NO; break;
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h b/ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h index 92bc3f0..246f2914c 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h
@@ -9,8 +9,18 @@ // controller. @protocol SafetyCheckNavigationCommands -// TODO(crbug.com/1078782): Add navigation commands for updates, passwords, and -// safe browsing. +// Shows password issues page. +- (void)showPasswordIssuesPage; + +// Opens Chrome page in App Store for updates. +- (void)showUpdateOnAppStorePage; + +// Shows page with Safe Browsing preference toggle. +- (void)showSafeBrowsingPreferencePage; + +// Shows the error popover with the corresponding |text|. +- (void)showErrorInfoFrom:(UIButton*)buttonView + withText:(NSAttributedString*)text; @end
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_service_delegate.h b/ios/chrome/browser/ui/settings/safety_check/safety_check_service_delegate.h index 267b2de9..3886a21 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_service_delegate.h +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_service_delegate.h
@@ -15,6 +15,13 @@ // Called when item is tapped. - (void)didSelectItem:(TableViewItem*)item; +// Checks if |item| should have an error popover. +- (BOOL)isItemWithErrorInfo:(TableViewItem*)item; + +// Notifies the mediator that an info button was tapped for |itemType|. +- (void)infoButtonWasTapped:(UIButton*)buttonView + usingItemType:(NSInteger)itemType; + @end #endif // IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_SERVICE_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.h b/ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.h index 1c2c925..8b18ec1a 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.h +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.h
@@ -10,13 +10,10 @@ @protocol SafetyCheckServiceDelegate; @class SafetyCheckTableViewController; -@protocol SafetyCheckTableViewControllerModelDelegate; // The accessibility identifier of the privacy settings collection view. extern NSString* const kSafetyCheckTableViewId; -@protocol SafetyCheckNavigationCommands; - // Delegate for presentation events related to // SafetyCheckTableViewController. @protocol SafetyCheckTableViewControllerPresentationDelegate @@ -40,9 +37,6 @@ // Handler for taps on items on the safety check page. @property(nonatomic, weak) id<SafetyCheckServiceDelegate> serviceDelegate; -// Handler used to navigate inside the safety check. -@property(nonatomic, weak) id<SafetyCheckNavigationCommands> handler; - @end #endif // IOS_CHROME_BROWSER_UI_SETTINGS_SAFETY_CHECK_SAFETY_CHECK_TABLE_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.mm b/ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.mm index c460bf30..c52bae36 100644 --- a/ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/safety_check/safety_check_table_view_controller.mm
@@ -6,6 +6,8 @@ #import "base/mac/foundation_util.h" #include "components/strings/grit/components_strings.h" +#import "ios/chrome/browser/ui/settings/cells/settings_check_cell.h" +#import "ios/chrome/browser/ui/settings/safety_check/safety_check_navigation_commands.h" #import "ios/chrome/browser/ui/settings/safety_check/safety_check_service_delegate.h" #import "ios/chrome/browser/ui/settings/settings_navigation_controller.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" @@ -97,4 +99,31 @@ [tableView deselectRowAtIndexPath:indexPath animated:YES]; } +#pragma mark - UITableViewDataSource + +- (UITableViewCell*)tableView:(UITableView*)tableView + cellForRowAtIndexPath:(NSIndexPath*)indexPath { + UITableViewCell* cell = [super tableView:tableView + cellForRowAtIndexPath:indexPath]; + TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath]; + if ([self.serviceDelegate isItemWithErrorInfo:item]) { + SettingsCheckCell* settingsCheckCell = + base::mac::ObjCCastStrict<SettingsCheckCell>(cell); + settingsCheckCell.infoButton.tag = item.type; + [settingsCheckCell.infoButton addTarget:self + action:@selector(didTapErrorInfoButton:) + forControlEvents:UIControlEventTouchUpInside]; + } + return cell; +} + +#pragma mark - Private + +// Called when user tapped on the information button of an +// item. Shows popover with detailed description of an error if needed. +- (void)didTapErrorInfoButton:(UIButton*)buttonView { + [self.serviceDelegate infoButtonWasTapped:buttonView + usingItemType:buttonView.tag]; +} + @end
diff --git a/ios/chrome/browser/ui/tab_grid/BUILD.gn b/ios/chrome/browser/ui/tab_grid/BUILD.gn index 42582503..b21d9f9 100644 --- a/ios/chrome/browser/ui/tab_grid/BUILD.gn +++ b/ios/chrome/browser/ui/tab_grid/BUILD.gn
@@ -8,9 +8,9 @@ sources = [ "tab_grid_coordinator.h", "tab_grid_coordinator.mm", + "tab_grid_coordinator_delegate.h", "tab_grid_mediator.h", "tab_grid_mediator.mm", - "tab_switcher.h", ] configs += [ "//build/config/compiler:enable_arc" ]
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h index 7f253ee..f624c7c 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.h
@@ -9,36 +9,37 @@ #import "base/ios/block_types.h" #import "ios/chrome/browser/chrome_root_coordinator.h" -#import "ios/chrome/browser/ui/tab_grid/tab_switcher.h" +#import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h" @protocol ApplicationCommands; -@protocol BrowsingDataCommands; - class Browser; +@protocol BrowsingDataCommands; +@protocol TabGridCoordinatorDelegate; -@interface TabGridCoordinator : ChromeRootCoordinator <TabSwitcher> +@interface TabGridCoordinator : ChromeRootCoordinator - (instancetype)initWithWindow:(UIWindow*)window applicationCommandEndpoint: (id<ApplicationCommands>)applicationCommandEndpoint browsingDataCommandEndpoint: (id<BrowsingDataCommands>)browsingDataCommandEndpoint + regularBrowser:(Browser*)regularBrowser + incognitoBrowser:(Browser*)incognitoBrowser NS_DESIGNATED_INITIALIZER; - (instancetype)initWithWindow:(UIWindow*)window NS_UNAVAILABLE; -@property(nonatomic, weak) id<TabSwitcherDelegate> delegate; +@property(nonatomic, weak) id<TabGridCoordinatorDelegate> delegate; -@property(nonatomic, assign) Browser* regularBrowser; +// Updates the incognito browser. Should only be sets when both the current +// incognito browser and the new incognito browser are either nil or contain no +// tabs. This must be called after the incognito browser has been deleted +// because the incognito browser state is deleted. @property(nonatomic, assign) Browser* incognitoBrowser; // The view controller, if any, that is active. @property(nonatomic, readonly, strong) UIViewController* activeViewController; -// The view controller that is doing the view controller swapping. -// This may or may not be the same as |activeViewController|. -@property(nonatomic, readonly, strong) UIViewController* viewController; - // If this property is YES, calls to |showTabSwitcher:completion:| and // |showTabViewController:completion:| will present the given view controllers // without animation. This should only be used by unittests. @@ -48,9 +49,11 @@ // whether or not child coordinators exist. - (void)stopChildCoordinatorsWithCompletion:(ProceduralBlock)completion; -// Displays the given TabSwitcher, replacing any TabSwitchers or view -// controllers that may currently be visible. -- (void)showTabSwitcher:(id<TabSwitcher>)tabSwitcher; +// Perform any initial setup required for the appearance of the TabGrid. +- (void)prepareToShowTabGrid; + +// Displays the TabGrid. +- (void)showTabGrid; // Displays the given view controller, replacing any TabSwitchers or other view // controllers that may currently be visible. Runs the given |completion| block @@ -58,8 +61,9 @@ - (void)showTabViewController:(UIViewController*)viewController completion:(ProceduralBlock)completion; -// Perform any initial setup required for the appearance of |tabSwitcher|. -- (void)prepareToShowTabSwitcher:(id<TabSwitcher>)tabSwitcher; +// Sets the |page| as the active (visible) one. The active page must not be the +// remote tabs. +- (void)setActivePage:(TabGridPage)page; @end
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 0451e10..a4f1c22b 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator.mm
@@ -11,6 +11,7 @@ #include "ios/chrome/browser/chrome_url_constants.h" #include "ios/chrome/browser/main/browser.h" #include "ios/chrome/browser/sessions/ios_chrome_tab_restore_service_factory.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/commands/browsing_data_commands.h" #import "ios/chrome/browser/ui/commands/command_dispatcher.h" @@ -21,6 +22,7 @@ #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_mediator.h" #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/tab_grid/tab_grid_coordinator_delegate.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_mediator.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_paging.h" #import "ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.h" @@ -28,20 +30,24 @@ #include "ios/chrome/browser/ui/ui_feature_flags.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" -#import "ios/chrome/browser/web_state_list/tab_insertion_browser_agent.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." #endif -@interface TabGridCoordinator ()<TabPresentationDelegate, - HistoryPresentationDelegate, - RecentTabsPresentationDelegate> +@interface TabGridCoordinator () <TabPresentationDelegate, + HistoryPresentationDelegate, + RecentTabsPresentationDelegate> { + // Use an explicit ivar instead of synthesizing as the setter isn't using the + // ivar. + Browser* _incognitoBrowser; +} + +@property(nonatomic, assign, readonly) Browser* regularBrowser; // Superclass property specialized for the class that this coordinator uses. @property(nonatomic, weak) TabGridViewController* baseViewController; // Commad dispatcher used while this coordinator's view controller is active. -// (for compatibility with the TabSwitcher protocol). @property(nonatomic, strong) CommandDispatcher* dispatcher; // Container view controller for the BVC to live in; this class's view // controller will present this. @@ -65,13 +71,14 @@ @synthesize baseViewController = _baseViewController; // Ivars are not auto-synthesized when both accessor and mutator are overridden. @synthesize regularBrowser = _regularBrowser; -@synthesize incognitoBrowser = _incognitoBrowser; - (instancetype)initWithWindow:(nullable UIWindow*)window applicationCommandEndpoint: (id<ApplicationCommands>)applicationCommandEndpoint browsingDataCommandEndpoint: - (id<BrowsingDataCommands>)browsingDataCommandEndpoint { + (id<BrowsingDataCommands>)browsingDataCommandEndpoint + regularBrowser:(Browser*)regularBrowser + incognitoBrowser:(Browser*)incognitoBrowser { if ((self = [super initWithWindow:window])) { _dispatcher = [[CommandDispatcher alloc] init]; [_dispatcher startDispatchingToTarget:applicationCommandEndpoint @@ -84,6 +91,8 @@ forProtocol:@protocol(ApplicationSettingsCommands)]; [_dispatcher startDispatchingToTarget:browsingDataCommandEndpoint forProtocol:@protocol(BrowsingDataCommands)]; + _regularBrowser = regularBrowser; + _incognitoBrowser = incognitoBrowser; } return self; } @@ -97,14 +106,6 @@ : _regularBrowser; } -- (void)setRegularBrowser:(Browser*)regularBrowser { - if (self.regularTabsMediator) { - self.regularTabsMediator.browser = regularBrowser; - } else { - _regularBrowser = regularBrowser; - } -} - - (Browser*)incognitoBrowser { // Ensure browser which is actually used by the mediator is returned, as it // may have been updated. @@ -113,11 +114,8 @@ } - (void)setIncognitoBrowser:(Browser*)incognitoBrowser { - if (self.incognitoTabsMediator) { - self.incognitoTabsMediator.browser = incognitoBrowser; - } else { - _incognitoBrowser = incognitoBrowser; - } + DCHECK(self.incognitoTabsMediator); + self.incognitoTabsMediator.browser = incognitoBrowser; } - (void)stopChildCoordinatorsWithCompletion:(ProceduralBlock)completion { @@ -131,6 +129,112 @@ } } +- (void)setActivePage:(TabGridPage)page { + DCHECK(page != TabGridPageRemoteTabs); + self.baseViewController.activePage = page; +} + +- (UIViewController*)activeViewController { + if (self.bvcContainer) { + DCHECK(self.bvcContainer.currentBVC); + return self.bvcContainer.currentBVC; + } + return self.baseViewController; +} + +- (void)prepareToShowTabGrid { + // No-op if the BVC isn't being presented. + if (!self.bvcContainer) + return; + [base::mac::ObjCCast<TabGridViewController>(self.baseViewController) + prepareForAppearance]; +} + +- (void)showTabGrid { + BOOL animated = !self.animationsDisabledForTesting; + + // If a BVC is currently being presented, dismiss it. This will trigger any + // necessary animations. + if (self.bvcContainer) { + // This is done with a dispatch to make sure that the view isn't added to + // the view hierarchy right away, as it is not the expectations of the + // API. + dispatch_async(dispatch_get_main_queue(), ^{ + [self.baseViewController contentWillAppearAnimated:animated]; + self.baseViewController.childViewControllerForStatusBarStyle = nil; + + self.transitionHandler = [[TabGridTransitionHandler alloc] + initWithLayoutProvider:self.baseViewController]; + self.transitionHandler.animationDisabled = !animated; + [self.transitionHandler + transitionFromBrowser:self.bvcContainer + toTabGrid:self.baseViewController + withCompletion:^{ + self.bvcContainer = nil; + [self.baseViewController contentDidAppear]; + }]; + }); + } + // Record when the tab switcher is presented. + base::RecordAction(base::UserMetricsAction("MobileTabGridEntered")); +} + +- (void)showTabViewController:(UIViewController*)viewController + completion:(ProceduralBlock)completion { + DCHECK(viewController); + + // Record when the tab switcher is dismissed. + base::RecordAction(base::UserMetricsAction("MobileTabGridExited")); + + // If another BVC is already being presented, swap this one into the + // container. + if (self.bvcContainer) { + self.bvcContainer.currentBVC = viewController; + if (completion) { + completion(); + } + return; + } + + self.bvcContainer = [[BVCContainerViewController alloc] init]; + self.bvcContainer.currentBVC = viewController; + BOOL animated = !self.animationsDisabledForTesting; + // Never animate the first time. + if (self.firstPresentation) + animated = NO; + + // Extened |completion| to signal the tab switcher delegate + // that the animated "tab switcher dismissal" (that is, presenting something + // on top of the tab switcher) transition has completed. + // Finally, the launch mask view should be removed. + ProceduralBlock extendedCompletion = ^{ + [self.delegate tabGridDismissTransitionDidEnd:self]; + if (!GetFirstResponder()) { + // It is possible to already have a first responder (for example the + // omnibox). In that case, we don't want to mark BVC as first responder. + [self.bvcContainer.currentBVC becomeFirstResponder]; + } + if (completion) { + completion(); + } + self.firstPresentation = NO; + }; + + self.baseViewController.childViewControllerForStatusBarStyle = + self.bvcContainer.currentBVC; + + [self.baseViewController contentWillDisappearAnimated:animated]; + + self.transitionHandler = [[TabGridTransitionHandler alloc] + initWithLayoutProvider:self.baseViewController]; + self.transitionHandler.animationDisabled = !animated; + [self.transitionHandler transitionFromTabGrid:self.baseViewController + toBrowser:self.bvcContainer + withCompletion:^{ + extendedCompletion(); + }]; +} + #pragma mark - ChromeCoordinator - (void)start { @@ -226,116 +330,6 @@ self.remoteTabsMediator = nil; } -#pragma mark - ViewControllerSwapping - -- (UIViewController*)activeViewController { - if (self.bvcContainer) { - DCHECK(self.bvcContainer.currentBVC); - return self.bvcContainer.currentBVC; - } - return self.baseViewController; -} - -- (UIViewController*)viewController { - return self.baseViewController; -} - -- (void)prepareToShowTabSwitcher:(id<TabSwitcher>)tabSwitcher { - DCHECK(tabSwitcher); - DCHECK_EQ([tabSwitcher viewController], self.baseViewController); - // No-op if the BVC isn't being presented. - if (!self.bvcContainer) - return; - [base::mac::ObjCCast<TabGridViewController>(self.baseViewController) - prepareForAppearance]; -} - -- (void)showTabSwitcher:(id<TabSwitcher>)tabSwitcher { - DCHECK_EQ([tabSwitcher viewController], self.baseViewController); - BOOL animated = !self.animationsDisabledForTesting; - - // If a BVC is currently being presented, dismiss it. This will trigger any - // necessary animations. - if (self.bvcContainer) { - // This is done with a dispatch to make sure that the view isn't added to - // the view hierarchy right away, as it is not the expectations of the - // API. - dispatch_async(dispatch_get_main_queue(), ^{ - [self.baseViewController contentWillAppearAnimated:animated]; - self.baseViewController.childViewControllerForStatusBarStyle = nil; - - self.transitionHandler = [[TabGridTransitionHandler alloc] - initWithLayoutProvider:self.baseViewController]; - self.transitionHandler.animationDisabled = !animated; - [self.transitionHandler - transitionFromBrowser:self.bvcContainer - toTabGrid:self.baseViewController - withCompletion:^{ - self.bvcContainer = nil; - [self.baseViewController contentDidAppear]; - }]; - }); - } - // Record when the tab switcher is presented. - base::RecordAction(base::UserMetricsAction("MobileTabGridEntered")); -} - -- (void)showTabViewController:(UIViewController*)viewController - completion:(ProceduralBlock)completion { - DCHECK(viewController); - - // Record when the tab switcher is dismissed. - base::RecordAction(base::UserMetricsAction("MobileTabGridExited")); - - // If another BVC is already being presented, swap this one into the - // container. - if (self.bvcContainer) { - self.bvcContainer.currentBVC = viewController; - if (completion) { - completion(); - } - return; - } - - self.bvcContainer = [[BVCContainerViewController alloc] init]; - self.bvcContainer.currentBVC = viewController; - BOOL animated = !self.animationsDisabledForTesting; - // Never animate the first time. - if (self.firstPresentation) - animated = NO; - - // Extened |completion| to signal the tab switcher delegate - // that the animated "tab switcher dismissal" (that is, presenting something - // on top of the tab switcher) transition has completed. - // Finally, the launch mask view should be removed. - ProceduralBlock extendedCompletion = ^{ - [self.delegate tabSwitcherDismissTransitionDidEnd:self]; - if (!GetFirstResponder()) { - // It is possible to already have a first responder (for example the - // omnibox). In that case, we don't want to mark BVC as first responder. - [self.bvcContainer.currentBVC becomeFirstResponder]; - } - if (completion) { - completion(); - } - self.firstPresentation = NO; - }; - - self.baseViewController.childViewControllerForStatusBarStyle = - self.bvcContainer.currentBVC; - - [self.baseViewController contentWillDisappearAnimated:animated]; - - self.transitionHandler = [[TabGridTransitionHandler alloc] - initWithLayoutProvider:self.baseViewController]; - self.transitionHandler.animationDisabled = !animated; - [self.transitionHandler transitionFromTabGrid:self.baseViewController - toBrowser:self.bvcContainer - withCompletion:^{ - extendedCompletion(); - }]; -} - #pragma mark - TabPresentationDelegate - (void)showActiveTabInPage:(TabGridPage)page focusOmnibox:(BOOL)focusOmnibox { @@ -357,8 +351,8 @@ return; } // Trigger the transition through the delegate. This will in turn call back - // into this coordinator via the ViewControllerSwapping protocol. - [self.delegate tabSwitcher:self + // into this coordinator. + [self.delegate tabGrid:self shouldFinishWithBrowser:activeBrowser focusOmnibox:focusOmnibox]; } @@ -384,7 +378,7 @@ } - (void)showActiveRegularTabFromRecentTabs { - [self.delegate tabSwitcher:self + [self.delegate tabGrid:self shouldFinishWithBrowser:self.regularBrowser focusOmnibox:NO]; } @@ -392,49 +386,17 @@ #pragma mark - HistoryPresentationDelegate - (void)showActiveRegularTabFromHistory { - [self.delegate tabSwitcher:self + [self.delegate tabGrid:self shouldFinishWithBrowser:self.regularBrowser focusOmnibox:NO]; } - (void)showActiveIncognitoTabFromHistory { - [self.delegate tabSwitcher:self + [self.delegate tabGrid:self shouldFinishWithBrowser:self.incognitoBrowser focusOmnibox:NO]; } -#pragma mark - TabSwitcher - -- (void)restoreInternalStateWithMainBrowser:(Browser*)mainBrowser - otrBrowser:(Browser*)otrBrowser - activeBrowser:(Browser*)activeBrowser { - // The only action here is to signal to the tab grid which panel should be - // active. - if (activeBrowser == otrBrowser) { - self.baseViewController.activePage = TabGridPageIncognitoTabs; - } else { - self.baseViewController.activePage = TabGridPageRegularTabs; - } -} - -- (void)dismissWithNewTabAnimationToBrowser:(Browser*)browser - withUrlLoadParams:(const UrlLoadParams&)urlLoadParams - atIndex:(int)position { - int tabIndex = std::min(position, browser->GetWebStateList()->count()); - - TabInsertionBrowserAgent::FromBrowser(browser)->InsertWebState( - urlLoadParams.web_params, nil, false, tabIndex, false); - - // Tell the delegate to display the tab. - [self.delegate tabSwitcher:self - shouldFinishWithBrowser:browser - focusOmnibox:NO]; -} - -- (void)setOtrBrowser:(Browser*)browser { - DCHECK(self.incognitoTabsMediator); - self.incognitoTabsMediator.browser = browser; -} - (void)openAllTabsFromSession:(const synced_sessions::DistantSession*)session { // TODO(crbug.com/1093302) : Implement this.
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_delegate.h b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_delegate.h new file mode 100644 index 0000000..c68f8497 --- /dev/null +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_delegate.h
@@ -0,0 +1,29 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_COORDINATOR_DELEGATE_H_ +#define IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_COORDINATOR_DELEGATE_H_ + +#import <Foundation/Foundation.h> + +class Browser; +@class TabGridCoordinator; + +// This delegate is used to drive the TabSwitcher dismissal and execute code +// when the presentation and dismmiss animations finishes. +@protocol TabGridCoordinatorDelegate + +// Informs the delegate the tab switcher should be dismissed with the given +// active browser. +- (void)tabGrid:(TabGridCoordinator*)tabGrid + shouldFinishWithBrowser:(Browser*)browser + focusOmnibox:(BOOL)focusOmnibox; + +// Informs the delegate that the tab switcher is done and should be +// dismissed. +- (void)tabGridDismissTransitionDidEnd:(TabGridCoordinator*)tabGrid; + +@end + +#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_GRID_COORDINATOR_DELEGATE_H_
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm index 447b754..6432525 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_unittest.mm
@@ -8,8 +8,9 @@ #import "base/test/ios/wait_util.h" #import "ios/chrome/browser/main/test_browser.h" +#import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browsing_data_commands.h" -#import "ios/chrome/browser/ui/tab_grid/tab_switcher.h" +#include "ios/chrome/browser/ui/tab_grid/tab_grid_coordinator_delegate.h" #import "ios/chrome/test/block_cleanup_test.h" #include "ios/web/public/test/web_task_environment.h" #include "testing/gtest_mac.h" @@ -19,19 +20,20 @@ #error "This file requires ARC support." #endif -@interface TestTabSwitcherDelegate : NSObject<TabSwitcherDelegate> +@interface TestTabGridCoordinatorDelegate + : NSObject <TabGridCoordinatorDelegate> @property(nonatomic) BOOL didEndCalled; @end -@implementation TestTabSwitcherDelegate +@implementation TestTabGridCoordinatorDelegate @synthesize didEndCalled = _didEndCalled; -- (void)tabSwitcher:(id<TabSwitcher>)tabSwitcher +- (void)tabGrid:(TabGridCoordinator*)tabGrid shouldFinishWithBrowser:(Browser*)browser focusOmnibox:(BOOL)focusOmnibox { // No-op. } -- (void)tabSwitcherDismissTransitionDidEnd:(id<TabSwitcher>)tabSwitcher { +- (void)tabGridDismissTransitionDidEnd:(TabGridCoordinator*)tabGrid { self.didEndCalled = YES; } @end @@ -48,9 +50,10 @@ applicationCommandEndpoint:OCMProtocolMock( @protocol(ApplicationCommands)) browsingDataCommandEndpoint:OCMProtocolMock( - @protocol(BrowsingDataCommands))]; + @protocol(BrowsingDataCommands)) + regularBrowser:browser_.get() + incognitoBrowser:nil]; coordinator_.animationsDisabledForTesting = YES; - coordinator_.regularBrowser = browser_.get(); // TabGirdCoordinator will make its view controller the root, so stash the // original root view controller before starting |coordinator_|. original_root_view_controller_ = @@ -58,7 +61,7 @@ [coordinator_ start]; - delegate_ = [[TestTabSwitcherDelegate alloc] init]; + delegate_ = [[TestTabGridCoordinatorDelegate alloc] init]; coordinator_.delegate = delegate_; normal_tab_view_controller_ = [[UIViewController alloc] init]; @@ -89,7 +92,7 @@ TabGridCoordinator* coordinator_; // Delegate for the coordinator's TabSwitcher interface. - TestTabSwitcherDelegate* delegate_; + TestTabGridCoordinatorDelegate* delegate_; // The key window's original root view controller, which must be restored at // the end of the test. @@ -115,11 +118,11 @@ EXPECT_EQ(normal_tab_view_controller_, coordinator_.activeViewController); // Now setting a TabSwitcher will make the switcher active. - [coordinator_ showTabSwitcher:coordinator_]; + [coordinator_ showTabGrid]; bool tab_switcher_active = base::test::ios::WaitUntilConditionOrTimeout( base::test::ios::kWaitForUIElementTimeout, ^bool { - return - [coordinator_ viewController] == coordinator_.activeViewController; + return coordinator_.baseViewController == + coordinator_.activeViewController; }); EXPECT_TRUE(tab_switcher_active); } @@ -127,19 +130,19 @@ // Tests that it is possible to set a TabViewController after setting a // TabSwitcher. TEST_F(TabGridCoordinatorTest, TabViewControllerAfterTabSwitcher) { - [coordinator_ showTabSwitcher:coordinator_]; - EXPECT_EQ([coordinator_ viewController], coordinator_.activeViewController); + [coordinator_ showTabGrid]; + EXPECT_EQ(coordinator_.baseViewController, coordinator_.activeViewController); [coordinator_ showTabViewController:normal_tab_view_controller_ completion:nil]; EXPECT_EQ(normal_tab_view_controller_, coordinator_.activeViewController); // Showing the TabSwitcher again will make it active. - [coordinator_ showTabSwitcher:coordinator_]; + [coordinator_ showTabGrid]; bool tab_switcher_active = base::test::ios::WaitUntilConditionOrTimeout( base::test::ios::kWaitForUIElementTimeout, ^bool { - return - [coordinator_ viewController] == coordinator_.activeViewController; + return coordinator_.baseViewController == + coordinator_.activeViewController; }); EXPECT_TRUE(tab_switcher_active); } @@ -157,11 +160,11 @@ // Tests calling showTabSwitcher twice in a row with the same VC. TEST_F(TabGridCoordinatorTest, ShowTabSwitcherTwice) { - [coordinator_ showTabSwitcher:coordinator_]; - EXPECT_EQ([coordinator_ viewController], coordinator_.activeViewController); + [coordinator_ showTabGrid]; + EXPECT_EQ(coordinator_.baseViewController, coordinator_.activeViewController); - [coordinator_ showTabSwitcher:coordinator_]; - EXPECT_EQ([coordinator_ viewController], coordinator_.activeViewController); + [coordinator_ showTabGrid]; + EXPECT_EQ(coordinator_.baseViewController, coordinator_.activeViewController); } // Tests calling showTabViewController twice in a row with the same VC. @@ -179,7 +182,7 @@ // handlers are called properly after the new view controller is made active. TEST_F(TabGridCoordinatorTest, CompletionHandlers) { // Setup: show the switcher. - [coordinator_ showTabSwitcher:coordinator_]; + [coordinator_ showTabGrid]; // Tests that the completion handler is called when showing a tab view // controller. Tests that the delegate 'didEnd' method is also called.
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm index 2cbf57ec..242e1a3 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_view_controller.mm
@@ -199,6 +199,7 @@ [self scrollToPage:_currentPage animated:NO]; [self configureViewControllerForCurrentSizeClassesAndPage]; [self setInsetForRemoteTabs]; + [self setInsetForGridViews]; }; [coordinator animateAlongsideTransition:animate completion:nil]; }
diff --git a/ios/chrome/browser/ui/tab_grid/tab_switcher.h b/ios/chrome/browser/ui/tab_grid/tab_switcher.h deleted file mode 100644 index 31ebaf5..0000000 --- a/ios/chrome/browser/ui/tab_grid/tab_switcher.h +++ /dev/null
@@ -1,74 +0,0 @@ -// Copyright 2015 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_SWITCHER_H_ -#define IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_SWITCHER_H_ - -#import <UIKit/UIKit.h> - -#import "ios/chrome/browser/ui/commands/application_commands.h" -#include "ui/base/page_transition_types.h" -#include "url/gurl.h" - -class Browser; -@protocol TabSwitcher; -struct UrlLoadParams; - -// This delegate is used to drive the TabSwitcher dismissal and execute code -// when the presentation and dismmiss animations finishes. The main controller -// is a good example of the implementation of this delegate. -@protocol TabSwitcherDelegate <NSObject> - -// Informs the delegate the tab switcher should be dismissed with the given -// active browser. -- (void)tabSwitcher:(id<TabSwitcher>)tabSwitcher - shouldFinishWithBrowser:(Browser*)browser - focusOmnibox:(BOOL)focusOmnibox; - -// Informs the delegate that the tab switcher is done and should be -// dismissed. -- (void)tabSwitcherDismissTransitionDidEnd:(id<TabSwitcher>)tabSwitcher; - -@end - -// This protocol describes the common interface between the two implementations -// of the tab switcher. StackViewController for iPhone and TabSwitcherController -// for iPad are examples of implementers of this protocol. -@protocol TabSwitcher <NSObject> - -// This delegate must be set on the tab switcher in order to drive the tab -// switcher. -@property(nonatomic, weak) id<TabSwitcherDelegate> delegate; - -// Restores the internal state of the tab switcher with the given browser, -// which must not be nil. |activeBrowser| is the browser which starts active, -// and must be one of the other two browsers. Should only be called when the -// object is not being shown. -- (void)restoreInternalStateWithMainBrowser:(Browser*)mainBrowser - otrBrowser:(Browser*)otrBrowser - activeBrowser:(Browser*)activeBrowser; - -// Returns the view controller that displays the tab switcher. -- (UIViewController*)viewController; - -// Create a new tab in |browser|. Implementors are expected to also perform an -// animation from the selected tab in the tab switcher to the newly created tab -// in the content area. Objects adopting this protocol should call the following -// delegate methods: -// |-tabSwitcher:shouldFinishWithBrowser:| -// |-tabSwitcherDismissTransitionDidEnd:| -// to inform the delegate when this animation begins and ends. -- (void)dismissWithNewTabAnimationToBrowser:(Browser*)browser - withUrlLoadParams:(const UrlLoadParams&)urlLoadParams - atIndex:(int)position; - -// Updates the OTR (Off The Record) browser. Should only be called when both -// the current OTR browser and the new OTR browser are either nil or contain no -// tabs. This must be called after the otr browser has been deleted because the -// incognito browser state is deleted. -- (void)setOtrBrowser:(Browser*)otrBrowser; - -@end - -#endif // IOS_CHROME_BROWSER_UI_TAB_GRID_TAB_SWITCHER_H_
diff --git a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator.mm index 50a010e..4b64ce6 100644 --- a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator.mm +++ b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_coordinator.mm
@@ -103,6 +103,11 @@ [self.viewController setScrollProgressForTabletOmnibox:progress]; } +- (UIResponder<UITextInput>*)fakeboxScribbleForwardingTarget { + // Only works in primary toolbar. + return nil; +} + #pragma mark - ToolbarCommands - (void)triggerToolsMenuButtonAnimation {
diff --git a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller.h b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller.h index bf0185d9..0234dac2 100644 --- a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller.h +++ b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller.h
@@ -27,9 +27,7 @@ // dismissed on such events. For example, the tools menu is closed upon // rotation. @interface AdaptiveToolbarViewController - : UIViewController<PopupMenuUIUpdating, - ToolbarConsumer, - NewTabPageControllerDelegate> + : UIViewController <PopupMenuUIUpdating, ToolbarConsumer> // Button factory. @property(nonatomic, strong) ToolbarButtonFactory* buttonFactory; @@ -48,6 +46,8 @@ - (void)updateForSideSwipeSnapshotOnNTP:(BOOL)onNTP; // Resets the view after taking a snapshot for a side swipe. - (void)resetAfterSideSwipeSnapshot; +// Sets the toolbar location bar alpha and vertical offset based on |progress|. +- (void)setScrollProgressForTabletOmnibox:(CGFloat)progress; @end
diff --git a/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm b/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm index 0da36a3..f5a4e76c 100644 --- a/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm +++ b/ios/chrome/browser/ui/toolbar/primary_toolbar_coordinator.mm
@@ -171,6 +171,12 @@ } } +#pragma mark - NewTabPageControllerDelegate + +- (UIResponder<UITextInput>*)fakeboxScribbleForwardingTarget { + return self.locationBarCoordinator.omniboxScribbleForwardingTarget; +} + #pragma mark - FakeboxFocuser - (void)focusOmniboxNoAnimation {
diff --git a/ios/chrome/browser/ui/toolbar/toolbar_coordinator_adaptor.mm b/ios/chrome/browser/ui/toolbar/toolbar_coordinator_adaptor.mm index 698ba64..1570eb8b 100644 --- a/ios/chrome/browser/ui/toolbar/toolbar_coordinator_adaptor.mm +++ b/ios/chrome/browser/ui/toolbar/toolbar_coordinator_adaptor.mm
@@ -47,6 +47,15 @@ } } +- (UIResponder<UITextInput>*)fakeboxScribbleForwardingTarget { + for (id<NewTabPageControllerDelegate> coordinator in self.coordinators) { + if (coordinator.fakeboxScribbleForwardingTarget) { + return coordinator.fakeboxScribbleForwardingTarget; + } + } + return nil; +} + #pragma mark - ToolbarCommands - (void)triggerToolsMenuButtonAnimation {
diff --git a/ios/chrome/test/app/tab_test_util.mm b/ios/chrome/test/app/tab_test_util.mm index 6750d9c4..f2d7cdf 100644 --- a/ios/chrome/test/app/tab_test_util.mm +++ b/ios/chrome/test/app/tab_test_util.mm
@@ -18,7 +18,6 @@ #import "ios/chrome/browser/ui/commands/open_new_tab_command.h" #import "ios/chrome/browser/ui/main/scene_controller.h" #import "ios/chrome/browser/ui/main/scene_controller_testing.h" -#import "ios/chrome/browser/ui/tab_grid/tab_switcher.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" #import "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_usage_enabler/web_usage_enabler_browser_agent.h" @@ -58,10 +57,8 @@ Browser* browser = GetForegroundActiveScene().interfaceProvider.mainInterface.browser; UrlLoadParams params = UrlLoadParams::InNewTab(GURL(kChromeUINewTabURL)); - [GetForegroundActiveSceneController().tabSwitcher - dismissWithNewTabAnimationToBrowser:browser - withUrlLoadParams:params - atIndex:INT_MAX]; + [GetForegroundActiveSceneController() addANewTabAndPresentBrowser:browser + withURLLoadParams:params]; return; } id<ApplicationCommands, BrowserCommands> handler = @@ -95,10 +92,8 @@ Browser* browser = GetForegroundActiveScene() .interfaceProvider.incognitoInterface.browser; UrlLoadParams params = UrlLoadParams::InNewTab(GURL(kChromeUINewTabURL)); - [GetForegroundActiveSceneController().tabSwitcher - dismissWithNewTabAnimationToBrowser:browser - withUrlLoadParams:params - atIndex:INT_MAX]; + [GetForegroundActiveSceneController() addANewTabAndPresentBrowser:browser + withURLLoadParams:params]; return; } id<ApplicationCommands, BrowserCommands> handler =
diff --git a/ios/chrome/test/data/policy/policy_test_cases.json b/ios/chrome/test/data/policy/policy_test_cases.json index f7407efb..e478fcd 100644 --- a/ios/chrome/test/data/policy/policy_test_cases.json +++ b/ios/chrome/test/data/policy/policy_test_cases.json
@@ -46,6 +46,8 @@ ] }, + "CloudManagementEnrollmentToken": {}, + "CloudReportingEnabled": { "os": [ "ios" ], "policy_pref_mapping_test": [
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 ecf3841..37917c4 100644 --- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h +++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
@@ -154,38 +154,28 @@ // Returns YES if |identity| is valid and if the service has it in its list of // identitites. 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); - 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); - virtual ChromeIdentity* GetIdentityWithGaiaIDTemporary( - const std::string& gaia_id) const; // Returns the canonicalized emails for all identities. 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(); - virtual bool HasIdentitiesTemporary() const; // Returns all ChromeIdentity objects in an array. 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(); - virtual NSArray* GetAllIdentitiesSortedForDisplayTemporary() const; // Forgets the given identity on the device. This method logs the user out. // It is asynchronous because it needs to contact the server to revoke the
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 09254cd..c4c1aab 100644 --- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm +++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
@@ -62,66 +62,33 @@ } bool ChromeIdentityService::IsValidIdentity(ChromeIdentity* identity) { - return IsValidIdentityTemporary(identity); -} - -bool ChromeIdentityService::IsValidIdentityTemporary( - ChromeIdentity* identity) const { return false; } ChromeIdentity* ChromeIdentityService::GetIdentityWithEmail( const std::string& email) { - return GetIdentityWithEmailTemporary(email); -} - -ChromeIdentity* ChromeIdentityService::GetIdentityWithEmailTemporary( - const std::string& email) const { return nil; } ChromeIdentity* ChromeIdentityService::GetIdentityWithGaiaID( const std::string& gaia_id) { - return GetIdentityWithGaiaIDTemporary(gaia_id); -} - -ChromeIdentity* ChromeIdentityService::GetIdentityWithGaiaIDTemporary( - const std::string& gaia_id) const { return nil; } std::vector<std::string> ChromeIdentityService::GetCanonicalizeEmailsForAllIdentities() { - return GetCanonicalizeEmailsForAllIdentitiesTemporary(); -} - -std::vector<std::string> -ChromeIdentityService::GetCanonicalizeEmailsForAllIdentitiesTemporary() const { return std::vector<std::string>(); } bool ChromeIdentityService::HasIdentities() { - return HasIdentitiesTemporary(); -} - -bool ChromeIdentityService::HasIdentitiesTemporary() const { return false; } NSArray* ChromeIdentityService::GetAllIdentities() { - return GetAllIdentitiesTemporary(); -} - -NSArray* ChromeIdentityService::GetAllIdentitiesTemporary() const { return nil; } NSArray* ChromeIdentityService::GetAllIdentitiesSortedForDisplay() { - return GetAllIdentitiesSortedForDisplayTemporary(); -} - -NSArray* ChromeIdentityService::GetAllIdentitiesSortedForDisplayTemporary() - const { return nil; }
diff --git a/ios/web/navigation/resources/error_page_loaded.html b/ios/web/navigation/resources/error_page_loaded.html index aaa885b1..be36022 100644 --- a/ios/web/navigation/resources/error_page_loaded.html +++ b/ios/web/navigation/resources/error_page_loaded.html
@@ -18,17 +18,8 @@ } else { load(); } - // Display failed URL and error info. - window.addEventListener('load', () => { - document.getElementById('failedUrl').textContent = failedUrl; - let error = params.get('error'); - document.getElementById('error').textContent = error; - }); </script> </head> <body> - <h1>Error page loaded by [WKWebview loadFileURL:allowingReadAccessToURL:]</h1> - <h2 id='failedUrl'></h2> - <h2 id='error'></h2> </body> </html>
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 3897dd7..2712a623 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -862,6 +862,15 @@ } - (void)createFullPagePDFWithCompletion:(void (^)(NSData*))completionBlock { + // Invoke the |completionBlock| with nil rather than a blank PDF for certain + // URLs. + const GURL& URL = self.webState->GetLastCommittedURL(); + if (!URL.is_valid() || web::GetWebClient()->IsAppSpecificURL(URL)) { + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock(nil); + }); + return; + } web::CreateFullPagePdf(self.webView, base::BindOnce(completionBlock)); }
diff --git a/ios/web/web_state/web_state_unittest.mm b/ios/web/web_state/web_state_unittest.mm index fdf37e12..f0702669 100644 --- a/ios/web/web_state/web_state_unittest.mm +++ b/ios/web/web_state/web_state_unittest.mm
@@ -218,18 +218,29 @@ } // Tests that the create PDF method retuns an PDF of a rendered html page. -TEST_F(WebStateTest, CreateFullPagePdf) { - CGFloat kSaveAreaTopInset = - UIApplication.sharedApplication.keyWindow.safeAreaInsets.top; +TEST_F(WebStateTest, CreateFullPagePdf_ValidURL) { + // Load a URL and some HTML in the WebState. + NSString* data_html = + @"<html><div style='background-color:#FF0000; width:50%; " + "height:100%;'></div></html>"; + GURL url("https://www.chromium.org"); + web_state()->LoadData([data_html dataUsingEncoding:NSUTF8StringEncoding], + @"text/html", url); - ASSERT_TRUE(LoadHtml("<html><div style='background-color:#FF0000; width:50%; " - "height:100%;'></div></html>")); + NavigationManager::WebLoadParams load_params(url); + web_state()->GetNavigationManager()->LoadURLWithParams(load_params); + ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForPageLoadTimeout, ^bool { + return web_state()->GetLastCommittedURL() == url; + })); + + // Add the subview. Since it does not get immediately painted, adding a small + // delay is necessary. [[[UIApplication sharedApplication] keyWindow] addSubview:web_state()->GetView()]; - // The subview is added but not immediately painted, so a small delay is - // necessary. base::test::ios::SpinRunLoopWithMinDelay(base::TimeDelta::FromSecondsD(0.2)); + // Create a PDF for this page and validate the data. __block NSData* callback_data = nil; web_state()->CreateFullPagePdf(base::BindOnce(^(NSData* pdf_document_data) { callback_data = [pdf_document_data copy]; @@ -245,6 +256,8 @@ CGSize pdf_size = CGPDFPageGetBoxRect(CGPDFDocumentGetPage(pdf, 1), kCGPDFMediaBox).size; + CGFloat kSaveAreaTopInset = + UIApplication.sharedApplication.keyWindow.safeAreaInsets.top; EXPECT_GE(pdf_size.height, UIScreen.mainScreen.bounds.size.height - kSaveAreaTopInset); EXPECT_GE(pdf_size.width, [[UIScreen mainScreen] bounds].size.width); @@ -252,6 +265,42 @@ CGPDFDocumentRelease(pdf); } +// Tests that CreateFullPagePdf invokes completion callback nil when an invalid +// URL is loaded. +TEST_F(WebStateTest, CreateFullPagePdf_InvalidURLs) { + GURL app_specific_url( + base::StringPrintf("%s://app_specific_url", kTestAppSpecificScheme)); + + // Empty URL and app-specific URLs (e.g. app_specific_url) should get nil + // data through the completion callback. + std::vector<GURL> invalid_urls = {GURL(), app_specific_url}; + NSString* data_html = @(kTestPageHTML); + for (auto& url : invalid_urls) { + web_state()->LoadData([data_html dataUsingEncoding:NSUTF8StringEncoding], + @"text/html", url); + + NavigationManager::WebLoadParams load_params(url); + web_state()->GetNavigationManager()->LoadURLWithParams(load_params); + ASSERT_TRUE(base::test::ios::WaitUntilConditionOrTimeout( + base::test::ios::kWaitForPageLoadTimeout, ^bool { + return web_state()->GetLastCommittedURL() == url; + })); + + __block NSData* callback_data = nil; + __block bool callback_called = false; + web_state()->CreateFullPagePdf(base::BindOnce(^(NSData* pdf_document_data) { + callback_data = [pdf_document_data copy]; + callback_called = true; + })); + + ASSERT_TRUE(WaitUntilConditionOrTimeout(kWaitForPageLoadTimeout, ^bool { + return callback_called; + })); + + ASSERT_FALSE(callback_data); + } +} + // Tests that message sent from main frame triggers the ScriptCommandCallback // with |is_main_frame| = true. TEST_F(WebStateTest, MessageFromMainFrame) {
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 795fab1..b651ced5 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,8 +41,8 @@ password_manager::metrics_util::PasswordAccountStorageUsageLevel ComputePasswordAccountStorageUsageLevel() const override; - void IncrementMoveToAccountRefusedCount() override; - int GetMoveToAccountRefusedCount() const override; + void RecordMoveOfferedToNonOptedInUser() override; + int GetMoveOfferedToNonOptedInUserCount() const override; private: PrefService* const pref_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 2333846..8610a920 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,11 +71,11 @@ kUsingAccountStorage; } -void WebViewPasswordFeatureManager::IncrementMoveToAccountRefusedCount() { +void WebViewPasswordFeatureManager::RecordMoveOfferedToNonOptedInUser() { NOTREACHED(); } -int WebViewPasswordFeatureManager::GetMoveToAccountRefusedCount() const { +int WebViewPasswordFeatureManager::GetMoveOfferedToNonOptedInUserCount() const { NOTREACHED(); return 0; }
diff --git a/media/base/channel_mixing_matrix.cc b/media/base/channel_mixing_matrix.cc index 3ad627e..a8dd62d 100644 --- a/media/base/channel_mixing_matrix.cc +++ b/media/base/channel_mixing_matrix.cc
@@ -105,7 +105,9 @@ continue; int output_ch_index = ChannelOrder(output_layout_, ch); - if (output_ch_index < 0) { + if (output_ch_index < 0 || + (ch == CENTER && input_layout_ == CHANNEL_LAYOUT_MONO && + input_layout_ != output_layout_)) { unaccounted_inputs_.push_back(ch); continue; }
diff --git a/media/base/channel_mixing_matrix_unittest.cc b/media/base/channel_mixing_matrix_unittest.cc index 77a542f..797e920 100644 --- a/media/base/channel_mixing_matrix_unittest.cc +++ b/media/base/channel_mixing_matrix_unittest.cc
@@ -94,6 +94,36 @@ EXPECT_EQ(1.0f, matrix[1][0]); } +TEST(ChannelMixingMatrixTest, MonoToSurround) { + ChannelLayout input_layout = CHANNEL_LAYOUT_MONO; + ChannelLayout output_layout = CHANNEL_LAYOUT_5_1; + ChannelMixingMatrix matrix_builder( + input_layout, ChannelLayoutToChannelCount(input_layout), output_layout, + ChannelLayoutToChannelCount(output_layout)); + std::vector<std::vector<float>> matrix; + bool remapping = matrix_builder.CreateTransformationMatrix(&matrix); + + // Input: mono + // CENTER + // Output: surround LEFT 1 + // RIGHT 1 + // CENTER 0 + // LFE 0 + // SL 0 + // SR 0 + // + EXPECT_FALSE(remapping); + EXPECT_EQ(6u, matrix.size()); + EXPECT_EQ(1u, matrix[0].size()); + EXPECT_EQ(1.0f, matrix[0][0]); + EXPECT_EQ(1u, matrix[1].size()); + EXPECT_EQ(1.0f, matrix[1][0]); + for (size_t i = 2; i < 6; i++) { + EXPECT_EQ(1u, matrix[i].size()); + EXPECT_EQ(0.0f, matrix[i][0]); + } +} + TEST(ChannelMixingMatrixTest, FiveOneToMono) { ChannelLayout input_layout = CHANNEL_LAYOUT_5_1; ChannelLayout output_layout = CHANNEL_LAYOUT_MONO;
diff --git a/media/base/media_switches.cc b/media/base/media_switches.cc index 7a22d84..124c37c 100644 --- a/media/base/media_switches.cc +++ b/media/base/media_switches.cc
@@ -690,12 +690,11 @@ // Enables Media Feeds to allow sites to provide specific recommendations for // users. -const base::Feature kMediaFeeds{"MediaFeeds", - base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kMediaFeeds{"MediaFeeds", base::FEATURE_ENABLED_BY_DEFAULT}; // Enables fetching Media Feeds periodically in the background. const base::Feature kMediaFeedsBackgroundFetching{ - "MediaFeedsBackgroundFetching", base::FEATURE_DISABLED_BY_DEFAULT}; + "MediaFeedsBackgroundFetching", base::FEATURE_ENABLED_BY_DEFAULT}; // Enables checking Media Feeds against safe search to prevent adult content. const base::Feature kMediaFeedsSafeSearch{"MediaFeedsSafeSearch",
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index 44940b5..dbf6480 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -875,7 +875,6 @@ case PIXEL_FORMAT_YUV420P12: case PIXEL_FORMAT_YUV422P12: case PIXEL_FORMAT_YUV444P12: - case PIXEL_FORMAT_P016LE: return 2; case PIXEL_FORMAT_NV12: case PIXEL_FORMAT_NV21: { @@ -883,6 +882,11 @@ DCHECK_LT(plane, base::size(bytes_per_element)); return bytes_per_element[plane]; } + case PIXEL_FORMAT_P016LE: { + static const int bytes_per_element[] = {1, 2}; + DCHECK_LT(plane, base::size(bytes_per_element)); + return bytes_per_element[plane] * 2; + } case PIXEL_FORMAT_YV12: case PIXEL_FORMAT_I420: case PIXEL_FORMAT_I422:
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc index d01f8b1..405c604 100644 --- a/media/base/video_frame_unittest.cc +++ b/media/base/video_frame_unittest.cc
@@ -686,6 +686,7 @@ case PIXEL_FORMAT_YUV420P9: case PIXEL_FORMAT_YUV420P10: case PIXEL_FORMAT_YUV420P12: + case PIXEL_FORMAT_P016LE: EXPECT_EQ(72u, VideoFrame::AllocationSize(format, size)) << VideoPixelFormatToString(format); break; @@ -708,7 +709,6 @@ case PIXEL_FORMAT_I420A: case PIXEL_FORMAT_ABGR: case PIXEL_FORMAT_XBGR: - case PIXEL_FORMAT_P016LE: case PIXEL_FORMAT_XR30: case PIXEL_FORMAT_XB30: EXPECT_EQ(60u, VideoFrame::AllocationSize(format, size))
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl index 730e5fe..e88022b2 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_definition.tmpl
@@ -121,8 +121,11 @@ #if BUILDFLAG(MOJO_TRACE_ENABLED) {%- set qualified_method_name = "%s::%s::%s" % (namespace_as_string, class_name, method.name) %} - {{interface_macros.trace_event("param_", method.parameters, - qualified_method_name)}} + {{interface_macros.trace_event(prefix="param_", + method_parameters=method.parameters, + method_name=qualified_method_name, + parameter_group="input_parameters", + trace_event_type='_BEGIN')}} #endif const bool kExpectsResponse = true; const bool kIsSync = true; @@ -133,13 +136,13 @@ {%- for param in method.parameters -%} , std::move(param_{{param.name}}) {%- endfor %}); -{%- else %} +{%- else %} {#- if method|method_supports_lazy_serialization #} {{interface_macros.build_message_flags(False, "kIsSync", "kExpectsResponse", "kFlags")}} {{interface_macros.build_serialized_message( message_name, "param_%s", params_struct, params_description, "kFlags", "message")}} -{%- endif %} +{%- endif %} {#- if method|method_supports_lazy_serialization #} #if defined(ENABLE_IPC_FUZZER) message.set_interface_name({{class_name}}::Name_); @@ -154,18 +157,27 @@ , out_param_{{param.name}} {%- endfor %})); ignore_result(receiver_->AcceptWithResponder(&message, std::move(responder))); - // TODO(karelkral) Trace the out_ parameters here +#if BUILDFLAG(MOJO_TRACE_ENABLED) + {{interface_macros.trace_event(prefix="out_param_", + method_parameters=method.response_parameters, + method_name=qualified_method_name, + parameter_group="sync_response_parameters", + trace_event_type='_END', + dereference_parameters=True)}} +#endif return result; } -{%- endif %} +{%- endif %} {#- if method.sync #} void {{proxy_name}}::{{method.name}}( {{interface_macros.declare_request_params("in_", method)}}) { #if BUILDFLAG(MOJO_TRACE_ENABLED) {%- set qualified_method_name = "%s::%s::%s" % (namespace_as_string, class_name, method.name) %} - {{interface_macros.trace_event("in_", method.parameters, - qualified_method_name)}} + {{interface_macros.trace_event(prefix="in_", + method_parameters=method.parameters, + method_name=qualified_method_name, + parameter_group="input_parameters")}} #endif {%- if method.response_parameters != None %} const bool kExpectsResponse = true; @@ -321,6 +333,16 @@ void {{class_name}}_{{method.name}}_ProxyToResponder::Run( {{interface_macros.declare_params("in_", method.response_parameters)}}) { +#if BUILDFLAG(MOJO_TRACE_ENABLED) +{%- set qualified_method_name = "(Impl)%s::%s::%sCallback" + % (namespace_as_string, class_name, method.name) %} + {{interface_macros.trace_event(prefix="in_", + method_parameters=method.response_parameters, + method_name=qualified_method_name, + parameter_group="async_response_parameters", + trace_event_type='_BEGIN', + dereference_parameters=False)}} +#endif {%- if method|method_supports_lazy_serialization %} const bool kSerialize = responder_->PrefersSerializedMessages(); auto message = {{response_message_typename}}::Build(kSerialize, is_sync_ @@ -335,8 +357,8 @@ {%- endif %} #if BUILDFLAG(MOJO_TRACE_ENABLED) - TRACE_EVENT1("mojom", "(Impl){{namespace_as_string}}::{{class_name}}::{{method.name}}Callback", - "message", message.name()); + TRACE_EVENT_END1("mojom", "{{qualified_method_name}}", "message", + message.name()); #endif #if defined(ENABLE_IPC_FUZZER)
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl index 0b415c2..6327a10 100644 --- a/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl +++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_macros.tmpl
@@ -24,29 +24,54 @@ {%- endif -%} {%- endmacro -%} -{%- macro trace_event(prefix, method_parameters, qualified_method_name) -%} +{%- macro trace_event(prefix, method_parameters, method_name, parameter_group, + trace_event_type='', dereference_parameters=False) -%} {#- This macro assumes that the argument names are the ones declared by -#} -{#- |declare_request_params|. Namely the |prefix| should be the same here as -#} -{#- in |declare_request_params|. -#} +{#- |declare_request_params/declare_sync_method_params|. Namely the |prefix| -#} +{#- must be the same here as in -#} +{#- |declare_request_params/declare_sync_method_params|. -#} +{#- |trace_event_type| can be set to: -#} +{#- '' just standalone trace. -#} +{#- Parameter names must match |declare_request_params|. -#} +{#- '_BEGIN' input parameters to be later merged, must be before the _END. -#} +{#- Parameter names must match |declare_request_params|. -#} +{#- '_END' merge corresponding sync response parameters. -#} +{#- Parameter names must match |declare_sync_method_params|. -#} +{#- |dereference_parameters| the parameters type is actually |kind*|. -#} {%- if method_parameters -%} - TRACE_EVENT1( - "mojom", "{{qualified_method_name}}", "input_parameters", + TRACE_EVENT{{trace_event_type}}1( + "mojom", "{{method_name}}", "{{parameter_group}}", [&](){ auto value = std::make_unique<base::trace_event::TracedValue>(); base::trace_event::TracedValue* raw_value = value.get(); {%- for param in method_parameters %} -{%- for line in param.kind|write_input_param_for_tracing( - parameter_name=param.name, - cpp_parameter_name=prefix+param.name, - value='raw_value') %} +{%- if dereference_parameters -%} +{%- set cpp_parameter_ptr = prefix + param.name %} +{%- set cpp_parameter_name = "(*%s)" % cpp_parameter_ptr %} + if ({{cpp_parameter_ptr}}) { +{%- for line in param.kind|write_input_param_for_tracing( + parameter_name=param.name, + cpp_parameter_name=cpp_parameter_name, + value='raw_value') %} + {{line}} +{%- endfor %} + } else { + raw_value->SetString("{{param.name}}", "nullptr"); + } +{%- else %} {#- if dereference_parameters #} +{%- for line in param.kind|write_input_param_for_tracing( + parameter_name=param.name, + cpp_parameter_name=prefix+param.name, + value='raw_value') %} {{line}} -{%- endfor -%} +{%- endfor %} +{%- endif %} {#- if dereference_parameters #} {%- endfor %} return value; }()); -{%- else -%} - TRACE_EVENT0("mojom", "{{qualified_method_name}}"); -{%- endif %} +{%- else -%} {#- if method_parameters -#} + TRACE_EVENT{{trace_event_type}}0("mojom", "{{method_name}}"); +{%- endif %} {#- if method_parameters #} {%- endmacro -%} {%- macro declare_sync_method_params(prefix, method) -%}
diff --git a/pdf/pdf.cc b/pdf/pdf.cc index 36d6ed6..ac143f1f 100644 --- a/pdf/pdf.cc +++ b/pdf/pdf.cc
@@ -121,13 +121,16 @@ int bitmap_height, int dpi_x, int dpi_y, + bool stretch_to_bounds, + bool keep_aspect_ratio, bool autorotate, bool use_color) { ScopedSdkInitializer scoped_sdk_initializer(/*enable_v8=*/true); PDFEngineExports* engine_exports = PDFEngineExports::Get(); PDFEngineExports::RenderingSettings settings( - dpi_x, dpi_y, pp::Rect(bitmap_width, bitmap_height), true, false, true, - true, autorotate, use_color); + dpi_x, dpi_y, pp::Rect(bitmap_width, bitmap_height), + /*fit_to_bounds=*/true, stretch_to_bounds, keep_aspect_ratio, + /*center_in_bounds=*/true, autorotate, use_color); return engine_exports->RenderPDFPageToBitmap(pdf_buffer, page_number, settings, bitmap_buffer); }
diff --git a/pdf/pdf.h b/pdf/pdf.h index 4e76f53..66da006 100644 --- a/pdf/pdf.h +++ b/pdf/pdf.h
@@ -136,6 +136,10 @@ // |bitmap_width| is the width of the output bitmap. // |bitmap_height| is the height of the output bitmap. // |dpi_x| and |dpi_y| is the resolution. +// |stretch_to_bounds| specifies whether the output should be stretched to fit +// the supplied |bitmap_width| and |bitmap_height|. +// |keep_aspect_ratio| If any scaling is needed, this parameter specifies +// whether the original aspect ratio of the page is preserved while scaling. // |autorotate| specifies whether the final image should be rotated to match // the output bound. // |use_color| specifies color or grayscale. @@ -147,6 +151,8 @@ int bitmap_height, int dpi_x, int dpi_y, + bool stretch_to_bounds, + bool keep_aspect_ratio, bool autorotate, bool use_color);
diff --git a/remoting/protocol/webrtc_dummy_video_encoder.cc b/remoting/protocol/webrtc_dummy_video_encoder.cc index 58da05e..e8743e09 100644 --- a/remoting/protocol/webrtc_dummy_video_encoder.cc +++ b/remoting/protocol/webrtc_dummy_video_encoder.cc
@@ -19,40 +19,9 @@ #include "third_party/webrtc/api/video_codecs/sdp_video_format.h" #include "third_party/webrtc/media/base/vp9_profile.h" -#if defined(USE_H264_ENCODER) -#include "media/video/h264_parser.h" -#endif - namespace remoting { namespace protocol { -#if defined(USE_H264_ENCODER) -namespace { - -// Populates struct webrtc::RTPFragmentationHeader for H264 codec. -// Each entry specifies the offset and length (excluding start code) of a NALU. -// Returns true if successful. -bool GetRTPFragmentationHeaderH264(webrtc::RTPFragmentationHeader* header, - const uint8_t* data, uint32_t length) { - std::vector<media::H264NALU> nalu_vector; - if (!media::H264Parser::ParseNALUs(data, length, &nalu_vector)) { - // H264Parser::ParseNALUs() has logged the errors already. - return false; - } - - // TODO(zijiehe): Find a right place to share the following logic between - // //content and //remoting. - header->VerifyAndAllocateFragmentationHeader(nalu_vector.size()); - for (size_t i = 0; i < nalu_vector.size(); ++i) { - header->fragmentationOffset[i] = nalu_vector[i].data - data; - header->fragmentationLength[i] = nalu_vector[i].size; - } - return true; -} - -} // namespace -#endif - WebrtcDummyVideoEncoder::WebrtcDummyVideoEncoder( scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, base::WeakPtr<VideoChannelStateObserver> video_channel_state_observer, @@ -201,25 +170,8 @@ NOTREACHED(); } - webrtc::RTPFragmentationHeader header; - if (frame.codec == webrtc::kVideoCodecH264) { -#if defined(USE_H264_ENCODER) - if (!GetRTPFragmentationHeaderH264(&header, buffer, buffer_size)) { - return webrtc::EncodedImageCallback::Result( - webrtc::EncodedImageCallback::Result::ERROR_SEND_FAILED); - } -#else - NOTREACHED(); -#endif - } else { - header.VerifyAndAllocateFragmentationHeader(1); - header.fragmentationOffset[0] = 0; - header.fragmentationLength[0] = buffer_size; - } - DCHECK(encoded_callback_); - return encoded_callback_->OnEncodedImage(encoded_image, &codec_specific_info, - &header); + return encoded_callback_->OnEncodedImage(encoded_image, &codec_specific_info); } webrtc::VideoEncoder::EncoderInfo WebrtcDummyVideoEncoder::GetEncoderInfo()
diff --git a/testing/buildbot/chrome.ci.json b/testing/buildbot/chrome.ci.json index 8b83741..12c386f0 100644 --- a/testing/buildbot/chrome.ci.json +++ b/testing/buildbot/chrome.ci.json
@@ -3656,7 +3656,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "cores": "2", + "cores": "8", "os": "Ubuntu-16.04" } ], @@ -3787,7 +3787,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "cores": "2", + "cores": "8", "os": "Ubuntu-16.04" } ],
diff --git a/testing/buildbot/chromium.dev.json b/testing/buildbot/chromium.dev.json index 035dfe0..1f6e20d9 100644 --- a/testing/buildbot/chromium.dev.json +++ b/testing/buildbot/chromium.dev.json
@@ -642,7 +642,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "cores": "2", + "cores": "8", "os": "Ubuntu-16.04" } ], @@ -773,7 +773,7 @@ "can_use_on_swarming_builders": true, "dimension_sets": [ { - "cores": "2", + "cores": "8", "os": "Ubuntu-16.04" } ],
diff --git a/testing/buildbot/filters/bfcache.browser_tests.filter b/testing/buildbot/filters/bfcache.browser_tests.filter index abb1eaf..2d8f82a 100644 --- a/testing/buildbot/filters/bfcache.browser_tests.filter +++ b/testing/buildbot/filters/bfcache.browser_tests.filter
@@ -1,16 +1 @@ # These tests currently fail when run with --enable-features=BackForwardCache - -# Test are using a custom NavigateToURL function waiting for the old -# RenderFrameHost to be deleted. This won't happen. --ProcessManagementTest.ExtensionProcessBalancing --ProcessManagerBrowserTest.NoBackgroundPage - -# Test goes back and forth in between a "preview" page and a "normal" page. -# When going back to the first page, it expected to be loaded as a "normal" page, -# but it isn't reloaded at all with the BackForwardCache. --PreviewsLitePageRedirectServerBrowserTest.LitePagePreviewsNavigation/* - -# Flaky on the bots, need to be investigated, see https://crbug.com/1010870. -# 16/100 failures. -# https://chromium-swarm.appspot.com/task?id=48104c14d9892f10 --BookmarksCommandManagerTest.All
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 798a6ed..2897562 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -893,7 +893,7 @@ 'swarming': { 'dimension_sets': [ { - 'cores': '2', + 'cores': '8', }, ], },
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 9e0d9a6..bb4c23e 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1369,9 +1369,9 @@ ], "experiments": [ { - "name": "Enabled10_v3", + "name": "Enabled8_v4", "params": { - "max_shared_ops": "10" + "max_shared_ops": "8" }, "enable_features": [ "CacheStorageParallelOps",
diff --git a/third_party/abseil-cpp/patches/0002-delete-unprefixed-annotations.patch b/third_party/abseil-cpp/patches/0002-delete-unprefixed-annotations.patch new file mode 100644 index 0000000..0434896 --- /dev/null +++ b/third_party/abseil-cpp/patches/0002-delete-unprefixed-annotations.patch
@@ -0,0 +1,27 @@ +diff --git a/third_party/abseil-cpp/absl/base/dynamic_annotations.h b/third_party/abseil-cpp/absl/base/dynamic_annotations.h +index 1444dc48e283..6687291cade3 100644 +--- a/third_party/abseil-cpp/absl/base/dynamic_annotations.h ++++ b/third_party/abseil-cpp/absl/base/dynamic_annotations.h +@@ -49,9 +49,6 @@ + + #include "absl/base/config.h" + +-// TODO(rogeeff): Remove after the backward compatibility period. +-#include "absl/base/internal/dynamic_annotations.h" // IWYU pragma: export +- + // ------------------------------------------------------------------------- + // Decide which features are enabled + +diff --git a/third_party/abseil-cpp/absl/base/thread_annotations.h b/third_party/abseil-cpp/absl/base/thread_annotations.h +index 5f51c0c2d2d5..10b9bde551a7 100644 +--- a/third_party/abseil-cpp/absl/base/thread_annotations.h ++++ b/third_party/abseil-cpp/absl/base/thread_annotations.h +@@ -35,8 +35,6 @@ + #define ABSL_BASE_THREAD_ANNOTATIONS_H_ + + #include "absl/base/config.h" +-// TODO(mbonadei): Remove after the backward compatibility period. +-#include "absl/base/internal/thread_annotations.h" // IWYU pragma: export + + #if defined(__clang__) + #define ABSL_INTERNAL_THREAD_ANNOTATION_ATTRIBUTE(x) __attribute__((x))
diff --git a/third_party/abseil-cpp/roll_abseil.py b/third_party/abseil-cpp/roll_abseil.py new file mode 100755 index 0000000..cc22b73 --- /dev/null +++ b/third_party/abseil-cpp/roll_abseil.py
@@ -0,0 +1,133 @@ +#!/usr/bin/env python + +# NOTE: This script requires python 3. + +"""Script to do the first step of Abseil roll into chromium. +""" + +import logging +import os +import re +import subprocess +import tempfile +from datetime import datetime + +ABSL_URI = 'https://github.com/abseil/abseil-cpp.git' + +def _PullAbseil(abseil_dir): + logging.info('Updating abseil...') + subprocess.check_call(['git', 'clone', ABSL_URI], + cwd=abseil_dir) + +def _SyncChromium(chromium_dir): + logging.info('Updating chromium...') + subprocess.check_call(['git', 'checkout', 'master'], cwd=chromium_dir) + subprocess.check_call(['git', 'pull', '--rebase'], cwd=chromium_dir) + subprocess.check_call(['gclient', 'sync'], cwd=chromium_dir) + + +def _UpdateChromiumReadme(readme_filename, abseil_dir): + logging.info('Updating ' + readme_filename) + + stdout = subprocess.check_output(['git', 'log', '-n1', '--pretty=short'], + cwd=abseil_dir) + new_revision = re.search('commit\\s(.{40})', str(stdout)).group(1) + + with open(readme_filename, 'r+') as f: + content = f.read() + prefix = 'Revision: ' + pos = content.find(prefix) + assert(pos > 0) + pos = pos + len(prefix) + old_revision = content[pos:pos+40] + f.seek(pos) + f.write(new_revision) + + logging.info('Abseil old revision is ' + old_revision) + logging.info('Abseil new revision is ' + new_revision) + return old_revision[0:10] + '..' + new_revision[0:10] + + +def _UpdateAbseilInChromium(abseil_dir, chromium_dir): + logging.info('Syncing abseil in chromium/src/third_party...') + exclude = [ + '*BUILD.gn', + 'README.chromium', + 'OWNERS', + '.gitignore', + '.git', + '*.gni', + '*clang-format', + 'patches/*', + 'patches', + 'absl_hardening_test.cc', + 'roll_abseil.py', + 'generate_def_files.py', + '*.def', + ] + params = ['rsync', '-aP', abseil_dir, os.path.join(chromium_dir, 'third_party'), '--delete'] + for e in exclude: + params.append('--exclude={}'.format(e)) + subprocess.check_call(params, cwd=chromium_dir) + + +def _PatchAbseil(abseil_in_chromium_dir): + logging.info('Patching abseil...') + for patch in os.listdir(os.path.join(abseil_in_chromium_dir, 'patches')): + subprocess.check_call(['patch', '--strip', '1', '-i', os.path.join(abseil_in_chromium_dir, 'patches', patch)]) + + os.remove(os.path.join(abseil_in_chromium_dir, 'absl', 'base', 'internal', 'thread_annotations.h')) + os.remove(os.path.join(abseil_in_chromium_dir, 'absl', 'base', 'internal', 'dynamic_annotations.h')) + #Chromium complains when a script file doesn't have execute permission. + os.chmod(os.path.join(abseil_in_chromium_dir, 'conanfile.py'), 0o750) + + +def _Commit(chromium_dir, hash_diff): + logging.info('Commit...') + desc="""Roll abseil_revision {0} + +Change Log: +https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+log/{0} +Full diff: +https://chromium.googlesource.com/external/github.com/abseil/abseil-cpp/+/{0} +Bug: None""".format(hash_diff) + + subprocess.check_call(['git', 'add', 'third_party/abseil-cpp'], cwd=chromium_dir) + subprocess.check_call(['git', 'commit', '-m', desc], cwd=chromium_dir) + + logging.info('Upload...') + subprocess.check_call(['git', 'cl', 'upload', '-m', desc, '--bypass-hooks'], cwd=chromium_dir) + + +def _Roll(): + chromium_dir = os.getcwd() + abseil_in_chromium_dir = os.path.join(chromium_dir, 'third_party', 'abseil-cpp') + _SyncChromium(chromium_dir) + + branch_name = datetime.today().strftime('rolling-absl-%Y%m%d') + logging.info('Creating branch ' + branch_name + ' for the roll...') + subprocess.check_call(['git', 'checkout', '-b', branch_name], cwd=chromium_dir) + + with tempfile.TemporaryDirectory() as abseil_root: + _PullAbseil(abseil_root) + abseil_dir = os.path.join(abseil_root, 'abseil-cpp') + _UpdateAbseilInChromium(abseil_dir, chromium_dir) + hash_diff = _UpdateChromiumReadme(os.path.join(abseil_in_chromium_dir, 'README.chromium'), + abseil_dir) + + _PatchAbseil(abseil_in_chromium_dir) + _Commit(chromium_dir, hash_diff) + + +if __name__ == '__main__': + logging.getLogger().setLevel(logging.INFO) + + if os.getcwd().endswith('src') and os.path.exists('chrome/browser'): + _Roll() + + logging.info("Next step is manual: Fix BUILD.gn files to match BUILD.bazel changes.") + logging.info("After that run generate_def_files.py. ") + else: + logging.error('Run this script from a chromium/src/ directory.') + +
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index 241ddda8..444b671 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -581,8 +581,7 @@ // 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. Disabling -// AppCache will also delete any AppCache data from the profile directory. +// api, regardless of the presence of valid origin trial tokens. 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/common/tokens/multi_token_unittest.cc b/third_party/blink/common/tokens/multi_token_unittest.cc index 224304df..1305e68 100644 --- a/third_party/blink/common/tokens/multi_token_unittest.cc +++ b/third_party/blink/common/tokens/multi_token_unittest.cc
@@ -82,7 +82,7 @@ EXPECT_FALSE(token1.Is<BarToken>()); // Test copy construction. - BarToken bar = BarToken::Create(); + BarToken bar = BarToken(); FooBarToken token2(bar); EXPECT_EQ(token2.value(), bar.value()); EXPECT_FALSE(token2.value().is_empty());
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 12376b8..2500559 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2702,6 +2702,8 @@ kWindowClosed = 3371, kWrongBaselineOfMultiLineButton = 3372, kWrongBaselineOfEmptyLineButton = 3373, + kV8RTCRtpTransceiver_Stopped_AttributeGetter = 3374, + kV8RTCRtpTransceiver_Stop_Method = 3375, // Add new features immediately above this line. Don't change assigned // numbers of any item, and don't reuse removed slots.
diff --git a/third_party/blink/public/web/web_local_frame_client.h b/third_party/blink/public/web/web_local_frame_client.h index 6d2a073..e07d735 100644 --- a/third_party/blink/public/web/web_local_frame_client.h +++ b/third_party/blink/public/web/web_local_frame_client.h
@@ -221,8 +221,7 @@ CrossVariantMojoAssociatedRemote<mojom::PortalClientInterfaceBase> client_endpoint, const WebElement& portal_element) { - return std::pair<WebRemoteFrame*, PortalToken>(nullptr, - blink::PortalToken::Null()); + return std::pair<WebRemoteFrame*, PortalToken>(nullptr, PortalToken()); } // Request the creation of a remote frame which corresponds to an existing
diff --git a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py index eaca86d6..73ddc4bc0 100644 --- a/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py +++ b/third_party/blink/renderer/bindings/scripts/bind_gen/interface.py
@@ -1223,8 +1223,7 @@ elif (cg_context.attribute_set and not ("Setter" in values)): return None - return TextNode("${blink_receiver}->ReportCoopAccess" - "(${isolate}, ${property_name});") + return TextNode("${blink_receiver}->ReportCoopAccess(${property_name});") def make_report_deprecate_as(cg_context):
diff --git a/third_party/blink/renderer/core/dom/attribute.h b/third_party/blink/renderer/core/dom/attribute.h index 1869c50..3db098e 100644 --- a/third_party/blink/renderer/core/dom/attribute.h +++ b/third_party/blink/renderer/core/dom/attribute.h
@@ -39,8 +39,8 @@ DISALLOW_NEW(); public: - Attribute(const QualifiedName& name, const AtomicString& value) - : name_(name), value_(value) {} + Attribute(const QualifiedName& name, AtomicString value) + : name_(name), value_(std::move(value)) {} // NOTE: The references returned by these functions are only valid for as long // as the Attribute stays in place. For example, calling a function that @@ -56,7 +56,10 @@ bool Matches(const QualifiedName&) const; bool MatchesCaseInsensitive(const QualifiedName&) const; - void SetValue(const AtomicString& value) { value_ = value; } + void SetValue(AtomicString value) { value_ = std::move(value); } + AtomicString ExchangeValue(AtomicString value) { + return std::exchange(value_, std::move(value)); + } // Note: This API is only for HTMLTreeBuilder. It is not safe to change the // name of an attribute once parseAttribute has been called as DOM
diff --git a/third_party/blink/renderer/core/dom/attribute_collection.h b/third_party/blink/renderer/core/dom/attribute_collection.h index c403f85..30df3cc 100644 --- a/third_party/blink/renderer/core/dom/attribute_collection.h +++ b/third_party/blink/renderer/core/dom/attribute_collection.h
@@ -160,13 +160,15 @@ attributes) {} // These functions do no error/duplicate checking. - void Append(const QualifiedName&, const AtomicString& value); + const AtomicString& Append(const QualifiedName&, AtomicString value); void Remove(unsigned index); }; -inline void MutableAttributeCollection::Append(const QualifiedName& name, - const AtomicString& value) { - attributes_.push_back(Attribute(name, value)); +inline const AtomicString& MutableAttributeCollection::Append( + const QualifiedName& name, + AtomicString value) { + attributes_.emplace_back(name, std::move(value)); + return attributes_.back().Value(); } inline void MutableAttributeCollection::Remove(unsigned index) {
diff --git a/third_party/blink/renderer/core/dom/element-hot.cc b/third_party/blink/renderer/core/dom/element-hot.cc index 1ff9542..87b14332 100644 --- a/third_party/blink/renderer/core/dom/element-hot.cc +++ b/third_party/blink/renderer/core/dom/element-hot.cc
@@ -120,45 +120,45 @@ g_null_atom)); } -void Element::setAttribute(const QualifiedName& name, - const AtomicString& value) { +void Element::setAttribute(const QualifiedName& name, AtomicString value) { SynchronizeAttribute(name); wtf_size_t index = GetElementData() ? GetElementData()->Attributes().FindIndex(name) : kNotFound; - SetAttributeInternal(index, name, value, + SetAttributeInternal(index, name, std::move(value), kNotInSynchronizationOfLazyAttribute); } void Element::setAttribute(const QualifiedName& name, - const AtomicString& value, + AtomicString value, ExceptionState& exception_state) { SynchronizeAttribute(name); wtf_size_t index = GetElementData() ? GetElementData()->Attributes().FindIndex(name) : kNotFound; - String trusted_value = - TrustedTypesCheckFor(ExpectedTrustedTypeForAttribute(name), value, - GetExecutionContext(), exception_state); + AtomicString trusted_value(TrustedTypesCheckFor( + ExpectedTrustedTypeForAttribute(name), std::move(value), + GetExecutionContext(), exception_state)); if (exception_state.HadException()) return; - SetAttributeInternal(index, name, AtomicString(trusted_value), + SetAttributeInternal(index, name, std::move(trusted_value), kNotInSynchronizationOfLazyAttribute); } void Element::SetSynchronizedLazyAttribute(const QualifiedName& name, - const AtomicString& value) { + AtomicString value) { wtf_size_t index = GetElementData() ? GetElementData()->Attributes().FindIndex(name) : kNotFound; - SetAttributeInternal(index, name, value, kInSynchronizationOfLazyAttribute); + SetAttributeInternal(index, name, std::move(value), + kInSynchronizationOfLazyAttribute); } void Element::SetAttributeHinted(const AtomicString& local_name, WTF::AtomicStringTable::WeakResult hint, - const AtomicString& value, + AtomicString value, ExceptionState& exception_state) { if (!Document::IsValidName(local_name)) { exception_state.ThrowDOMException( @@ -172,13 +172,13 @@ QualifiedName q_name = QualifiedName::Null(); std::tie(index, q_name) = LookupAttributeQNameHinted(local_name, hint); - String trusted_value = - TrustedTypesCheckFor(ExpectedTrustedTypeForAttribute(q_name), value, - GetExecutionContext(), exception_state); + AtomicString trusted_value(TrustedTypesCheckFor( + ExpectedTrustedTypeForAttribute(q_name), std::move(value), + GetExecutionContext(), exception_state)); if (exception_state.HadException()) return; - SetAttributeInternal(index, q_name, AtomicString(trusted_value), + SetAttributeInternal(index, q_name, std::move(trusted_value), kNotInSynchronizationOfLazyAttribute); } @@ -199,19 +199,19 @@ wtf_size_t index; QualifiedName q_name = QualifiedName::Null(); std::tie(index, q_name) = LookupAttributeQNameHinted(local_name, hint); - String value = TrustedTypesCheckFor(ExpectedTrustedTypeForAttribute(q_name), - string_or_trusted, GetExecutionContext(), - exception_state); + AtomicString value(TrustedTypesCheckFor( + ExpectedTrustedTypeForAttribute(q_name), string_or_trusted, + GetExecutionContext(), exception_state)); if (exception_state.HadException()) return; - SetAttributeInternal(index, q_name, AtomicString(value), + SetAttributeInternal(index, q_name, std::move(value), kNotInSynchronizationOfLazyAttribute); } ALWAYS_INLINE void Element::SetAttributeInternal( wtf_size_t index, const QualifiedName& name, - const AtomicString& new_value, + AtomicString new_value, SynchronizationOfLazyAttribute in_synchronization_of_lazy_attribute) { if (new_value.IsNull()) { if (index != kNotFound) @@ -220,25 +220,32 @@ } if (index == kNotFound) { - AppendAttributeInternal(name, new_value, + AppendAttributeInternal(name, std::move(new_value), in_synchronization_of_lazy_attribute); return; } const Attribute& existing_attribute = GetElementData()->Attributes().at(index); - AtomicString existing_attribute_value = existing_attribute.Value(); - QualifiedName existing_attribute_name = existing_attribute.GetName(); if (!in_synchronization_of_lazy_attribute) { - WillModifyAttribute(existing_attribute_name, existing_attribute_value, - new_value); + WillModifyAttribute(existing_attribute.GetName(), + existing_attribute.Value(), new_value); } - if (new_value != existing_attribute_value) - EnsureUniqueElementData().Attributes().at(index).SetValue(new_value); + + AtomicString old_value_storage; // Keep the old value alive in an update. + const AtomicString* old_val_ptr = &existing_attribute.Value(); + const AtomicString* new_val_ptr = &new_value; + if (new_value != *old_val_ptr) { + Attribute& attribute = EnsureUniqueElementData().Attributes().at(index); + old_value_storage = attribute.ExchangeValue(std::move(new_value)); + old_val_ptr = &old_value_storage; + new_val_ptr = &attribute.Value(); + } + if (!in_synchronization_of_lazy_attribute) { - DidModifyAttribute(existing_attribute_name, existing_attribute_value, - new_value); + DidModifyAttribute(existing_attribute.GetName(), *old_val_ptr, + *new_val_ptr); } } @@ -270,9 +277,9 @@ SynchronizeAllAttributes(); const UniqueElementData& element_data = EnsureUniqueElementData(); - String value = TrustedTypesCheckFor( + AtomicString value(TrustedTypesCheckFor( ExpectedTrustedTypeForAttribute(attr_node->GetQualifiedName()), - attr_node->value(), GetExecutionContext(), exception_state); + attr_node->value(), GetExecutionContext(), exception_state)); if (exception_state.HadException()) return nullptr; @@ -301,8 +308,7 @@ } } - SetAttributeInternal(index, attr_node->GetQualifiedName(), - AtomicString(value), + SetAttributeInternal(index, attr_node->GetQualifiedName(), std::move(value), kNotInSynchronizationOfLazyAttribute); attr_node->AttachToElement(this, local_name);
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index d6afcd40..3ed7bcb 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -3788,13 +3788,13 @@ exception_state)) return; - String value = TrustedTypesCheckFor( + AtomicString value(TrustedTypesCheckFor( ExpectedTrustedTypeForAttribute(parsed_name), string_or_trusted, - GetExecutionContext(), exception_state); + GetExecutionContext(), exception_state)); if (exception_state.HadException()) return; - setAttribute(parsed_name, AtomicString(value)); + setAttribute(parsed_name, std::move(value)); } void Element::RemoveAttributeInternal( @@ -3828,13 +3828,14 @@ void Element::AppendAttributeInternal( const QualifiedName& name, - const AtomicString& value, + AtomicString value, SynchronizationOfLazyAttribute in_synchronization_of_lazy_attribute) { if (!in_synchronization_of_lazy_attribute) WillModifyAttribute(name, g_null_atom, value); - EnsureUniqueElementData().Attributes().Append(name, value); + const AtomicString& stored_value = + EnsureUniqueElementData().Attributes().Append(name, std::move(value)); if (!in_synchronization_of_lazy_attribute) - DidAddAttribute(name, value); + DidAddAttribute(name, stored_value); } void Element::removeAttributeNS(const AtomicString& namespace_uri,
diff --git a/third_party/blink/renderer/core/dom/element.h b/third_party/blink/renderer/core/dom/element.h index 7d6143be..d21249ab 100644 --- a/third_party/blink/renderer/core/dom/element.h +++ b/third_party/blink/renderer/core/dom/element.h
@@ -162,12 +162,9 @@ // Passing g_null_atom as the second parameter removes the attribute when // calling either of these set methods. - void setAttribute(const QualifiedName&, const AtomicString& value); - void setAttribute(const QualifiedName&, - const AtomicString& value, - ExceptionState&); - void SetSynchronizedLazyAttribute(const QualifiedName&, - const AtomicString& value); + void setAttribute(const QualifiedName&, AtomicString value); + void setAttribute(const QualifiedName&, AtomicString value, ExceptionState&); + void SetSynchronizedLazyAttribute(const QualifiedName&, AtomicString value); void removeAttribute(const QualifiedName&); @@ -233,7 +230,7 @@ void setAttribute(const AtomicString& name, AtomicString value, ExceptionState& exception_state = ASSERT_NO_EXCEPTION) { - SetAttributeHinted(name, WeakLowercaseIfNecessary(name), value, + SetAttributeHinted(name, WeakLowercaseIfNecessary(name), std::move(value), exception_state); } @@ -265,7 +262,7 @@ bool toggleAttribute(const AtomicString&, bool force, ExceptionState&); const AtomicString& GetIdAttribute() const; - void SetIdAttribute(const AtomicString&); + void SetIdAttribute(AtomicString); const AtomicString& GetNameAttribute() const; const AtomicString& GetClassAttribute() const; @@ -1102,10 +1099,10 @@ void SetAttributeInternal(wtf_size_t index, const QualifiedName&, - const AtomicString& value, + AtomicString value, SynchronizationOfLazyAttribute); void AppendAttributeInternal(const QualifiedName&, - const AtomicString& value, + AtomicString value, SynchronizationOfLazyAttribute); void RemoveAttributeInternal(wtf_size_t index, SynchronizationOfLazyAttribute); @@ -1129,7 +1126,7 @@ WTF::AtomicStringTable::WeakResult hint) const; void SetAttributeHinted(const AtomicString& name, WTF::AtomicStringTable::WeakResult hint, - const AtomicString& value, + AtomicString value, ExceptionState& = ASSERT_NO_EXCEPTION); void SetAttributeHinted( const AtomicString& name, @@ -1329,8 +1326,8 @@ return FastGetAttribute(html_names::kClassAttr); } -inline void Element::SetIdAttribute(const AtomicString& value) { - setAttribute(html_names::kIdAttr, value); +inline void Element::SetIdAttribute(AtomicString value) { + setAttribute(html_names::kIdAttr, std::move(value)); } inline const SpaceSplitString& Element::ClassNames() const {
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index 0360e07b..831ce5cc 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -245,7 +245,8 @@ // Creates a portal for the |HTMLPortalElement| and binds the other end of the // |mojo::PendingAssociatedReceiver<mojom::blink::Portal>|. Returns a pair of - // a RemoteFrame and a token that identifies the portal. + // a RemoteFrame and a token that identifies the portal. If the returned + // RemoteFrame is nullptr, then the PortalToken is meaningless. virtual std::pair<RemoteFrame*, PortalToken> CreatePortal( HTMLPortalElement*, mojo::PendingAssociatedReceiver<mojom::blink::Portal>,
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index f1d3ff00..ae92c1c2 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -686,7 +686,7 @@ } } - root.UpdateLayout(); + ToLayoutBox(root).LayoutSubtreeRoot(); return true; } @@ -1708,6 +1708,7 @@ void LocalFrameView::ScheduleRelayoutOfSubtree(LayoutObject* relayout_root) { DCHECK(frame_->View() == this); + DCHECK(relayout_root->IsBox()); // TODO(crbug.com/590856): It's still broken when we choose not to crash when // the check fails.
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.cc b/third_party/blink/renderer/core/html/portal/html_portal_element.cc index 443a1923..4ad4c5c 100644 --- a/third_party/blink/renderer/core/html/portal/html_portal_element.cc +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.cc
@@ -55,7 +55,7 @@ HTMLPortalElement::HTMLPortalElement( Document& document, - const PortalToken& portal_token, + const PortalToken* portal_token, mojo::PendingAssociatedRemote<mojom::blink::Portal> remote_portal, mojo::PendingAssociatedReceiver<mojom::blink::PortalClient> portal_client_receiver) @@ -65,12 +65,13 @@ SchedulingPolicy::Feature::kPortal, {SchedulingPolicy::RecordMetricsForBackForwardCache()})) { if (remote_portal) { + DCHECK(portal_token); was_just_adopted_ = true; DCHECK(CanHaveGuestContents()) << "<portal> element was created with an existing contents but is not " "permitted to have one"; portal_ = MakeGarbageCollected<PortalContents>( - *this, portal_token, std::move(remote_portal), + *this, *portal_token, std::move(remote_portal), std::move(portal_client_receiver)); } UseCounter::Count(document, WebFeature::kHTMLPortalElement); @@ -391,7 +392,7 @@ const PortalToken& HTMLPortalElement::GetToken() const { DCHECK(portal_ && portal_->IsValid()); - return portal_->GetToken(); + return portal_->GetToken().value(); } Node::InsertionNotificationRequest HTMLPortalElement::InsertedInto( @@ -461,6 +462,7 @@ std::tie(portal_frame, portal_token) = GetDocument().GetFrame()->Client()->CreatePortal( this, std::move(portal_receiver), std::move(client)); + DCHECK(portal_frame); portal_ = MakeGarbageCollected<PortalContents>( *this, portal_token, std::move(portal), std::move(client_receiver));
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element.h b/third_party/blink/renderer/core/html/portal/html_portal_element.h index 9311cc7..a2c1d19 100644 --- a/third_party/blink/renderer/core/html/portal/html_portal_element.h +++ b/third_party/blink/renderer/core/html/portal/html_portal_element.h
@@ -5,7 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_HTML_PORTAL_ELEMENT_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_HTML_PORTAL_ELEMENT_H_ -#include "base/unguessable_token.h" +#include "base/optional.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" @@ -34,9 +34,12 @@ DEFINE_WRAPPERTYPEINFO(); public: + // |portal_token|, |remote_portal| and |portal_client_receiver| are all empty + // when an empty HTMLPortalElement is constructed, (it hasn't yet been + // attached to an actual contents). explicit HTMLPortalElement( Document& document, - const PortalToken& portal_token = PortalToken::Null(), + const PortalToken* portal_token = nullptr, mojo::PendingAssociatedRemote<mojom::blink::Portal> remote_portal = {}, mojo::PendingAssociatedReceiver<mojom::blink::PortalClient> portal_client_receiver = {});
diff --git a/third_party/blink/renderer/core/html/portal/html_portal_element_test.cc b/third_party/blink/renderer/core/html/portal/html_portal_element_test.cc index 9432444..74c2eab 100644 --- a/third_party/blink/renderer/core/html/portal/html_portal_element_test.cc +++ b/third_party/blink/renderer/core/html/portal/html_portal_element_test.cc
@@ -82,7 +82,7 @@ client_remote.InitWithNewEndpointAndPassReceiver(); auto* activate_event = PortalActivateEvent::Create( - &GetFrame(), PortalToken::Create(), std::move(portal_remote), + &GetFrame(), PortalToken(), std::move(portal_remote), std::move(client_receiver), nullptr, nullptr, base::NullCallback()); activate_event->adoptPredecessor(exception_state); EXPECT_TRUE(exception_state.HadException());
diff --git a/third_party/blink/renderer/core/html/portal/portal_activate_event.cc b/third_party/blink/renderer/core/html/portal/portal_activate_event.cc index 1647c64f..fc1890bc 100644 --- a/third_party/blink/renderer/core/html/portal/portal_activate_event.cc +++ b/third_party/blink/renderer/core/html/portal/portal_activate_event.cc
@@ -140,7 +140,7 @@ DCHECK(!adopted_portal_); adopted_portal_ = MakeGarbageCollected<HTMLPortalElement>( - *document_, predecessor_portal_token_, std::move(predecessor_portal_), + *document_, &predecessor_portal_token_, std::move(predecessor_portal_), std::move(predecessor_portal_client_receiver_)); std::move(on_portal_activated_callback_) .Run(mojom::blink::PortalActivateResult::kPredecessorWasAdopted);
diff --git a/third_party/blink/renderer/core/html/portal/portal_contents.cc b/third_party/blink/renderer/core/html/portal/portal_contents.cc index 100063c..b12a9b7 100644 --- a/third_party/blink/renderer/core/html/portal/portal_contents.cc +++ b/third_party/blink/renderer/core/html/portal/portal_contents.cc
@@ -169,7 +169,7 @@ portal_element_->PortalContentsWillBeDestroyed(this); portal_element_ = nullptr; } - portal_token_ = PortalToken::Null(); + portal_token_ = base::nullopt; remote_portal_.reset(); portal_client_receiver_.reset(); DocumentPortals::From(GetDocument()).DeregisterPortalContents(this);
diff --git a/third_party/blink/renderer/core/html/portal/portal_contents.h b/third_party/blink/renderer/core/html/portal/portal_contents.h index a33b60f8..caf3112d 100644 --- a/third_party/blink/renderer/core/html/portal/portal_contents.h +++ b/third_party/blink/renderer/core/html/portal/portal_contents.h
@@ -6,7 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_PORTAL_PORTAL_CONTENTS_H_ #include "base/memory/scoped_refptr.h" -#include "base/unguessable_token.h" +#include "base/optional.h" #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" @@ -53,7 +53,7 @@ // Returns an unguessable token which uniquely identifies the contents, if // valid. - const PortalToken& GetToken() const { return portal_token_; } + const base::Optional<PortalToken>& GetToken() const { return portal_token_; } // Returns the RemoteFrame associated with this portal, if any. RemoteFrame* GetFrame() const; @@ -103,7 +103,8 @@ // TODO(jbroman): Should this be a ExecutionContextLifecycleObserver instead? Member<Document> document_; - // The element which owns this contents, if any. + // The element which owns this contents, if any. This is set to nullptr once + // Destroy has been called. Member<HTMLPortalElement> portal_element_; // Set if the portal contents is currently being activated. @@ -111,10 +112,12 @@ // DocumentPortals. Member<PortalActivationDelegate> activation_delegate_; - // Uniquely identifies the portal, this token is used by the browser process - // to reference this portal when communicating with the renderer. - PortalToken portal_token_; + // Uniquely identifies the portal. This token is used by the browser process + // to reference this portal when communicating with the renderer. This is set + // to base::nullopt once Destroy has been called. + base::Optional<PortalToken> portal_token_; + // Both of these will be reset once Destroy has been called. mojo::AssociatedRemote<mojom::blink::Portal> remote_portal_; mojo::AssociatedReceiver<mojom::blink::PortalClient> portal_client_receiver_; };
diff --git a/third_party/blink/renderer/core/html/rel_list.cc b/third_party/blink/renderer/core/html/rel_list.cc index 5e86b0a..6b70a34 100644 --- a/third_party/blink/renderer/core/html/rel_list.cc +++ b/third_party/blink/renderer/core/html/rel_list.cc
@@ -60,7 +60,7 @@ return true; } if (RuntimeEnabledFeatures::MediaFeedsEnabled( - GetElement().GetExecutionContext()) || + GetElement().GetExecutionContext()) && token_value == "media-feed") { return true; }
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index 2b903cc..cb42bb9 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -650,6 +650,37 @@ SetHasNonCollapsedBorderDecoration(style_to_use.HasBorderDecoration()); } +void LayoutBox::LayoutSubtreeRoot() { + if (RuntimeEnabledFeatures::LayoutNGEnabled() && + !NGBlockNode::CanUseNewLayout(*this)) { + // If this object is laid out by the legacy engine, while its containing + // block is laid out by NG, it means that we normally (when laying out + // starting at the real root, i.e. LayoutView) enter layout of this object + // from NG code. This takes care of setting up a BoxLayoutExtraInput + // structure, which makes legacy layout behave when managed by NG. Make a + // short detour via NG just to set things up to re-enter legacy layout + // correctly. + if (const NGLayoutResult* result = GetCachedLayoutResult()) { + DCHECK_EQ(PhysicalFragmentCount(), 1u); + LayoutPoint old_location = Location(); + + // Make a copy of the cached constraint space, since we'll overwrite the + // layout result object as part of performing layout. + auto constraint_space = result->GetConstraintSpaceForCaching(); + + NGBlockNode(this).Layout(constraint_space); + + // Restore the old location. While it's usually the job of the containing + // block to position its children, out-of-flow positioned objects set + // their own position, which could be wrong in this case. + SetLocation(old_location); + return; + } + } + + UpdateLayout(); +} + void LayoutBox::UpdateLayout() { DCHECK(NeedsLayout()); LayoutAnalyzer::Scope analyzer(*this);
diff --git a/third_party/blink/renderer/core/layout/layout_box.h b/third_party/blink/renderer/core/layout/layout_box.h index 994d6b6..8394c96 100644 --- a/third_party/blink/renderer/core/layout/layout_box.h +++ b/third_party/blink/renderer/core/layout/layout_box.h
@@ -797,6 +797,8 @@ return extra_input_; } + void LayoutSubtreeRoot(); + void UpdateLayout() override; void Paint(const PaintInfo&) const override;
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 5d834c71..5e7b81f 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -976,6 +976,11 @@ return true; } + // SVG roots are sufficiently self-contained to be a relayout boundary, even + // if their size is non-fixed. + if (is_svg_root) + return true; + // If either dimension is percent-based, intrinsic, or anything but fixed, // this object cannot form a re-layout boundary. A non-fixed computed logical // height will allow the object to grow and shrink based on the content @@ -987,9 +992,6 @@ if (object->IsTextControl()) return true; - if (is_svg_root) - return true; - if (!object->HasOverflowClip()) return false;
diff --git a/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc b/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc index 0a089a7..ffd43ef 100644 --- a/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc +++ b/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.cc
@@ -146,31 +146,38 @@ unsigned LegacyAbstractInlineTextBox::Len() const { if (!inline_text_box_) - return 0; + return 0u; - return inline_text_box_->Len(); + return NeedsTrailingSpace() ? inline_text_box_->Len() + 1 + : inline_text_box_->Len(); } unsigned LegacyAbstractInlineTextBox::TextOffsetInContainer( unsigned offset) const { if (!inline_text_box_) - return 0; - - unsigned offset_in_container = inline_text_box_->Start() + offset; - - const NGOffsetMapping* offset_mapping = GetOffsetMapping(); - if (!offset_mapping) - return offset_in_container; + return 0U; // The start offset of the inline text box returned by // inline_text_box_->Start() includes the collapsed white-spaces. Here, we // want the position in the parent node after white-space collapsing. // NGOffsetMapping can map an offset before whites-spaces are collapsed to the // offset after white-spaces are collapsed. - Position position(GetNode(), offset_in_container); - const NGOffsetMappingUnit* unit = - offset_mapping->GetMappingUnitForPosition(position); - return offset_in_container - unit->DOMStart() + unit->TextContentStart(); + unsigned int offset_in_container = inline_text_box_->Start() + offset; + const Position position(GetNode(), offset_in_container); + LayoutBlockFlow* formatting_context = + NGOffsetMapping::GetInlineFormattingContextOf(position); + if (!formatting_context) + return offset_in_container; + + // If "formatting_context" is not a Layout NG object, the offset mappings will + // be computed on demand and cached. + const NGOffsetMapping* offset_mapping = + NGInlineNode::GetOffsetMapping(formatting_context); + if (!offset_mapping) + return offset_in_container; + + return offset_mapping->GetTextContentOffset(position).value_or( + offset_in_container); } AbstractInlineTextBox::Direction LegacyAbstractInlineTextBox::GetDirection() @@ -198,6 +205,8 @@ return; inline_text_box_->CharacterWidths(widths); + if (NeedsTrailingSpace()) + widths.push_back(inline_text_box_->NewlineSpaceWidth()); } void AbstractInlineTextBox::GetWordBoundaries( @@ -289,13 +298,8 @@ } // Insert a space at the end of this if necessary. - if (InlineTextBox* next = inline_text_box_->NextForSameLayoutObject()) { - if (next->Start() > inline_text_box_->Start() + inline_text_box_->Len() && - result.length() && !result.Right(1).ContainsOnlyWhitespaceOrEmpty() && - next->GetText().length() && - !next->GetText().Left(1).ContainsOnlyWhitespaceOrEmpty()) - return result + " "; - } + if (NeedsTrailingSpace()) + return result + " "; return result; } @@ -351,25 +355,18 @@ return inline_text_box_->IsLineBreak(); } -const NGOffsetMapping* LegacyAbstractInlineTextBox::GetOffsetMapping() const { - const auto* text_node = DynamicTo<Text>(GetNode()); - if (!text_node) - return nullptr; - - LayoutBlockFlow& block_flow = *NGOffsetMapping::GetInlineFormattingContextOf( - *text_node->GetLayoutObject()); - const NGOffsetMapping* offset_mapping = - NGInlineNode::GetOffsetMapping(&block_flow); - - if (UNLIKELY(!offset_mapping)) { - // TODO(crbug.com/955678): There are certain cases where we fail to - // compute // |NGOffsetMapping| due to failures in layout. As the root - // cause is hard to fix at the moment, we work around it here so that the - // production build doesn't crash. - NOTREACHED(); - return nullptr; +bool LegacyAbstractInlineTextBox::NeedsTrailingSpace() const { + if (const InlineTextBox* next = inline_text_box_->NextForSameLayoutObject()) { + return next->Start() > + inline_text_box_->Start() + inline_text_box_->Len() && + inline_text_box_->GetText().length() && + !inline_text_box_->GetText() + .Right(1) + .ContainsOnlyWhitespaceOrEmpty() && + next->GetText().length() && + !next->GetText().Left(1).ContainsOnlyWhitespaceOrEmpty(); } - return offset_mapping; + return false; } } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h b/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h index a820acd..ae70bbee 100644 --- a/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h +++ b/third_party/blink/renderer/core/layout/line/abstract_inline_text_box.h
@@ -42,7 +42,6 @@ namespace blink { class InlineTextBox; -class NGOffsetMapping; // High-level abstraction of InlineTextBox to allow the accessibility module to // get information about InlineTextBoxes without tight coupling. @@ -78,6 +77,7 @@ virtual scoped_refptr<AbstractInlineTextBox> NextOnLine() const = 0; virtual scoped_refptr<AbstractInlineTextBox> PreviousOnLine() const = 0; virtual bool IsLineBreak() const = 0; + virtual bool NeedsTrailingSpace() const = 0; protected: explicit AbstractInlineTextBox(LineLayoutText line_layout_item); @@ -123,7 +123,7 @@ scoped_refptr<AbstractInlineTextBox> NextOnLine() const final; scoped_refptr<AbstractInlineTextBox> PreviousOnLine() const final; bool IsLineBreak() const final; - const NGOffsetMapping* GetOffsetMapping() const; + bool NeedsTrailingSpace() const final; InlineTextBox* inline_text_box_;
diff --git a/third_party/blink/renderer/core/layout/line/abstract_inline_text_box_test.cc b/third_party/blink/renderer/core/layout/line/abstract_inline_text_box_test.cc index 5067af1..b123b73 100644 --- a/third_party/blink/renderer/core/layout/line/abstract_inline_text_box_test.cc +++ b/third_party/blink/renderer/core/layout/line/abstract_inline_text_box_test.cc
@@ -39,6 +39,8 @@ layout_text.FirstAbstractInlineTextBox(); EXPECT_EQ("abc", inline_text_box->GetText()); + EXPECT_EQ(3u, inline_text_box->Len()); + EXPECT_FALSE(inline_text_box->NeedsTrailingSpace()); } // For DumpAccessibilityTreeTest.AccessibilityInputTextValue/blink @@ -55,12 +57,14 @@ layout_text.FirstAbstractInlineTextBox(); EXPECT_EQ("abc:", inline_text_box->GetText()); + EXPECT_EQ(4u, inline_text_box->Len()); + EXPECT_FALSE(inline_text_box->NeedsTrailingSpace()); } // For "web_tests/accessibility/inline-text-change-style.html" TEST_P(AbstractInlineTextBoxTest, GetTextWithLineBreakAtMiddleCollapsedWhiteSpace) { - // Line break at a space after "012". + // There should be a line break at the space after "012". SetBodyInnerHTML(R"HTML( <style>* { font-size: 10px; }</style> <div id="target" style="width: 0ch">012 345</div>)HTML"); @@ -72,12 +76,14 @@ layout_text.FirstAbstractInlineTextBox(); EXPECT_EQ("012 ", inline_text_box->GetText()); + EXPECT_EQ(4u, inline_text_box->Len()); + EXPECT_TRUE(inline_text_box->NeedsTrailingSpace()); } // DumpAccessibilityTreeTest.AccessibilitySpanLineBreak/blink TEST_P(AbstractInlineTextBoxTest, GetTextWithLineBreakAtSpanCollapsedWhiteSpace) { - // Line break at a space in <span>. + // There should be a line break at the space in <span>. SetBodyInnerHTML(R"HTML( <style>* { font-size: 10px; }</style> <p id="t1" style="width: 0ch">012<span id="t2"> </span>345</p>)HTML"); @@ -89,6 +95,8 @@ layout_text1.FirstAbstractInlineTextBox(); EXPECT_EQ("012", inline_text_box1->GetText()); + EXPECT_EQ(3u, inline_text_box1->Len()); + EXPECT_FALSE(inline_text_box1->NeedsTrailingSpace()); const Element& target2 = *GetDocument().getElementById("t2"); LayoutText& layout_text2 = @@ -96,13 +104,14 @@ scoped_refptr<AbstractInlineTextBox> inline_text_box2 = layout_text2.FirstAbstractInlineTextBox(); - EXPECT_FALSE(inline_text_box2) << "We don't have inline box when <span> " - "contains only collapsed white spaces."; + EXPECT_EQ(nullptr, inline_text_box2) + << "We don't have inline box when <span> " + "contains only collapsed white spaces."; } // For DumpAccessibilityTreeTest.AccessibilityInputTypes/blink TEST_P(AbstractInlineTextBoxTest, GetTextWithLineBreakAtTrailingWhiteSpace) { - // Line break at a space of "abc: ". + // There should be a line break at the space of "abc: ". SetBodyInnerHTML(R"HTML( <style>* { font-size: 10px; }</style> <div style="width: 10ch"><label id=label>abc: <input></label></div>)HTML"); @@ -114,40 +123,56 @@ layout_text.FirstAbstractInlineTextBox(); EXPECT_EQ("abc: ", inline_text_box->GetText()); + EXPECT_EQ(5u, inline_text_box->Len()); + if (LayoutNGEnabled()) { + EXPECT_TRUE(inline_text_box->NeedsTrailingSpace()); + } else { + EXPECT_FALSE(inline_text_box->NeedsTrailingSpace()); + } } TEST_P(AbstractInlineTextBoxTest, GetTextOffsetInContainer) { - // "
" is a Line Feed ("\n"). + // The span should not affect the offset in container of the following inline + // text boxes in the paragraph. + // + // Note that "
" is a Line Feed, ("\n"). SetBodyInnerHTML(R"HTML( <style>p { white-space: pre-line; }</style> - <p id="paragraph">First sentence of the paragraph. Second sentence of the paragraph. </p> - <br id='br'>)HTML"); + <p id="paragraph"><span>Offset</span>First sentence of the paragraph. Second sentence of the paragraph.</p> + <br id="br">)HTML"); const Element& paragraph = *GetDocument().getElementById("paragraph"); - LayoutText& layout_text = - *ToLayoutText(paragraph.firstChild()->GetLayoutObject()); + const Node& text_node = *paragraph.firstChild()->nextSibling(); + LayoutText& layout_text = *ToLayoutText(text_node.GetLayoutObject()); - // This test has 5 AbstractInlineTextBox. 1.text 2.\n 3.text 4.\n 5.text. - // The AbstractInlineTextBoxes are all child of the same text node and an + // The above "layout_text" should create five AbstractInlineTextBoxes: + // 1. "First sentence " + // 2. "\n" + // 3. "of the paragraph. Second sentence of " + // 4." \n" + // 5. "the paragraph." + // + // The AbstractInlineTextBoxes are all children of the same text node and an // an offset calculated in the container node should always be the same for // both LayoutNG and Legacy, even though Legacy doesn't collapse the - // white-spaces at the end of an AbstractInlineTextBox. + // white spaces at the end of an AbstractInlineTextBox. White spaces at the + // beginning of the third and fifth inline text box should be collapsed. scoped_refptr<AbstractInlineTextBox> inline_text_box = layout_text.FirstAbstractInlineTextBox(); - String text = "First sentence of the"; + String text = "First sentence"; EXPECT_EQ(LayoutNGEnabled() ? text : text + " ", inline_text_box->GetText()); - EXPECT_EQ(0u, inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(6u, inline_text_box->TextOffsetInContainer(0)); - // Need to jump over the line break AbstractInlineTextBox. + // We need to jump over the AbstractInlineTextBox with the line break. inline_text_box = inline_text_box->NextInlineTextBox()->NextInlineTextBox(); - text = "paragraph. Second sentence of"; + text = "of the paragraph. Second sentence of"; EXPECT_EQ(LayoutNGEnabled() ? text : text + " ", inline_text_box->GetText()); - EXPECT_EQ(22u, inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(21u, inline_text_box->TextOffsetInContainer(0u)); // See comment above. inline_text_box = inline_text_box->NextInlineTextBox()->NextInlineTextBox(); EXPECT_EQ("the paragraph.", inline_text_box->GetText()); - EXPECT_EQ(52u, inline_text_box->TextOffsetInContainer(0)); + EXPECT_EQ(58u, inline_text_box->TextOffsetInContainer(0u)); // Ensure that calling TextOffsetInContainer on a br gives the correct result. const Element& br_element = *GetDocument().getElementById("br"); @@ -157,4 +182,23 @@ EXPECT_EQ(0u, inline_text_box->TextOffsetInContainer(0)); } +TEST_P(AbstractInlineTextBoxTest, CharacterWidths) { + // There should be a line break at the space after "012". + SetBodyInnerHTML(R"HTML( + <style>* { font-size: 10px; }</style> + <div id="div" style="width: 0ch">012 345</div>)HTML"); + + const Element& div = *GetDocument().getElementById("div"); + LayoutText& layout_text = *ToLayoutText(div.firstChild()->GetLayoutObject()); + scoped_refptr<AbstractInlineTextBox> inline_text_box = + layout_text.FirstAbstractInlineTextBox(); + + Vector<float> widths; + inline_text_box->CharacterWidths(widths); + // There should be four elements in the "widths" vector, not three, because + // the width of the trailing space should be included. + EXPECT_EQ(4u, widths.size()); + EXPECT_TRUE(inline_text_box->NeedsTrailingSpace()); +} + } // namespace blink
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h b/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h index 85fec4b6..9343731 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_abstract_inline_text_box.h
@@ -38,7 +38,6 @@ NGInlineCursor GetCursor() const; NGInlineCursor GetCursorOnLine() const; String GetTextContent() const; - bool NeedsTrailingSpace() const; // Implementations of AbstractInlineTextBox member functions. void Detach() final; @@ -54,6 +53,7 @@ scoped_refptr<AbstractInlineTextBox> NextOnLine() const final; scoped_refptr<AbstractInlineTextBox> PreviousOnLine() const final; bool IsLineBreak() const final; + bool NeedsTrailingSpace() const final; union { const NGPaintFragment* fragment_;
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h index 0cad220..26a9250 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_node.h
@@ -99,7 +99,7 @@ // Returns the DOM to text content offset mapping of this block. If it is not // computed before, compute and store it in NGInlineNodeData. - // This funciton must be called with clean layout. + // This function must be called with clean layout. const NGOffsetMapping* ComputeOffsetMappingIfNeeded() const; // Get |NGOffsetMapping| for the |layout_block_flow|. |layout_block_flow|
diff --git a/third_party/blink/renderer/core/loader/empty_clients.cc b/third_party/blink/renderer/core/loader/empty_clients.cc index 298b8d06..ea24fab 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.cc +++ b/third_party/blink/renderer/core/loader/empty_clients.cc
@@ -132,7 +132,7 @@ HTMLPortalElement*, mojo::PendingAssociatedReceiver<mojom::blink::Portal>, mojo::PendingAssociatedRemote<mojom::blink::PortalClient>) { - return std::pair<RemoteFrame*, PortalToken>(nullptr, PortalToken::Null()); + return std::pair<RemoteFrame*, PortalToken>(nullptr, PortalToken()); } RemoteFrame* EmptyLocalFrameClient::AdoptPortal(HTMLPortalElement*) {
diff --git a/third_party/blink/renderer/core/page/chrome_client.cc b/third_party/blink/renderer/core/page/chrome_client.cc index 2cbdb38..74ecea0 100644 --- a/third_party/blink/renderer/core/page/chrome_client.cc +++ b/third_party/blink/renderer/core/page/chrome_client.cc
@@ -292,6 +292,11 @@ return false; } + // Suspend pages in case the client method runs a new event loop that would + // otherwise cause the load to continue while we're in the middle of + // executing JavaScript. + ScopedPagePauser pauser; + PrintDelegate(frame); return true; }
diff --git a/third_party/blink/renderer/core/script/classic_pending_script.cc b/third_party/blink/renderer/core/script/classic_pending_script.cc index 7e29da6..8fe87aae 100644 --- a/third_party/blink/renderer/core/script/classic_pending_script.cc +++ b/third_party/blink/renderer/core/script/classic_pending_script.cc
@@ -43,8 +43,9 @@ const WTF::TextEncoding& encoding, ScriptElementBase* element, FetchParameters::DeferOption defer) { + ExecutionContext* context = element_document.GetExecutionContext(); FetchParameters params(options.CreateFetchParameters( - url, element_document.GetExecutionContext()->GetSecurityOrigin(), + url, context->GetSecurityOrigin(), context->GetCurrentWorld(), cross_origin, encoding, defer)); ClassicPendingScript* pending_script =
diff --git a/third_party/blink/renderer/core/script/document_write_intervention.cc b/third_party/blink/renderer/core/script/document_write_intervention.cc index f7e38549..b9d2a86 100644 --- a/third_party/blink/renderer/core/script/document_write_intervention.cc +++ b/third_party/blink/renderer/core/script/document_write_intervention.cc
@@ -220,10 +220,10 @@ EmitErrorBlocked(resource->Url(), element_document); + ExecutionContext* context = element_document.GetExecutionContext(); FetchParameters params(options.CreateFetchParameters( - resource->Url(), - element_document.GetExecutionContext()->GetSecurityOrigin(), cross_origin, - resource->Encoding(), FetchParameters::kIdleLoad)); + resource->Url(), context->GetSecurityOrigin(), context->GetCurrentWorld(), + cross_origin, resource->Encoding(), FetchParameters::kIdleLoad)); AddHeader(¶ms); ScriptResource::Fetch(params, element_document.Fetcher(), nullptr, ScriptResource::kNoStreaming);
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_html.cc b/third_party/blink/renderer/core/trustedtypes/trusted_html.cc index 333aa0bc..2ca5a201 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_html.cc +++ b/third_party/blink/renderer/core/trustedtypes/trusted_html.cc
@@ -6,9 +6,9 @@ namespace blink { -TrustedHTML::TrustedHTML(const String& html) : html_(html) {} +TrustedHTML::TrustedHTML(String html) : html_(std::move(html)) {} -String TrustedHTML::toString() const { +const String& TrustedHTML::toString() const { return html_; }
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_html.h b/third_party/blink/renderer/core/trustedtypes/trusted_html.h index bbfa231..8e269e3a 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_html.h +++ b/third_party/blink/renderer/core/trustedtypes/trusted_html.h
@@ -15,10 +15,10 @@ DEFINE_WRAPPERTYPEINFO(); public: - explicit TrustedHTML(const String& html); + explicit TrustedHTML(String html); // TrustedHTML.idl - String toString() const; + const String& toString() const; private: const String html_;
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_script.cc b/third_party/blink/renderer/core/trustedtypes/trusted_script.cc index 9d8472a..4983fe98 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_script.cc +++ b/third_party/blink/renderer/core/trustedtypes/trusted_script.cc
@@ -6,9 +6,9 @@ namespace blink { -TrustedScript::TrustedScript(const String& script) : script_(script) {} +TrustedScript::TrustedScript(String script) : script_(std::move(script)) {} -String TrustedScript::toString() const { +const String& TrustedScript::toString() const { return script_; }
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_script.h b/third_party/blink/renderer/core/trustedtypes/trusted_script.h index 429790ac..c93620a 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_script.h +++ b/third_party/blink/renderer/core/trustedtypes/trusted_script.h
@@ -15,10 +15,10 @@ DEFINE_WRAPPERTYPEINFO(); public: - explicit TrustedScript(const String& script); + explicit TrustedScript(String script); // TrustedScript.idl - String toString() const; + const String& toString() const; private: const String script_;
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc index dd91ac5..1da404d8 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc +++ b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.cc
@@ -6,9 +6,9 @@ namespace blink { -TrustedScriptURL::TrustedScriptURL(const String& url) : url_(url) {} +TrustedScriptURL::TrustedScriptURL(String url) : url_(std::move(url)) {} -String TrustedScriptURL::toString() const { +const String& TrustedScriptURL::toString() const { return url_; }
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h index d3981c2e..d287ebd4 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h +++ b/third_party/blink/renderer/core/trustedtypes/trusted_script_url.h
@@ -15,10 +15,10 @@ DEFINE_WRAPPERTYPEINFO(); public: - explicit TrustedScriptURL(const String& url); + explicit TrustedScriptURL(String url); // TrustedScriptURL.idl - String toString() const; + const String& toString() const; private: const String url_;
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc index a22c1e91..3d077c8b 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc +++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.cc
@@ -206,7 +206,7 @@ // and has a number of additional parameters to enable proper error reporting // for each case. String GetStringFromScriptHelper( - const String& script, + String script, ExecutionContext* context, // Parameters to customize error messages: @@ -277,7 +277,7 @@ !ContentSecurityPolicy::ShouldBypassMainWorld(execution_context); } -String TrustedTypesCheckForHTML(const String& html, +String TrustedTypesCheckForHTML(String html, const ExecutionContext* execution_context, ExceptionState& exception_state) { bool require_trusted_type = RequireTrustedTypesCheck(execution_context); @@ -302,6 +302,9 @@ return html; } } + // TODO(ajwong): This can be optimized to avoid a AddRef in the + // StringCache::CreateStringAndInsertIntoCache() also, but it's a hard mess. + // Punt for now. TrustedHTML* result = default_policy->CreateHTML( execution_context->GetIsolate(), html, GetDefaultCallbackArgs(execution_context->GetIsolate(), "TrustedHTML", @@ -323,7 +326,7 @@ return result->toString(); } -String TrustedTypesCheckForScript(const String& script, +String TrustedTypesCheckForScript(String script, const ExecutionContext* execution_context, ExceptionState& exception_state) { bool require_trusted_type = RequireTrustedTypesCheck(execution_context); @@ -348,6 +351,9 @@ return script; } } + // TODO(ajwong): This can be optimized to avoid a AddRef in the + // StringCache::CreateStringAndInsertIntoCache() also, but it's a hard mess. + // Punt for now. TrustedScript* result = default_policy->CreateScript( execution_context->GetIsolate(), script, GetDefaultCallbackArgs(execution_context->GetIsolate(), "TrustedScript", @@ -370,7 +376,7 @@ return result->toString(); } -String TrustedTypesCheckForScriptURL(const String& script_url, +String TrustedTypesCheckForScriptURL(String script_url, const ExecutionContext* execution_context, ExceptionState& exception_state) { bool require_trusted_type = @@ -397,6 +403,9 @@ return script_url; } } + // TODO(ajwong): This can be optimized to avoid a AddRef in the + // StringCache::CreateStringAndInsertIntoCache() also, but it's a hard mess. + // Punt for now. TrustedScriptURL* result = default_policy->CreateScriptURL( execution_context->GetIsolate(), script_url, GetDefaultCallbackArgs(execution_context->GetIsolate(), @@ -446,7 +455,8 @@ } // In all other cases: run the full check against the string value. - return TrustedTypesCheckFor(type, value, execution_context, exception_state); + return TrustedTypesCheckFor(type, std::move(value), execution_context, + exception_state); } String TrustedTypesCheckForScript(StringOrTrustedScript trusted, @@ -468,41 +478,41 @@ } String TrustedTypesCheckFor(SpecificTrustedType type, - const String& trusted, + String trusted, const ExecutionContext* execution_context, ExceptionState& exception_state) { switch (type) { case SpecificTrustedType::kHTML: - return TrustedTypesCheckForHTML(trusted, execution_context, + return TrustedTypesCheckForHTML(std::move(trusted), execution_context, exception_state); case SpecificTrustedType::kScript: - return TrustedTypesCheckForScript(trusted, execution_context, + return TrustedTypesCheckForScript(std::move(trusted), execution_context, exception_state); case SpecificTrustedType::kScriptURL: - return TrustedTypesCheckForScriptURL(trusted, execution_context, - exception_state); + return TrustedTypesCheckForScriptURL(std::move(trusted), + execution_context, exception_state); case SpecificTrustedType::kNone: return trusted; } NOTREACHED(); - return ""; + return g_empty_string; } String CORE_EXPORT -GetStringForScriptExecution(const String& script, +GetStringForScriptExecution(String script, const ScriptElementBase::Type type, ExecutionContext* context) { - return GetStringFromScriptHelper(script, context, GetElementName(type), - "text", kScriptExecution, - kScriptExecutionAndDefaultPolicyFailed); + return GetStringFromScriptHelper( + std::move(script), context, GetElementName(type), "text", + kScriptExecution, kScriptExecutionAndDefaultPolicyFailed); } String TrustedTypesCheckForJavascriptURLinNavigation( - const String& javascript_url, + String javascript_url, ExecutionContext* context) { return GetStringFromScriptHelper( - javascript_url, context, "Location", "href", kNavigateToJavascriptURL, - kNavigateToJavascriptURLAndDefaultPolicyFailed); + std::move(javascript_url), context, "Location", "href", + kNavigateToJavascriptURL, kNavigateToJavascriptURLAndDefaultPolicyFailed); } } // namespace blink
diff --git a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h index 4f825a8..8b07373a 100644 --- a/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h +++ b/third_party/blink/renderer/core/trustedtypes/trusted_types_util.h
@@ -40,17 +40,17 @@ // Returns the effective value (which may have been modified by the "default" // policy. We use WARN_UNUSED_RESULT to prevent erroneous usage. String TrustedTypesCheckFor(SpecificTrustedType, - const String&, + String, const ExecutionContext*, ExceptionState&) WARN_UNUSED_RESULT; -CORE_EXPORT String TrustedTypesCheckForHTML(const String&, +CORE_EXPORT String TrustedTypesCheckForHTML(String, const ExecutionContext*, ExceptionState&) WARN_UNUSED_RESULT; -CORE_EXPORT String TrustedTypesCheckForScript(const String&, +CORE_EXPORT String TrustedTypesCheckForScript(String, const ExecutionContext*, ExceptionState&) WARN_UNUSED_RESULT; -CORE_EXPORT String TrustedTypesCheckForScriptURL(const String&, +CORE_EXPORT String TrustedTypesCheckForScriptURL(String, const ExecutionContext*, ExceptionState&) WARN_UNUSED_RESULT; @@ -58,9 +58,8 @@ // Functionally equivalent to TrustedTypesCheckForScript(const String&, ...), // but with setup & error handling suitable for the asynchronous execution // cases. -String TrustedTypesCheckForJavascriptURLinNavigation(const String&, - ExecutionContext*); -CORE_EXPORT String GetStringForScriptExecution(const String&, +String TrustedTypesCheckForJavascriptURLinNavigation(String, ExecutionContext*); +CORE_EXPORT String GetStringForScriptExecution(String, ScriptElementBase::Type, ExecutionContext*);
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker.cc b/third_party/blink/renderer/core/workers/dedicated_worker.cc index 09e5b70..298c07a 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker.cc
@@ -87,7 +87,6 @@ const KURL& script_request_url, const WorkerOptions* options) : AbstractWorker(context), - token_(blink::DedicatedWorkerToken::Create()), script_request_url_(script_request_url), options_(options), context_proxy_(
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc index 7b7aa9e..66e0439 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.cc
@@ -35,8 +35,13 @@ DedicatedWorker* worker_object) : ThreadedMessagingProxyBase(execution_context), worker_object_(worker_object) { - worker_object_proxy_ = std::make_unique<DedicatedWorkerObjectProxy>( - this, GetParentExecutionContextTaskRunners()); + if (worker_object) { + // Worker object is only nullptr in tests, which subsequently manually + // injects a |worker_object_proxy_|. + worker_object_proxy_ = std::make_unique<DedicatedWorkerObjectProxy>( + this, GetParentExecutionContextTaskRunners(), + worker_object->GetToken()); + } } DedicatedWorkerMessagingProxy::~DedicatedWorkerMessagingProxy() = default; @@ -241,13 +246,6 @@ ThreadedMessagingProxyBase::Trace(visitor); } -const DedicatedWorkerToken& -DedicatedWorkerMessagingProxy::GetDedicatedWorkerToken() const { - if (!worker_object_) - return DedicatedWorkerToken::Null(); - return worker_object_->GetToken(); -} - base::Optional<WorkerBackingThreadStartupData> DedicatedWorkerMessagingProxy::CreateBackingThreadStartupData( v8::Isolate* isolate) {
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h index cfc9757..73fde5e 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_messaging_proxy.h
@@ -8,7 +8,6 @@ #include <memory> #include "base/macros.h" #include "base/memory/scoped_refptr.h" -#include "base/optional.h" #include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h" #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/messaging/transferable_message.mojom-blink-forward.h" @@ -73,8 +72,6 @@ void Trace(Visitor*) const override; - const DedicatedWorkerToken& GetDedicatedWorkerToken() const; - private: friend class DedicatedWorkerMessagingProxyForTest;
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.cc b/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.cc index fb3df92..108e9571 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.cc
@@ -119,9 +119,10 @@ DedicatedWorkerObjectProxy::DedicatedWorkerObjectProxy( DedicatedWorkerMessagingProxy* messaging_proxy_weak_ptr, - ParentExecutionContextTaskRunners* parent_execution_context_task_runners) + ParentExecutionContextTaskRunners* parent_execution_context_task_runners, + const DedicatedWorkerToken& token) : ThreadedObjectProxyBase(parent_execution_context_task_runners), - token_(messaging_proxy_weak_ptr->GetDedicatedWorkerToken()), + token_(token), messaging_proxy_weak_ptr_(messaging_proxy_weak_ptr) {} CrossThreadWeakPersistent<ThreadedMessagingProxyBase>
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h b/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h index ee83dd4..f8e4eaf 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h +++ b/third_party/blink/renderer/core/workers/dedicated_worker_object_proxy.h
@@ -57,7 +57,8 @@ public: DedicatedWorkerObjectProxy(DedicatedWorkerMessagingProxy*, - ParentExecutionContextTaskRunners*); + ParentExecutionContextTaskRunners*, + const DedicatedWorkerToken&); ~DedicatedWorkerObjectProxy() override; void PostMessageToWorkerObject(BlinkTransferableMessage);
diff --git a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc index 195f105..96e1ad0 100644 --- a/third_party/blink/renderer/core/workers/dedicated_worker_test.cc +++ b/third_party/blink/renderer/core/workers/dedicated_worker_test.cc
@@ -89,7 +89,8 @@ DedicatedWorkerMessagingProxy* messaging_proxy, ParentExecutionContextTaskRunners* parent_execution_context_task_runners) : DedicatedWorkerObjectProxy(messaging_proxy, - parent_execution_context_task_runners) {} + parent_execution_context_task_runners, + DedicatedWorkerToken()) {} void CountFeature(WebFeature feature) override { // Any feature should be reported only one time. @@ -109,6 +110,9 @@ DedicatedWorkerMessagingProxyForTest(ExecutionContext* execution_context) : DedicatedWorkerMessagingProxy(execution_context, nullptr /* worker_object */) { + // The |worker_object_proxy_| should not have been set in the + // DedicatedWorkerMessagingProxy constructor as |worker_object| is nullptr. + DCHECK(!worker_object_proxy_); worker_object_proxy_ = std::make_unique<DedicatedWorkerObjectProxyForTest>( this, GetParentExecutionContextTaskRunners()); }
diff --git a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc index 32dc777..0cb251fd 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc +++ b/third_party/blink/renderer/core/workers/shared_worker_global_scope.cc
@@ -64,7 +64,6 @@ time_origin, ukm_source_id), token_(token) { - DCHECK(token); appcache_host_ = MakeGarbageCollected<ApplicationCacheHostForWorker>( appcache_host_id, GetBrowserInterfaceBroker(), GetTaskRunner(TaskType::kInternalLoading), this);
diff --git a/third_party/blink/renderer/core/workers/shared_worker_thread.cc b/third_party/blink/renderer/core/workers/shared_worker_thread.cc index b31bc1e5..2200309e 100644 --- a/third_party/blink/renderer/core/workers/shared_worker_thread.cc +++ b/third_party/blink/renderer/core/workers/shared_worker_thread.cc
@@ -48,9 +48,7 @@ ThreadCreationParams(GetThreadType()))), token_(token), appcache_host_id_(appcache_host_id), - ukm_source_id_(ukm_source_id) { - DCHECK(token); -} + ukm_source_id_(ukm_source_id) {} SharedWorkerThread::~SharedWorkerThread() = default;
diff --git a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc index 645f0b2..7b4f030 100644 --- a/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc +++ b/third_party/blink/renderer/modules/credentialmanager/credentials_container.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/metrics/histogram_macros.h" #include "build/build_config.h" #include "third_party/blink/public/common/sms/sms_receiver_outcome.h" #include "third_party/blink/public/mojom/credentialmanager/credential_manager.mojom-blink.h" @@ -654,6 +655,8 @@ CredentialManagerProxy::From(script_state)->SmsReceiver(); sms_receiver->Receive(WTF::Bind(&OnSmsReceive, WrapPersistent(resolver), base::TimeTicks::Now())); + UMA_HISTOGRAM_ENUMERATION("Blink.UseCounter.Features", + WebFeature::kSMSReceiverStart); return promise; }
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc index 2ccd3bae..e99c7f5 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.cc +++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -98,6 +98,7 @@ const char kGooglePlayBillingMethod[] = "https://play.google.com/billing"; const char kUnknownCurrency[] = "ZZZ"; const char kAppStoreBillingLabelPlaceHolder[] = "AppStoreBillingPlaceHolder"; +const char kSecurePaymentConfirmationMethod[] = "secure-payment-confirmation"; } // namespace @@ -438,7 +439,7 @@ if (supported_method == "basic-card") { BasicCardHelper::ParseBasiccardData(input, output->supported_networks, exception_state); - } else if (supported_method == "secure-payment-confirmation" && + } else if (supported_method == kSecurePaymentConfirmationMethod && RuntimeEnabledFeatures::SecurePaymentConfirmationEnabled( &execution_context)) { SecurePaymentConfirmationHelper::ParseSecurePaymentConfirmationData( @@ -676,6 +677,18 @@ return; } + if (payment_method_data->supportedMethod() == + kSecurePaymentConfirmationMethod && + input.size() > 1 && + RuntimeEnabledFeatures::SecurePaymentConfirmationEnabled( + &execution_context)) { + exception_state.ThrowRangeError( + String(kSecurePaymentConfirmationMethod) + + " must be the only payment method identifier specified in the " + "PaymentRequest constructor."); + return; + } + method_names.insert(payment_method_data->supportedMethod()); output.push_back(payments::mojom::blink::PaymentMethodData::New());
diff --git a/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc b/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc index 591b6bb..4f84dd2 100644 --- a/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.cc
@@ -235,9 +235,10 @@ return direction_; } -void FakeRTCRtpTransceiverImpl::SetDirection( +webrtc::RTCError FakeRTCRtpTransceiverImpl::SetDirection( webrtc::RtpTransceiverDirection direction) { NOTIMPLEMENTED(); + return webrtc::RTCError::OK(); } base::Optional<webrtc::RtpTransceiverDirection>
diff --git a/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h b/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h index b69e90d..9c19b3e 100644 --- a/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h +++ b/third_party/blink/renderer/modules/peerconnection/fake_rtc_rtp_transceiver_impl.h
@@ -105,7 +105,8 @@ std::unique_ptr<RTCRtpReceiverPlatform> Receiver() const override; bool Stopped() const override; webrtc::RtpTransceiverDirection Direction() const override; - void SetDirection(webrtc::RtpTransceiverDirection direction) override; + webrtc::RTCError SetDirection( + webrtc::RtpTransceiverDirection direction) override; base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() const override; base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
diff --git a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc index 2459ac0..5437abb2 100644 --- a/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc +++ b/third_party/blink/renderer/modules/peerconnection/mock_rtc_peer_connection_handler_platform.cc
@@ -179,8 +179,9 @@ return std::make_unique<DummyRTCRtpReceiverPlatform>(receiver_); } webrtc::RtpTransceiverDirection direction() const { return direction_; } - void set_direction(webrtc::RtpTransceiverDirection direction) { + webrtc::RTCError set_direction(webrtc::RtpTransceiverDirection direction) { direction_ = direction; + return webrtc::RTCError::OK(); } private: @@ -223,8 +224,9 @@ webrtc::RtpTransceiverDirection Direction() const override { return internal_->direction(); } - void SetDirection(webrtc::RtpTransceiverDirection direction) override { - internal_->set_direction(direction); + webrtc::RTCError SetDirection( + webrtc::RtpTransceiverDirection direction) override { + return internal_->set_direction(direction); } base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() const override {
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc index 5bbf210..2c41f1c 100644 --- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc +++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
@@ -145,6 +145,8 @@ return "'recvonly'"; case webrtc::RtpTransceiverDirection::kInactive: return "'inactive'"; + case webrtc::RtpTransceiverDirection::kStopped: + return "'stopped'"; default: NOTREACHED(); return String();
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.cc index aab131e7..811817b 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.cc
@@ -405,9 +405,10 @@ return webrtc::RtpTransceiverDirection::kSendOnly; } -void RTCRtpReceiverOnlyTransceiver::SetDirection( +webrtc::RTCError RTCRtpReceiverOnlyTransceiver::SetDirection( webrtc::RtpTransceiverDirection direction) { NOTIMPLEMENTED(); + return webrtc::RTCError::OK(); } base::Optional<webrtc::RtpTransceiverDirection>
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.h b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.h index 282e001..d737060 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver_impl.h
@@ -165,7 +165,8 @@ std::unique_ptr<RTCRtpReceiverPlatform> Receiver() const override; bool Stopped() const override; webrtc::RtpTransceiverDirection Direction() const override; - void SetDirection(webrtc::RtpTransceiverDirection direction) override; + webrtc::RTCError SetDirection( + webrtc::RtpTransceiverDirection direction) override; base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() const override; base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc index fae544b..fcf80ad 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.cc
@@ -611,9 +611,10 @@ return webrtc::RtpTransceiverDirection::kSendOnly; } -void RTCRtpSenderOnlyTransceiver::SetDirection( +webrtc::RTCError RTCRtpSenderOnlyTransceiver::SetDirection( webrtc::RtpTransceiverDirection direction) { NOTIMPLEMENTED(); + return webrtc::RTCError::OK(); } base::Optional<webrtc::RtpTransceiverDirection>
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.h b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.h index 7dc010b..42ffd6c 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender_impl.h
@@ -184,7 +184,8 @@ std::unique_ptr<RTCRtpReceiverPlatform> Receiver() const override; bool Stopped() const override; webrtc::RtpTransceiverDirection Direction() const override; - void SetDirection(webrtc::RtpTransceiverDirection direction) override; + webrtc::RTCError SetDirection( + webrtc::RtpTransceiverDirection direction) override; base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() const override; base::Optional<webrtc::RtpTransceiverDirection> FiredDirection()
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc index 50bde04..0a9cf5b12 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h" +#include "third_party/blink/renderer/modules/peerconnection/rtc_error_util.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.h" #include "third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.h" @@ -28,6 +29,8 @@ return "recvonly"; case webrtc::RtpTransceiverDirection::kInactive: return "inactive"; + case webrtc::RtpTransceiverDirection::kStopped: + return "stopped"; default: NOTREACHED(); return String(); @@ -147,7 +150,12 @@ "The transceiver is stopped."); return; } - platform_transceiver_->SetDirection(*webrtc_direction); + webrtc::RTCError error = + platform_transceiver_->SetDirection(*webrtc_direction); + if (!error.ok()) { + ThrowExceptionFromRTCError(error, exception_state); + return; + } UpdateMembers(); } @@ -197,6 +205,15 @@ *fired_direction_ == webrtc::RtpTransceiverDirection::kRecvOnly); } +void RTCRtpTransceiver::stop(ExceptionState& exception_state) { + webrtc::RTCError error = platform_transceiver_->Stop(); + if (!error.ok()) { + ThrowExceptionFromRTCError(error, exception_state); + return; + } + stopped_ = true; +} + void RTCRtpTransceiver::setCodecPreferences( const HeapVector<Member<RTCRtpCodecCapability>>& codecs, ExceptionState& exception_state) {
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h index d2d82ca..ce7a658 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.h
@@ -46,6 +46,7 @@ String direction() const; void setDirection(String direction, ExceptionState&); String currentDirection() const; + void stop(ExceptionState&); void setCodecPreferences( const HeapVector<Member<RTCRtpCodecCapability>>& codecs, ExceptionState& exception_state);
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.idl b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.idl index 5fdb827..d642fd2 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.idl +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver.idl
@@ -17,8 +17,10 @@ readonly attribute DOMString? mid; [SameObject] readonly attribute RTCRtpSender sender; [SameObject] readonly attribute RTCRtpReceiver receiver; - readonly attribute boolean stopped; + // Non-standard + [Measure] readonly attribute boolean stopped; [Measure, RaisesException=Setter] attribute RTCRtpTransceiverDirection direction; readonly attribute RTCRtpTransceiverDirection? currentDirection; + [Measure, RuntimeEnabled=RTCRtpTransceiverStop, RaisesException] void stop(); [RaisesException] void setCodecPreferences(sequence<RTCRtpCodecCapability> codecs); };
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc index 8b3498a..900be89 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.cc
@@ -245,14 +245,19 @@ return receiver_.get(); } - void SetDirection(webrtc::RtpTransceiverDirection direction) { + webrtc::RTCError SetDirection(webrtc::RtpTransceiverDirection direction) { DCHECK(main_task_runner_->BelongsToCurrentThread()); // This implicitly performs a blocking invoke on the webrtc signaling thread // due to use of PROXY references for |webrtc_transceiver_|. - webrtc_transceiver_->SetDirection(direction); - state_.set_direction(webrtc_transceiver_->direction()); + auto error = webrtc_transceiver_->SetDirectionWithError(direction); + if (error.ok()) { + state_.set_direction(webrtc_transceiver_->direction()); + } + return error; } + webrtc::RTCError Stop() { return webrtc_transceiver_->StopStandard(); } + webrtc::RTCError setCodecPreferences( std::vector<webrtc::RtpCodecCapability> codec_preferences) { return webrtc_transceiver_->SetCodecPreferences(codec_preferences); @@ -383,9 +388,9 @@ return internal_->state().direction(); } -void RTCRtpTransceiverImpl::SetDirection( +webrtc::RTCError RTCRtpTransceiverImpl::SetDirection( webrtc::RtpTransceiverDirection direction) { - internal_->SetDirection(direction); + return internal_->SetDirection(direction); } base::Optional<webrtc::RtpTransceiverDirection> @@ -398,6 +403,10 @@ return internal_->state().fired_direction(); } +webrtc::RTCError RTCRtpTransceiverImpl::Stop() { + return internal_->Stop(); +} + webrtc::RTCError RTCRtpTransceiverImpl::SetCodecPreferences( Vector<webrtc::RtpCodecCapability> codec_preferences) { std::vector<webrtc::RtpCodecCapability> std_codec_preferences(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.h b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.h index 24921be..78f26335 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.h +++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_transceiver_impl.h
@@ -176,11 +176,13 @@ std::unique_ptr<RTCRtpReceiverPlatform> Receiver() const override; bool Stopped() const override; webrtc::RtpTransceiverDirection Direction() const override; - void SetDirection(webrtc::RtpTransceiverDirection direction) override; + webrtc::RTCError SetDirection( + webrtc::RtpTransceiverDirection direction) override; base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() const override; base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() const override; + webrtc::RTCError Stop() override; webrtc::RTCError SetCodecPreferences( Vector<webrtc::RtpCodecCapability>) override;
diff --git a/third_party/blink/renderer/platform/bindings/script_state.cc b/third_party/blink/renderer/platform/bindings/script_state.cc index c659c18..982aa765 100644 --- a/third_party/blink/renderer/platform/bindings/script_state.cc +++ b/third_party/blink/renderer/platform/bindings/script_state.cc
@@ -18,8 +18,7 @@ context_(isolate_, context), world_(std::move(world)), per_context_data_(std::make_unique<V8PerContextData>(context)), - reference_from_v8_context_(PERSISTENT_FROM_HERE, this), - token_(V8ContextToken::Create()) { + reference_from_v8_context_(PERSISTENT_FROM_HERE, this) { DCHECK(world_); context_.SetWeak(this, &OnV8ContextCollectedCallback); context->SetAlignedPointerInEmbedderData(kV8ContextPerContextDataIndex, this);
diff --git a/third_party/blink/renderer/platform/bindings/v8_set_return_value.h b/third_party/blink/renderer/platform/bindings/v8_set_return_value.h index 52269d5..7010888 100644 --- a/third_party/blink/renderer/platform/bindings/v8_set_return_value.h +++ b/third_party/blink/renderer/platform/bindings/v8_set_return_value.h
@@ -177,8 +177,8 @@ // the IDL type because Blink is not always respectful to IDL types. These // functions fix such a type mismatch. template <typename CallbackInfo, typename BlinkType, typename IdlType> -typename std::enable_if_t<std::is_arithmetic<BlinkType>::value || - std::is_enum<BlinkType>::value> +inline typename std::enable_if_t<std::is_arithmetic<BlinkType>::value || + std::is_enum<BlinkType>::value> V8SetReturnValue(const CallbackInfo& info, BlinkType value, V8ReturnValue::PrimitiveType<IdlType>) { @@ -186,9 +186,9 @@ } template <typename CallbackInfo, typename BlinkType> -void V8SetReturnValue(const CallbackInfo& info, - BlinkType* value, - V8ReturnValue::PrimitiveType<bool>) { +inline void V8SetReturnValue(const CallbackInfo& info, + BlinkType* value, + V8ReturnValue::PrimitiveType<bool>) { V8SetReturnValue(info, bool(value)); }
diff --git a/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.cc b/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.cc index e353199..619765def 100644 --- a/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.cc +++ b/third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.cc
@@ -4,27 +4,18 @@ #include "third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h" -#include <CoreText/CoreText.h> +#include "base/mac/mac_util.h" namespace blink { -// Compare CoreText.h in an up to date SDK, redefining here since we don't seem -// to have access to this value when building against the 10.10 SDK in our -// standard Chrome build configuration. -// static const uint32_t kBlinkLocalCTVersionNumber10_12 = 0x00090000; -static const uint32_t kBlinkLocalCTVersionNumber10_13 = 0x000A0000; -static const uint32_t kBlinkLocalCTVersionNumber10_14 = 0x000B0000; - bool CoreTextVersionSupportsVariations() { - return &CTGetCoreTextVersion && - CTGetCoreTextVersion() >= kBlinkLocalCTVersionNumber10_14; + return base::mac::IsAtLeastOS10_14(); } // CoreText versions below 10.13 display COLR cpal as black/foreground-color // glyphs and do not interpret color glyph layers correctly. bool CoreTextVersionSupportsColrCpal() { - return &CTGetCoreTextVersion && - CTGetCoreTextVersion() >= kBlinkLocalCTVersionNumber10_13; + return base::mac::IsAtLeastOS10_13(); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h index 3c83b3bd..ed3dfa6 100644 --- a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h +++ b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.h
@@ -46,6 +46,9 @@ class FontPlatformData; class FontVariationSettings; +// Given a typeface and a variable axis, returns whether a new value for that +// axis isn't clamped and therefore will effect a change to the typeface if +// applied. bool PLATFORM_EXPORT VariableAxisChangeEffective(SkTypeface* typeface, SkFourByteTag axis, float new_value);
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm index d6abddab..cf23bfc2 100644 --- a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm +++ b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac.mm
@@ -26,22 +26,23 @@ #import <AppKit/NSFont.h> #import <AvailabilityMacros.h> -#include "base/mac/foundation_util.h" -#include "base/mac/scoped_nsobject.h" +#import "base/mac/foundation_util.h" +#import "base/mac/scoped_nsobject.h" #include "base/stl_util.h" -#import "third_party/blink/public/platform/mac/web_sandbox_support.h" -#import "third_party/blink/public/platform/platform.h" -#import "third_party/blink/renderer/platform/fonts/font.h" -#import "third_party/blink/renderer/platform/fonts/font_platform_data.h" -#import "third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h" -#import "third_party/blink/renderer/platform/fonts/opentype/font_settings.h" -#import "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h" -#import "third_party/blink/renderer/platform/web_test_support.h" -#import "third_party/blink/renderer/platform/wtf/text/wtf_string.h" -#import "third_party/skia/include/core/SkFont.h" -#import "third_party/skia/include/core/SkStream.h" -#import "third_party/skia/include/core/SkTypeface.h" -#import "third_party/skia/include/core/SkTypes.h" +#include "third_party/blink/public/platform/mac/web_sandbox_support.h" +#include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/platform/fonts/font.h" +#include "third_party/blink/renderer/platform/fonts/font_platform_data.h" +#include "third_party/blink/renderer/platform/fonts/mac/core_text_font_format_support.h" +#include "third_party/blink/renderer/platform/fonts/opentype/font_settings.h" +#include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h" +#include "third_party/blink/renderer/platform/web_test_support.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" +#include "third_party/skia/include/core/SkFont.h" +#include "third_party/skia/include/core/SkStream.h" +#include "third_party/skia/include/core/SkTypeface.h" +#include "third_party/skia/include/core/SkTypes.h" #import "third_party/skia/include/ports/SkTypeface_mac.h" namespace { @@ -58,9 +59,9 @@ if (num_axes <= 0) return false; - SkFontParameters::Variation::Axis axes_parameters[num_axes]; + Vector<SkFontParameters::Variation::Axis> axes_parameters(num_axes); int returned_axes = - typeface->getVariationDesignParameters(axes_parameters, num_axes); + typeface->getVariationDesignParameters(axes_parameters.data(), num_axes); DCHECK_EQ(num_axes, returned_axes); DCHECK_GE(num_axes, 0); @@ -78,9 +79,10 @@ // effect. // Then compare if clamped value differs from what is set on the font. - SkFontArguments::VariationPosition::Coordinate coordinates[num_coordinates]; + Vector<SkFontArguments::VariationPosition::Coordinate> coordinates( + num_coordinates); int returned_coordinates = - typeface->getVariationDesignPosition(coordinates, num_coordinates); + typeface->getVariationDesignPosition(coordinates.data(), num_coordinates); if (returned_coordinates != num_coordinates) return false; // Something went wrong in retrieving actual axis positions, @@ -213,10 +215,10 @@ } // Iterate over the font's axes and find a missing tag from variation - // settings, special case opsz, track the number of axes reconfigured. + // settings, special case 'opsz', track the number of axes reconfigured. bool axes_reconfigured = false; for (auto& coordinate : coordinates_to_set) { - // Set opsz to font size but allow having it overriden by + // Set 'opsz' to font size but allow having it overridden by // font-variation-settings in case it has 'opsz'. if (coordinate.axis == kOpszTag && optical_sizing == kAutoOpticalSizing) { if (VariableAxisChangeEffective(typeface.get(), coordinate.axis, size)) { @@ -247,7 +249,7 @@ SkFontArguments().setVariationDesignPosition(variation_design_position))); if (!cloned_typeface) { - // Applying varition parameters failed, return original typeface. + // Applying variation parameters failed, return original typeface. return make_typeface_fontplatformdata(); } typeface = cloned_typeface;
diff --git a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac_test.mm b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac_test.mm index e62d3735..018743cf 100644 --- a/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac_test.mm +++ b/third_party/blink/renderer/platform/fonts/mac/font_platform_data_mac_test.mm
@@ -27,48 +27,182 @@ } TEST(FontPlatformDataMacTest, VariableOpticalSizingThreshold) { - sk_sp<SkTypeface> system_font(MakeSystemFontOfSize(19)); - if (@available(macOS 10.15, *)) { - EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); - EXPECT_FALSE( - VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + // Before macOS 10.15, the system font did not have variable optical sizing. + // In 10.15, the system font has two optical sizes glued together at 19.9. In + // 11.0, the system font has a real optical size axis with range 17-96. + + // Below the 11.0 axis minimum. + sk_sp<SkTypeface> system_font(MakeSystemFontOfSize(12)); + // TODO(https://crbug.com/1115294, https://crbug.com/1105187): Switch back to + // @available when it works. + if (base::mac::IsOS11()) { EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_TRUE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); - } else { - if (@available(macOS 10.13, *)) { - EXPECT_FALSE( - VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); - EXPECT_FALSE( - VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); - EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); - EXPECT_FALSE( - VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); - EXPECT_FALSE( - VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); - EXPECT_FALSE( - VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); - } - } - - system_font = MakeSystemFontOfSize(20); - if (@available(macOS 10.15, *)) { - EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); - EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); - EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); - EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); - EXPECT_TRUE( - VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); - EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); - } else { - EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); - EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); - EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } else if (base::mac::IsOS10_15()) { + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); EXPECT_FALSE( VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } else { EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_FALSE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } + + // Just smaller than the switch-over size in 10.15, which is 19.9. + system_font = MakeSystemFontOfSize(19); + if (base::mac::IsOS11()) { + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_TRUE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } else if (base::mac::IsOS10_15()) { + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_FALSE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } else { + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_FALSE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } + + // Just larger than the switch-over size in 10.15, which is 19.9. + system_font = MakeSystemFontOfSize(20); + if (base::mac::IsOS11()) { + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_TRUE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } else if (base::mac::IsOS10_15()) { + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_TRUE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } else { + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_FALSE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } + + // Above the 11.0 axis maximum. + system_font = MakeSystemFontOfSize(128); + if (base::mac::IsOS11()) { + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_TRUE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } else if (base::mac::IsOS10_15()) { + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_TRUE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_TRUE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); + } else { + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 6)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 12)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 17)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 18)); + EXPECT_FALSE( + VariableAxisChangeEffective(system_font.get(), kOpszTag, 19.8999)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 19)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 20)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 24)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 72)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 96)); + EXPECT_FALSE(VariableAxisChangeEffective(system_font.get(), kOpszTag, 97)); } }
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc index 3c2bb9c..0a351b5 100644 --- a/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc +++ b/third_party/blink/renderer/platform/loader/fetch/fetch_parameters.cc
@@ -44,11 +44,10 @@ scoped_refptr<const DOMWrapperWorld> world) : resource_request_(std::move(resource_request)), decoder_options_(TextResourceDecoderOptions::kPlainTextContent), + options_(std::move(world)), speculative_preload_type_(SpeculativePreloadType::kNotSpeculative), defer_(kNoDefer), - image_request_behavior_(kNone) { - options_.world = std::move(world); -} + image_request_behavior_(kNone) {} FetchParameters::FetchParameters(ResourceRequest resource_request, const ResourceLoaderOptions& options)
diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc b/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc index 5f8b5247..289e7a0 100644 --- a/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
@@ -88,7 +88,9 @@ FakeResource(const char* url, ResourceType type) : FakeResource(KURL(url), type) {} FakeResource(const KURL& url, ResourceType type) - : FakeResource(ResourceRequest(url), type, ResourceLoaderOptions()) {} + : FakeResource(ResourceRequest(url), + type, + ResourceLoaderOptions(nullptr /* world */)) {} FakeResource(const ResourceRequest& request, ResourceType type, const ResourceLoaderOptions& options)
diff --git a/third_party/blink/renderer/platform/loader/fetch/raw_resource.h b/third_party/blink/renderer/platform/loader/fetch/raw_resource.h index 760b6f97..12dd376 100644 --- a/third_party/blink/renderer/platform/loader/fetch/raw_resource.h +++ b/third_party/blink/renderer/platform/loader/fetch/raw_resource.h
@@ -65,7 +65,7 @@ // Exposed for testing static RawResource* CreateForTest(const ResourceRequest& request, ResourceType type) { - ResourceLoaderOptions options; + ResourceLoaderOptions options(nullptr /* world */); return MakeGarbageCollected<RawResource>(request, type, options); } static RawResource* CreateForTest(const KURL& url,
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc index 4103621..4dd998e 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -464,7 +464,7 @@ auto* fetcher = CreateFetcher(); ResourceRequest request(KURL("data:text/html,foo")); request.SetRequestContext(mojom::RequestContextType::VIDEO); - ResourceLoaderOptions options; + ResourceLoaderOptions options(nullptr /* world */); options.data_buffering_policy = kDoNotBufferData; options.initiator_info.name = fetch_initiator_type_names::kInternal; FetchParameters fetch_params(std::move(request), options);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc b/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc index cb2c29d1..4470630 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.cc
@@ -30,11 +30,14 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h" +#include <utility> + #include "services/network/public/mojom/url_loader_factory.mojom-blink.h" namespace blink { -ResourceLoaderOptions::ResourceLoaderOptions() +ResourceLoaderOptions::ResourceLoaderOptions( + scoped_refptr<const DOMWrapperWorld> world) : data_buffering_policy(kBufferData), content_security_policy_option(network::mojom::CSPDisposition::CHECK), request_initiator_context(kDocumentContext), @@ -42,7 +45,8 @@ cors_handling_by_resource_fetcher(kEnableCorsHandlingByResourceFetcher), cors_flag(false), parser_disposition(kParserInserted), - cache_aware_loading_enabled(kNotCacheAwareLoadingEnabled) {} + cache_aware_loading_enabled(kNotCacheAwareLoadingEnabled), + world(std::move(world)) {} ResourceLoaderOptions::ResourceLoaderOptions( const ResourceLoaderOptions& other) = default;
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h b/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h index 3f941f5..0c4a707 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_loader_options.h
@@ -88,7 +88,10 @@ // resource_loader_options.cc because they require the full definition of // URLLoaderFactory for |url_loader_factory| data member, and we'd like // to avoid to include huge url_loader_factory.mojom-blink.h. - ResourceLoaderOptions(); + // TODO(crbug.com/896041): Make |world| non-optional by plumbing it for all + // requests. + explicit ResourceLoaderOptions( + scoped_refptr<const DOMWrapperWorld> world = nullptr); ResourceLoaderOptions(const ResourceLoaderOptions& other); ResourceLoaderOptions& operator=(const ResourceLoaderOptions& other); ~ResourceLoaderOptions(); @@ -118,7 +121,8 @@ CacheAwareLoadingEnabled cache_aware_loading_enabled; // The world in which this request initiated. This will be used for CSP checks - // if specified. If unspecified, the CSP bound to the FetchContext is used. + // if specified. If null, the CSP bound to the FetchContext is used. + // TODO(crbug.com/896041): Rename to |world_for_csp|. scoped_refptr<const DOMWrapperWorld> world; // If not null, this URLLoaderFactory should be used to load this resource
diff --git a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc index f264722..3dfe9938 100644 --- a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc +++ b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h" +#include <utility> + #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/security_origin.h" @@ -13,6 +15,7 @@ FetchParameters ScriptFetchOptions::CreateFetchParameters( const KURL& url, const SecurityOrigin* security_origin, + scoped_refptr<const DOMWrapperWorld> world_for_csp, CrossOriginAttributeValue cross_origin, const WTF::TextEncoding& encoding, FetchParameters::DeferOption defer) const { @@ -21,7 +24,7 @@ ResourceRequest resource_request(url); // Step 1. ... "script", ... [spec text] - ResourceLoaderOptions resource_loader_options; + ResourceLoaderOptions resource_loader_options(std::move(world_for_csp)); resource_loader_options.initiator_info.name = "script"; resource_loader_options.reject_coep_unsafe_none = reject_coep_unsafe_none_; FetchParameters params(std::move(resource_request), resource_loader_options);
diff --git a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h index 45977a4..41ea4c6 100644 --- a/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h +++ b/third_party/blink/renderer/platform/loader/fetch/script_fetch_options.h
@@ -19,6 +19,7 @@ namespace blink { +class DOMWrapperWorld; class KURL; class SecurityOrigin; @@ -82,11 +83,13 @@ // https://html.spec.whatwg.org/C/#fetch-a-classic-script // Steps 1 and 3. - FetchParameters CreateFetchParameters(const KURL&, - const SecurityOrigin*, - CrossOriginAttributeValue, - const WTF::TextEncoding&, - FetchParameters::DeferOption) const; + FetchParameters CreateFetchParameters( + const KURL&, + const SecurityOrigin*, + scoped_refptr<const DOMWrapperWorld> world, + CrossOriginAttributeValue, + const WTF::TextEncoding&, + FetchParameters::DeferOption) const; private: // https://html.spec.whatwg.org/C/#concept-script-fetch-options-nonce
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h index 573cc25..0e06411 100644 --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader.h
@@ -109,7 +109,7 @@ Member<ResourceLoadObserver> resource_load_observer_; ResourceRequest initial_request_; - ResourceLoaderOptions resource_loader_options_; + ResourceLoaderOptions resource_loader_options_{nullptr /* world */}; KURL initial_request_url_; KURL last_request_url_; ResourceResponse resource_response_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc index 2674c87..22c3a19 100644 --- a/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc +++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/worker_main_script_loader_unittest.cc
@@ -232,7 +232,8 @@ request.SetRequestContext(mojom::RequestContextType::SHARED_WORKER); request.SetRequestDestination( network::mojom::RequestDestination::kSharedWorker); - FetchParameters fetch_params(std::move(request), ResourceLoaderOptions()); + FetchParameters fetch_params(std::move(request), + ResourceLoaderOptions(nullptr /* world */)); WorkerMainScriptLoader* worker_main_script_loader = MakeGarbageCollected<WorkerMainScriptLoader>(); worker_main_script_loader->Start(
diff --git a/third_party/blink/renderer/platform/loader/testing/mock_resource.cc b/third_party/blink/renderer/platform/loader/testing/mock_resource.cc index 773060d3b..09a7a8e 100644 --- a/third_party/blink/renderer/platform/loader/testing/mock_resource.cc +++ b/third_party/blink/renderer/platform/loader/testing/mock_resource.cc
@@ -37,7 +37,7 @@ MockResource::MockResource(const KURL& url) : MockResource(ResourceRequest(url)) {} MockResource::MockResource(const ResourceRequest& request) - : MockResource(request, ResourceLoaderOptions()) {} + : MockResource(request, ResourceLoaderOptions(nullptr /* world */)) {} MockResource::MockResource(const ResourceRequest& request, const ResourceLoaderOptions& options) : Resource(request, ResourceType::kMock, options) {}
diff --git a/third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h b/third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h index 1ba9324..eba22db 100644 --- a/third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h +++ b/third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h
@@ -58,11 +58,15 @@ virtual std::unique_ptr<RTCRtpReceiverPlatform> Receiver() const = 0; virtual bool Stopped() const = 0; virtual webrtc::RtpTransceiverDirection Direction() const = 0; - virtual void SetDirection(webrtc::RtpTransceiverDirection) = 0; + virtual webrtc::RTCError SetDirection(webrtc::RtpTransceiverDirection) = 0; virtual base::Optional<webrtc::RtpTransceiverDirection> CurrentDirection() const = 0; virtual base::Optional<webrtc::RtpTransceiverDirection> FiredDirection() const = 0; + virtual webrtc::RTCError Stop() { + NOTREACHED(); + return webrtc::RTCError::OK(); + } virtual webrtc::RTCError SetCodecPreferences( Vector<webrtc::RtpCodecCapability>) { return {};
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 675569e..6be2a6fa 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -699,7 +699,7 @@ }, { name: "EncryptedMediaPersistentUsageRecordSession", - status: "experimental", + status: "stable", }, { name: "EnterKeyHintAttribute", @@ -1612,6 +1612,11 @@ origin_trial_feature_name: "RTCQuicTransport", status: "experimental", }, + // Enables the use of |RTCRtpTransceiver::stop()| + { + name: "RTCRtpTransceiverStop", + status: "experimental", + }, { name: "RTCStatsRelativePacketArrivalDelay", origin_trial_feature_name: "RTCStatsRelativePacketArrivalDelay",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index c6a5f71..4f277262 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1827,7 +1827,7 @@ # Flaking on Linux Leak crbug.com/1049599 [ Linux ] virtual/threaded-prefer-compositing/fast/scrolling/events/overscroll-event-fired-to-element-with-overscroll-behavior.html [ Pass Failure Timeout ] crbug.com/1081237 [ Mac ] virtual/threaded-prefer-compositing/fast/scrolling/events/overscroll-event-fired-to-element-with-overscroll-behavior.html [ Pass Timeout ] -crbug.com/1049641 [ Debug ] http/tests/devtools/sources/debugger/js-with-inline-stylesheets.js [ Pass Failure ] +crbug.com/1049641 http/tests/devtools/sources/debugger/js-with-inline-stylesheets.js [ Pass Failure ] crbug.com/1049641 [ Debug ] http/tests/devtools/sources/debugger-breakpoints/set-breakpoint.js [ Pass Failure ] crbug.com/1049641 [ Debug ] http/tests/devtools/sources/debugger-breakpoints/set-conditional-breakpoint.js [ Pass Failure ] crbug.com/1049641 http/tests/devtools/sources/debugger/debugger-disable-enable.js [ Pass Timeout ] @@ -3117,6 +3117,10 @@ crbug.com/1110833 external/wpt/webrtc/RTCPeerConnection-explicit-rollback-iceGatheringState.html [ Timeout ] +# Tests that start hanging after implementing RTCRtpTransceiver.stop +crbug.com/1115080 external/wpt/webrtc/RTCPeerConnection-iceGatheringState.html [ Timeout ] +crbug.com/1115087 external/wpt/webrtc/RTCRtpTransceiver.https.html [ Timeout ] + # See also crbug.com/920100 (sheriff 2019-01-09). crbug.com/626703 external/wpt/referrer-policy/css-integration/svg/external-stylesheet.html [ Timeout Failure ] crbug.com/626703 external/wpt/referrer-policy/css-integration/svg/inline-style.html [ Timeout Failure ]
diff --git a/third_party/blink/web_tests/WebDriverExpectations b/third_party/blink/web_tests/WebDriverExpectations index b6d5928..e17f57e 100644 --- a/third_party/blink/web_tests/WebDriverExpectations +++ b/third_party/blink/web_tests/WebDriverExpectations
@@ -77,6 +77,157 @@ crbug.com/1020018 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_sucess_input_non_interactable [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_screenshot/screenshot.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/release_actions/release.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_modifiers.py>>test_shift_modifier_generates_capital_letters[\ue050] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/navigate_to/navigate.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_no_browsing_history [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_accept[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss[capabilities0-alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/add_cookie/add.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_dismissed_beforeunload [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_default[confirm-False] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_selected/selected.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/close.py>>test_close_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_window/switch.py>>test_null_response_value [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/user_prompts.py>>test_accept[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_abort_by_user_prompt[confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/none.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_accept[capabilities0-alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_all_cookies/delete.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_abort_by_user_prompt_twice[confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_default[alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/print/printcmd.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/user_prompts.py>>test_dismiss[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_async_script/execute_async.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_null_response_value [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_dismiss[capabilities0-alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/user_prompts.py>>test_accept[capabilities0-confirm-True] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/take_element_screenshot/screenshot.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/accept_alert/accept.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_history_pushstate [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/fullscreen_window/fullscreen.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_fragments [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new_window.py>>test_new_window_sets_no_window_name [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_property/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[capabilities0-realmSetting0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[capabilities0-realmSetting1-granted] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/close.py>>test_close_browsing_context_with_dismissed_beforeunload_prompt [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept[capabilities0-alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_tag_name/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_default[prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_history_pushstate [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_data_urls [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_accept[capabilities0-confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/set_window_rect/set.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_abort_by_user_prompt[prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[capabilities0-realmSetting0-denied] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/is_element_enabled/enabled.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_window_rect/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/delete_cookie/delete.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_abort_by_user_prompt_twice[alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss[capabilities0-alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_dismiss[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new_window.py>>test_new_window_opens_about_blank [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_refresh_switches_to_parent_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_css_value/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/maximize_window/maximize.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/element_send_keys/send_keys.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_no_browsing_history [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_attribute/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_modifiers.py>>test_shift_modifier_generates_capital_letters[\ue008] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_ending_comment [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_window_handle/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_rect/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_null_parameter_value [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[capabilities0-realmSetting1-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_frame/switch.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new.py>>test_type_with_null_value [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new_tab.py>>test_new_tab [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss_and_notify[capabilities0-confirm-False] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_fragments [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_element_text/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/user_prompts.py>>test_dismiss[capabilities0-confirm-False] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept[capabilities0-confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_basic [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_override_listeners [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/switch_to_parent_frame/switch.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_ignore[capabilities0-alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new.py>>test_type_with_unknown_value [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/minimize_window/minimize.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_ignore[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_active_element/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_page_source/source.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_history_pushstate [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept_and_notify[capabilities0-confirm-True] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_null_response_value [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_default[prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[capabilities0-realmSetting0-granted] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_modifiers.py>>test_shift_modifier_and_non_printable_keys[\ue008] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/user_prompts.py>>test_dismiss[capabilities0-prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/user_prompts.py>>test_accept[capabilities0-prompt-] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_current_url/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_window_handles/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss_and_notify[capabilities0-prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_alert_text/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_default[confirm-False] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_default[prompt-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_default[confirm-False] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_accept_and_notify[capabilities0-prompt-] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/permissions/set.py>>test_set_to_state_cross_realm[capabilities0-realmSetting1-denied] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/close.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_title/get.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_abort_by_user_prompt[alert] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_dismissed_beforeunload [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new_tab.py>>test_new_tab_sets_no_opener [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/back.py>>test_dismissed_beforeunload [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/forward.py>>test_data_urls [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_ignore[capabilities0-confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss[capabilities0-prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new_tab.py>>test_new_tab_opens_about_blank [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/execute_script/execute.py>>test_abort_by_user_prompt_twice[prompt] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new_window.py>>test_type_with_window [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_accept[capabilities0-confirm] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/forward/user_prompts.py>>test_dismiss_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/refresh/refresh.py>>test_null_response_value [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_default[alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/dismiss_alert/dismiss.py>>test_no_browsing_context [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new_window.py>>test_new_window_sets_no_opener [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_window_handles/get.py>>test_multiple_windows [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/key_modifiers.py>>test_shift_modifier_and_non_printable_keys[\ue050] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/close_window/user_prompts.py>>test_accept_and_notify[capabilities0-alert-None] [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/new_window/new_tab.py>>test_new_tab_sets_no_window_name [ Failure ] +crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/back/user_prompts.py>>test_dismiss[capabilities0-confirm] [ Failure ] crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/perform_actions/pointer_tripleclick.py>>test_tripleclick_at_coordinates [ Failure ] crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/minimize_window/minimize.py>>test_fully_exit_fullscreen [ Failure ] crbug.com/626703 [ Linux ] external/wpt/webdriver/tests/get_named_cookie/get.py>>test_duplicated_cookie [ Failure ]
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 1a25e41..46f3160d 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
@@ -10255,12 +10255,12 @@ }, "animation-worklet": { "worklet-animation-cancel.https.html": [ - "3a28c7515db455ba50ed50135c5a5bb8534ae580", + "3b664ecddba8fb805b035d759a3b3cb109329274", [ null, [ [ - "/animation-worklet/worklet-animation-cancel-ref.html", + "/animation-worklet/references/not-translated-box-ref.html", "==" ] ], @@ -10268,12 +10268,12 @@ ] ], "worklet-animation-get-timing-on-worklet-thread.https.html": [ - "54d1c8bcc0c0a20d9af4e96ea240060ebd348982", + "4ba68d79e4de5544d36c826ad3b41613d9e3f289", [ null, [ [ - "/animation-worklet/worklet-animation-get-timing-on-worklet-thread-ref.html", + "/animation-worklet/references/translated-box-ref.html", "==" ] ], @@ -10281,12 +10281,12 @@ ] ], "worklet-animation-local-time-after-duration.https.html": [ - "adc90f1d3f6befa906473dd1bfb500b605431d0a", + "21293bc09b17591cb5dd8c2bbe3b09e726b4b5f3", [ null, [ [ - "/animation-worklet/worklet-animation-local-time-after-duration-ref.html", + "/animation-worklet/references/not-translated-box-ref.html", "==" ] ], @@ -10294,18 +10294,33 @@ ] ], "worklet-animation-local-time-before-start.https.html": [ - "addb16e7d1751280c8d4f3e0052b808ab807cd7e", + "a959b73c08d8c2a2a32fb5d6d3dbe8169b0c6512", [ null, [ [ - "/animation-worklet/worklet-animation-local-time-before-start-ref.html", + "/animation-worklet/references/translated-box-ref.html", "==" ] ], {} ] ], + "worklet-animation-local-time-null-2.https.html": [ + "9c499bac0ee51b7b41c9cf1ca5f917d096c9a756", + [ + null, + [ + [ + "/animation-worklet/worklet-animation-local-time-null-2-ref.html", + "==" + ] + ], + { + "timeout": "long" + } + ] + ], "worklet-animation-pause-immediately.https.html": [ "f9dcf30bc908adb4e6b260dd00263e434a9b9ae4", [ @@ -10333,12 +10348,12 @@ ] ], "worklet-animation-set-keyframes.https.html": [ - "017408494602ff51aec483ccc6dd0dd2f82bba4e", + "d3d02898db294b82bedda67b82b286cae9aeff06", [ null, [ [ - "/animation-worklet/worklet-animation-set-keyframes-ref.html", + "/animation-worklet/references/translated-box-ref.html", "==" ] ], @@ -10346,12 +10361,12 @@ ] ], "worklet-animation-set-timing.https.html": [ - "ac3f05f4234ac1036e388536c4237686b07e6037", + "6c5cd51300c5cbea15d094a5023d8b663fa759e6", [ null, [ [ - "/animation-worklet/worklet-animation-set-timing-ref.html", + "/animation-worklet/references/translated-box-ref.html", "==" ] ], @@ -65563,7 +65578,7 @@ ] ], "flex-and-intrinsic-sizes-002.html": [ - "1f93d0e3d0e2b6bff13351e92c7ffaba7cb68553", + "6b2df4e572094d424833e3a342431b11d7f4dc4a", [ null, [ @@ -85571,7 +85586,7 @@ ] ], "abspos-008.tentative.html": [ - "c81e9fcf40547bf34c47ab11ca3fda307f5f77ed", + "429b14ac35feb710354b9133ba435dc7fd192808", [ null, [ @@ -85883,7 +85898,111 @@ ] ], "block-aspect-ratio-020.tentative.html": [ - "3cb076252b0a356774cd4f9257c8561973a5d5d0", + "b07e91faf9860ea4b07d233103233b42e9ffd9c8", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-aspect-ratio-021.tentative.html": [ + "0e9c1b6b0a2697d9f1ee6309e4255859ecc7d1ad", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-aspect-ratio-022.tentative.html": [ + "1ee8021a3bbb428d9f7234590072986bd3ec4318", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-aspect-ratio-023.tentative.html": [ + "e38cfe0cb26e47eea9c6c8c32a692d045c692a13", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-aspect-ratio-024.tentative.html": [ + "d6f6716b99d527d421e892d80a79f9a31e84ec45", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-aspect-ratio-025.tentative.html": [ + "6ce673672372a84bbba40bc455d4fa744848852e", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-aspect-ratio-026.tentative.html": [ + "0e0ce5efe3aa8b83f64e8deee46bafb2c7144c58", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-aspect-ratio-027.tentative.html": [ + "532f558b39deff2788e58865cc2ae3777a6d4716", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-aspect-ratio-028.tentative.html": [ + "ec49bd4d7af834c3fea345b34b0eb05ff58f9e4d", [ null, [ @@ -86336,6 +86455,32 @@ ], {} ] + ], + "replaced-element-013.tentative.html": [ + "bcbf653d68af4c1f908a59ca6e66e5752a09c833", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "replaced-element-014.tentative.html": [ + "4c1ad16ce8624295251b73d1a14f53b9c9905610", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] ] }, "auto-scrollbar-inside-stf-abspos.html": [ @@ -157600,8 +157745,12 @@ [] ], "references": { + "not-translated-box-ref.html": [ + "96acf1ad96c7c41e870429d55142269f4468bb97", + [] + ], "translated-box-ref.html": [ - "c73f5a177bf70f3a71d981bc9f04b38c5afe9f1c", + "f1dde2e19b2ebad50dd29e693b2a81f7de2cc620", [] ] }, @@ -157615,28 +157764,8 @@ [] ] }, - "worklet-animation-cancel-ref.html": [ - "d44927374703ef2b38d3ed0c9570609b62baec65", - [] - ], - "worklet-animation-get-timing-on-worklet-thread-ref.html": [ - "aad07d5f6f26692dc47ce0219a78d3c1a50c608a", - [] - ], - "worklet-animation-local-time-after-duration-ref.html": [ - "96acf1ad96c7c41e870429d55142269f4468bb97", - [] - ], - "worklet-animation-local-time-before-start-ref.html": [ - "cda4ca4132cabcb13719f12248773026b0642df2", - [] - ], - "worklet-animation-set-keyframes-ref.html": [ - "26bf33fdb403877f2e3adf9b8bb3fca6bf8301bb", - [] - ], - "worklet-animation-set-timing-ref.html": [ - "8c354a8b06f815d4f8000895964b59c3f6c242e4", + "worklet-animation-local-time-null-2-ref.html": [ + "3b7a2b9258d0c2a210aaa389fadc3787c0da93a5", [] ], "worklet-animation-start-delay-ref.html": [ @@ -189283,7 +189412,7 @@ ] }, "event-dispatch.tentative-expected.txt": [ - "180a68fa2af47c9699da1a3f7abc1ba9015072ba", + "6c2a306154da5228dee5771f2b7ecaf953683af4", [] ], "idlharness-expected.txt": [ @@ -218766,7 +218895,7 @@ [] ], "web-animations.idl": [ - "ae64bb867eb23d6c491d3e9fee743c7cf8963236", + "2f2b086e65cc981d47def182b46ad48ebb28f846", [] ], "web-bluetooth.idl": [ @@ -235966,7 +236095,7 @@ [] ], "client.py": [ - "7f122c83dd99117678e574b7a7a81b6e976dbfd9", + "fe5189ec0b30a4e20642624c55e464ef40f2901d", [] ], "error.py": [ @@ -236287,7 +236416,7 @@ [] ], "executorwebdriver.py": [ - "2b3d53d7445706ae3ab601c42e2f17496f6868db", + "695b16b9cca19525a0656f66da45fe66c599fb8b", [] ], "executorwebkit.py": [ @@ -237985,6 +238114,10 @@ ] } }, + "idlharness.window-expected.txt": [ + "3725def5ec3bf4ac804ff5236f48ae18d44c208d", + [] + ], "interfaces": { "Animatable": { "animate-expected.txt": [ @@ -238640,7 +238773,7 @@ [] ], "conftest.py": [ - "d5fd320a696a507718299c765278edde6205608a", + "bd5db0cfeba7bbc8aaf23c3151109cf48094ff09", [] ] }, @@ -238690,10 +238823,6 @@ [] ], "support": { - "close_window.html": [ - "7a3619829d10de99268b35968e8dec8985575564", - [] - ], "input.html": [ "e2c6dadd1218e0a7d8b7d243a1c49b7f47092d77", [] @@ -238752,7 +238881,7 @@ [] ], "conftest.py": [ - "d5fd320a696a507718299c765278edde6205608a", + "bd5db0cfeba7bbc8aaf23c3151109cf48094ff09", [] ] }, @@ -238982,7 +239111,7 @@ [] ], "conftest.py": [ - "f34630c3cbc5de2700552e576bc7c797d2bd724f", + "b080761bde881d236aed87dbfcd03963051ba443", [] ] }, @@ -239022,11 +239151,11 @@ [] ], "fixtures.py": [ - "80ccfddf3d15ad739f7eca6a77fac79e2dcdcaef", + "364ede1c93b12debcfbb171cc0aada8a663dbab4", [] ], "helpers.py": [ - "8bc53e7b4030dfdc6a78d11cb95915ea081eae73", + "f857083b47743e0925e7baf8b0b964008be7923c", [] ], "html": { @@ -256372,6 +256501,13 @@ {} ] ], + "worklet-animation-local-time-null-1.https.html": [ + "7db0a9721f67c59d6f453e32f3e2a65e064ff215", + [ + null, + {} + ] + ], "worklet-animation-pause.https.html": [ "417db9e37a61193a99908648e4cbc3be4c2e9618", [ @@ -286452,7 +286588,7 @@ ] ], "event-dispatch.tentative.html": [ - "9e4946cf336ad0d78b3b87426d121a39ffb98037", + "5ed01cdd2588d1a5a5226a9abb46f60dd441ed13", [ null, {} @@ -365590,6 +365726,13 @@ "testdriver": true } ] + ], + "secure-payment-confirmation.https.html": [ + "1133214217a79f640e35ee09ab4abbaa8ca00e4a", + [ + null, + {} + ] ] }, "performance-timeline": { @@ -366418,7 +366561,7 @@ "pointerevents": { "compat": { "pointerevent_compat-mouse-events-when-removing-nodes.html": [ - "88d03b7965efc241893b8fbfc4c8f2e2b0967bf5", + "6d13b0de354a140e472d42bd8b81b408fad52495", [ null, { @@ -424752,14 +424895,14 @@ }, "close_window": { "close.py": [ - "f4e3b0481d3b3cbc93ba8b44c639934cf8eef9de", + "fa8236791067410c01bae081723ee26e237a476b", [ null, {} ] ], "user_prompts.py": [ - "22df9155e8e7bd3aa32fc96c7dd482972c490fd2", + "c0f9cc7610c21ea97064392eb2e09fce6f853bbc", [ null, { @@ -424863,7 +425006,7 @@ ] ], "navigate.py": [ - "ead4f5aa04befe664f17036de925fd9df7626470", + "9426ea089b0f24da8576ac39eab74abe4abe4786", [ null, {} @@ -425377,7 +425520,7 @@ }, "get_window_handles": { "get.py": [ - "07ff9d4d26fd3b7cff5620b5295ebe386a226cf2", + "b25d76ce588449cf3279aa61e4c1c39863e44d12", [ null, {} @@ -425747,7 +425890,7 @@ }, "permissions": { "set.py": [ - "349462dbb5037321e16b92b8055bd94c015ea11c", + "4dce1589641d9c35e729344ac548f3ba99bc084a", [ null, {} @@ -425896,14 +426039,14 @@ }, "switch_to_window": { "alerts.py": [ - "8824138c2d25c07232847062c4853d73075eb94e", + "2fc390e8641b980bc1c317db93f9f1166bcb8284", [ null, {} ] ], "switch.py": [ - "907be66a149e8196c87760544140636d9625bbb9", + "8fb80fb3238f99eae758658d7796b29c1f8db717", [ null, {}
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-importScripts.any.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-importScripts.any.js new file mode 100644 index 0000000..8791a09 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/checkpoint-importScripts.any.js
@@ -0,0 +1,40 @@ +// META: global=dedicatedworker,sharedworker + +// The `then` handlers for `Promise.resolve()` are evaluated in the first +// microtasks checkpoint after `Promise.resolve()`. + +// ---------------------------------------------------------------- +// Check when microtasks checkpoint is performed around importScripts(). + +// The expectation is: the `then` handlers are evaluated after the script +// calling importScripts() is finished, not immediately after importScripts(). +// Although #clean-up-after-running-script is executed as a part of +// #run-a-classic-script for importScripts()ed scripts, but at that time +// microtasks checkpoint is NOT performed because JavaScript execution context +// stack is not empty. + +self.log = []; + +// Microtasks should be executed before +// #run-a-classic-script/#run-a-module-script is completed, and thus before +// script evaluation scheduled by setTimeout(). +async_test(t => { + self.addEventListener('error', + t.unreached_func('error event should not be fired')); + + t.step_timeout(() => { + assert_array_equals(log, [ + 'importScripts()ed script', + 'catch', + 'promise' + ]); + t.done(); + }, + 0); +}, "Promise resolved during importScripts()"); + +try { + importScripts('resources/resolve-then-throw.js'); +} catch (e) { + self.log.push('catch'); +}
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/resolve-then-throw.js b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/resolve-then-throw.js new file mode 100644 index 0000000..a841eb78 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/semantics/scripting-1/the-script-element/microtasks/resources/resolve-then-throw.js
@@ -0,0 +1,3 @@ +self.log.push('importScripts()ed script'); +Promise.resolve().then(() => self.log.push('promise')); +throw new Error('foo');
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/web-animations.idl b/third_party/blink/web_tests/external/wpt/interfaces/web-animations.idl index ae64bb8..2f2b086 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/web-animations.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/web-animations.idl
@@ -24,7 +24,7 @@ optional AnimationTimeline? timeline); attribute DOMString id; attribute AnimationEffect? effect; - readonly attribute AnimationTimeline? timeline; + attribute AnimationTimeline? timeline; attribute double? startTime; attribute double? currentTime; attribute double playbackRate;
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 index 113321421..860876e 100644 --- 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
@@ -174,20 +174,4 @@ }], 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.'); </script>
diff --git a/third_party/blink/web_tests/external/wpt/tools/webdriver/webdriver/client.py b/third_party/blink/web_tests/external/wpt/tools/webdriver/webdriver/client.py index 7f122c8..fe5189ec0 100644 --- a/third_party/blink/web_tests/external/wpt/tools/webdriver/webdriver/client.py +++ b/third_party/blink/web_tests/external/wpt/tools/webdriver/webdriver/client.py
@@ -242,6 +242,15 @@ def __init__(self, session): self.session = session + @command + def close(self): + handles = self.session.send_session_command("DELETE", "window") + if handles is not None and len(handles) == 0: + # With no more open top-level browsing contexts, the session is closed. + self.session.session_id = None + + return handles + @property @command def rect(self): @@ -548,6 +557,13 @@ def source(self): return self.send_session_command("GET", "source") + @command + def new_window(self, type_hint=None): + body = {"type": type_hint} + value = self.send_session_command("POST", "window/new", body) + + return value["handle"] + @property @command def window_handle(self): @@ -569,15 +585,6 @@ return self.send_session_command("POST", url, body) - @command - def close(self): - handles = self.send_session_command("DELETE", "window") - if handles is not None and len(handles) == 0: - # With no more open top-level browsing contexts, the session is closed. - self.session_id = None - - return handles - @property @command def handles(self):
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py index 2b3d53d..695b16b 100644 --- a/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py +++ b/third_party/blink/web_tests/external/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py
@@ -112,7 +112,7 @@ for handle in handles: try: self.webdriver.window_handle = handle - self.webdriver.close() + self.webdriver.window.close() except client.NoSuchWindowException: pass self.webdriver.window_handle = self.runner_handle
diff --git a/third_party/blink/web_tests/external/wpt/web-animations/idlharness.window-expected.txt b/third_party/blink/web_tests/external/wpt/web-animations/idlharness.window-expected.txt new file mode 100644 index 0000000..3725def --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/web-animations/idlharness.window-expected.txt
@@ -0,0 +1,149 @@ +This is a testharness.js-based test. +Found 145 tests; 144 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS idl_test setup +PASS idl_test validation +PASS Partial interface Document: original interface defined +PASS Partial interface Document: member names are unique +PASS Partial interface mixin DocumentOrShadowRoot: original interface mixin defined +PASS Partial interface mixin DocumentOrShadowRoot: member names are unique +PASS Partial interface Document[2]: member names are unique +PASS Partial interface Document[3]: member names are unique +PASS Element includes Animatable: member names are unique +PASS Element includes ParentNode: member names are unique +PASS Element includes NonDocumentTypeChildNode: member names are unique +PASS Element includes ChildNode: member names are unique +PASS Element includes Slottable: member names are unique +PASS Document includes NonElementParentNode: member names are unique +PASS Document includes DocumentOrShadowRoot: member names are unique +PASS Document includes ParentNode: member names are unique +PASS Document includes XPathEvaluatorBase: member names are unique +PASS Document includes GlobalEventHandlers: member names are unique +PASS Document includes DocumentAndElementEventHandlers: member names are unique +PASS DocumentFragment includes NonElementParentNode: member names are unique +PASS DocumentFragment includes ParentNode: member names are unique +PASS ShadowRoot includes DocumentOrShadowRoot: member names are unique +PASS AnimationTimeline interface: existence and properties of interface object +PASS AnimationTimeline interface object length +PASS AnimationTimeline interface object name +PASS AnimationTimeline interface: existence and properties of interface prototype object +PASS AnimationTimeline interface: existence and properties of interface prototype object's "constructor" property +PASS AnimationTimeline interface: existence and properties of interface prototype object's @@unscopables property +PASS AnimationTimeline interface: attribute currentTime +PASS AnimationTimeline interface: attribute phase +PASS DocumentTimeline interface: existence and properties of interface object +PASS DocumentTimeline interface object length +PASS DocumentTimeline interface object name +PASS DocumentTimeline interface: existence and properties of interface prototype object +PASS DocumentTimeline interface: existence and properties of interface prototype object's "constructor" property +PASS DocumentTimeline interface: existence and properties of interface prototype object's @@unscopables property +PASS DocumentTimeline must be primary interface of document.timeline +PASS Stringification of document.timeline +PASS AnimationTimeline interface: document.timeline must inherit property "currentTime" with the proper type +PASS AnimationTimeline interface: document.timeline must inherit property "phase" with the proper type +PASS Animation interface: existence and properties of interface object +PASS Animation interface object length +PASS Animation interface object name +PASS Animation interface: existence and properties of interface prototype object +PASS Animation interface: existence and properties of interface prototype object's "constructor" property +PASS Animation interface: existence and properties of interface prototype object's @@unscopables property +PASS Animation interface: attribute id +PASS Animation interface: attribute effect +FAIL Animation interface: attribute timeline assert_equals: setter must be function for PutForwards, Replaceable, or non-readonly attributes expected "function" but got "undefined" +PASS Animation interface: attribute startTime +PASS Animation interface: attribute currentTime +PASS Animation interface: attribute playbackRate +PASS Animation interface: attribute playState +PASS Animation interface: attribute replaceState +PASS Animation interface: attribute pending +PASS Animation interface: attribute ready +PASS Animation interface: attribute finished +PASS Animation interface: attribute onfinish +PASS Animation interface: attribute oncancel +PASS Animation interface: attribute onremove +PASS Animation interface: operation cancel() +PASS Animation interface: operation finish() +PASS Animation interface: operation play() +PASS Animation interface: operation pause() +PASS Animation interface: operation updatePlaybackRate(double) +PASS Animation interface: operation reverse() +PASS Animation interface: operation persist() +PASS Animation interface: operation commitStyles() +PASS Animation must be primary interface of new Animation() +PASS Stringification of new Animation() +PASS Animation interface: new Animation() must inherit property "id" with the proper type +PASS Animation interface: new Animation() must inherit property "effect" with the proper type +PASS Animation interface: new Animation() must inherit property "timeline" with the proper type +PASS Animation interface: new Animation() must inherit property "startTime" with the proper type +PASS Animation interface: new Animation() must inherit property "currentTime" with the proper type +PASS Animation interface: new Animation() must inherit property "playbackRate" with the proper type +PASS Animation interface: new Animation() must inherit property "playState" with the proper type +PASS Animation interface: new Animation() must inherit property "replaceState" with the proper type +PASS Animation interface: new Animation() must inherit property "pending" with the proper type +PASS Animation interface: new Animation() must inherit property "ready" with the proper type +PASS Animation interface: new Animation() must inherit property "finished" with the proper type +PASS Animation interface: new Animation() must inherit property "onfinish" with the proper type +PASS Animation interface: new Animation() must inherit property "oncancel" with the proper type +PASS Animation interface: new Animation() must inherit property "onremove" with the proper type +PASS Animation interface: new Animation() must inherit property "cancel()" with the proper type +PASS Animation interface: new Animation() must inherit property "finish()" with the proper type +PASS Animation interface: new Animation() must inherit property "play()" with the proper type +PASS Animation interface: new Animation() must inherit property "pause()" with the proper type +PASS Animation interface: new Animation() must inherit property "updatePlaybackRate(double)" with the proper type +PASS Animation interface: calling updatePlaybackRate(double) on new Animation() with too few arguments must throw TypeError +PASS Animation interface: new Animation() must inherit property "reverse()" with the proper type +PASS Animation interface: new Animation() must inherit property "persist()" with the proper type +PASS Animation interface: new Animation() must inherit property "commitStyles()" with the proper type +PASS AnimationEffect interface: existence and properties of interface object +PASS AnimationEffect interface object length +PASS AnimationEffect interface object name +PASS AnimationEffect interface: existence and properties of interface prototype object +PASS AnimationEffect interface: existence and properties of interface prototype object's "constructor" property +PASS AnimationEffect interface: existence and properties of interface prototype object's @@unscopables property +PASS AnimationEffect interface: operation getTiming() +PASS AnimationEffect interface: operation getComputedTiming() +PASS AnimationEffect interface: operation updateTiming(optional OptionalEffectTiming) +PASS KeyframeEffect interface: existence and properties of interface object +PASS KeyframeEffect interface object length +PASS KeyframeEffect interface object name +PASS KeyframeEffect interface: existence and properties of interface prototype object +PASS KeyframeEffect interface: existence and properties of interface prototype object's "constructor" property +PASS KeyframeEffect interface: existence and properties of interface prototype object's @@unscopables property +PASS KeyframeEffect interface: attribute target +PASS KeyframeEffect interface: attribute pseudoElement +PASS KeyframeEffect interface: attribute composite +PASS KeyframeEffect interface: operation getKeyframes() +PASS KeyframeEffect interface: operation setKeyframes(object?) +PASS KeyframeEffect must be primary interface of new KeyframeEffect(null, null) +PASS Stringification of new KeyframeEffect(null, null) +PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "target" with the proper type +PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "pseudoElement" with the proper type +PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "composite" with the proper type +PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "getKeyframes()" with the proper type +PASS KeyframeEffect interface: new KeyframeEffect(null, null) must inherit property "setKeyframes(object?)" with the proper type +PASS KeyframeEffect interface: calling setKeyframes(object?) on new KeyframeEffect(null, null) with too few arguments must throw TypeError +PASS AnimationEffect interface: new KeyframeEffect(null, null) must inherit property "getTiming()" with the proper type +PASS AnimationEffect interface: new KeyframeEffect(null, null) must inherit property "getComputedTiming()" with the proper type +PASS AnimationEffect interface: new KeyframeEffect(null, null) must inherit property "updateTiming(optional OptionalEffectTiming)" with the proper type +PASS AnimationEffect interface: calling updateTiming(optional OptionalEffectTiming) on new KeyframeEffect(null, null) with too few arguments must throw TypeError +PASS AnimationPlaybackEvent interface: existence and properties of interface object +PASS AnimationPlaybackEvent interface object length +PASS AnimationPlaybackEvent interface object name +PASS AnimationPlaybackEvent interface: existence and properties of interface prototype object +PASS AnimationPlaybackEvent interface: existence and properties of interface prototype object's "constructor" property +PASS AnimationPlaybackEvent interface: existence and properties of interface prototype object's @@unscopables property +PASS AnimationPlaybackEvent interface: attribute currentTime +PASS AnimationPlaybackEvent interface: attribute timelineTime +PASS AnimationPlaybackEvent must be primary interface of new AnimationPlaybackEvent("cancel") +PASS Stringification of new AnimationPlaybackEvent("cancel") +PASS AnimationPlaybackEvent interface: new AnimationPlaybackEvent("cancel") must inherit property "currentTime" with the proper type +PASS AnimationPlaybackEvent interface: new AnimationPlaybackEvent("cancel") must inherit property "timelineTime" with the proper type +PASS Document interface: attribute timeline +PASS Document interface: operation getAnimations() +PASS Document interface: document must inherit property "timeline" with the proper type +PASS Document interface: document must inherit property "getAnimations()" with the proper type +PASS ShadowRoot interface: operation getAnimations() +PASS ShadowRoot interface: shadowRoot must inherit property "getAnimations()" with the proper type +PASS Element interface: operation animate(object?, optional (unrestricted double or KeyframeAnimationOptions)) +PASS Element interface: operation getAnimations(optional GetAnimationsOptions) +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/back/conftest.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/back/conftest.py index d5fd320a..bd5db0c 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/back/conftest.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/back/conftest.py
@@ -4,15 +4,15 @@ @pytest.fixture(name="session") -def fixture_session(capabilities, session, create_window): +def fixture_session(capabilities, session): """Prevent re-using existent history by running the test in a new window.""" original_handle = session.window_handle - session.window_handle = create_window() + session.window_handle = session.new_window() yield session try: - session.close() + session.window.close() except NoSuchWindowException: pass
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/close_window/close.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/close_window/close.py index f4e3b04..fa82367 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/close_window/close.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/close_window/close.py
@@ -15,10 +15,10 @@ assert_error(response, "no such window") -def test_close_browsing_context(session, create_window): +def test_close_browsing_context(session): original_handles = session.handles - new_handle = create_window() + new_handle = session.new_window() session.window_handle = new_handle response = close(session) @@ -27,10 +27,10 @@ assert new_handle not in handles -def test_close_browsing_context_with_dismissed_beforeunload_prompt(session, create_window): +def test_close_browsing_context_with_dismissed_beforeunload_prompt(session): original_handles = session.handles - new_handle = create_window() + new_handle = session.new_window() session.window_handle = new_handle session.url = inline("""
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/close_window/user_prompts.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/close_window/user_prompts.py index 22df9155e..c0f9cc7 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/close_window/user_prompts.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/close_window/user_prompts.py
@@ -11,10 +11,10 @@ @pytest.fixture -def check_user_prompt_closed_without_exception(session, create_dialog, create_window): +def check_user_prompt_closed_without_exception(session, create_dialog): def check_user_prompt_closed_without_exception(dialog_type, retval): original_handle = session.window_handle - new_handle = create_window() + new_handle = session.new_window() session.window_handle = new_handle create_dialog(dialog_type, text=dialog_type) @@ -34,9 +34,9 @@ @pytest.fixture -def check_user_prompt_closed_with_exception(session, create_dialog, create_window): +def check_user_prompt_closed_with_exception(session, create_dialog): def check_user_prompt_closed_with_exception(dialog_type, retval): - new_handle = create_window() + new_handle = session.new_window() session.window_handle = new_handle create_dialog(dialog_type, text=dialog_type) @@ -52,9 +52,9 @@ @pytest.fixture -def check_user_prompt_not_closed_but_exception(session, create_dialog, create_window): +def check_user_prompt_not_closed_but_exception(session, create_dialog): def check_user_prompt_not_closed_but_exception(dialog_type): - new_handle = create_window() + new_handle = session.new_window() session.window_handle = new_handle create_dialog(dialog_type, text=dialog_type)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/navigate.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/navigate.py index ead4f5a..9426ea0 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/navigate.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/navigate.py
@@ -1,8 +1,7 @@ -import pytest - -from tests.support.asserts import assert_error, assert_success +from tests.support.asserts import assert_success from tests.support.inline import inline + def element_click(session, element): return session.transport.send( "POST", "session/{session_id}/element/{element_id}/click".format( @@ -93,12 +92,14 @@ """, args=(element,)) is True -def test_link_closes_window(session, create_window): - new_handle = create_window() +def test_link_closes_window(session, url): + new_handle = session.new_window() session.window_handle = new_handle - session.url = inline("""<a href="/webdriver/tests/element_click/support/close_window.html">asdf</a>""") + session.url = inline("""<a href="javascript:window.close()">Close me</a>""") element = session.find.css("a", all=False) + response = element_click(session, element) assert_success(response) + assert new_handle not in session.handles
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/support/close_window.html b/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/support/close_window.html deleted file mode 100644 index 7a361982..0000000 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/element_click/support/close_window.html +++ /dev/null
@@ -1,9 +0,0 @@ -<html> - <body onload="checkload()"> - <script> - function checkload() { - window.close() - } - </script> - </body> -</html>
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/forward/conftest.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/forward/conftest.py index d5fd320a..bd5db0c 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/forward/conftest.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/forward/conftest.py
@@ -4,15 +4,15 @@ @pytest.fixture(name="session") -def fixture_session(capabilities, session, create_window): +def fixture_session(capabilities, session): """Prevent re-using existent history by running the test in a new window.""" original_handle = session.window_handle - session.window_handle = create_window() + session.window_handle = session.new_window() yield session try: - session.close() + session.window.close() except NoSuchWindowException: pass
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/get_window_handles/get.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/get_window_handles/get.py index 07ff9d4..b25d76c 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/get_window_handles/get.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/get_window_handles/get.py
@@ -6,12 +6,11 @@ "GET", "session/{session_id}/window/handles".format(**vars(session))) -def test_no_browsing_context(session, create_window): +def test_no_browsing_context(session): window_handles = session.handles - new_handle = create_window() - session.window_handle = new_handle - session.close() + session.window_handle = session.new_window() + session.window.close() response = get_window_handles(session) assert_success(response, window_handles) @@ -26,9 +25,9 @@ assert value[0] == session.window_handle -def test_multiple_windows(session, create_window): +def test_multiple_windows(session): original_handle = session.window_handle - new_handle = create_window() + new_handle = session.new_window() response = get_window_handles(session) value = assert_success(response)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/permissions/set.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/permissions/set.py index 349462d..4dce158 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/permissions/set.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/permissions/set.py
@@ -100,10 +100,10 @@ {} ]) @pytest.mark.capabilities({"acceptInsecureCerts": True}) -def test_set_to_state_cross_realm(session, create_window, url, state, realmSetting): +def test_set_to_state_cross_realm(session, url, state, realmSetting): session.url = url("/common/blank.html", protocol="https") original_window = session.window_handle - session.window_handle = create_window() + session.window_handle = session.new_window() session.url = url("/common/blank.html", protocol="https") parameters = { "descriptor": { "name": "geolocation" }, "state": state } parameters.update(realmSetting)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/send_alert_text/conftest.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/send_alert_text/conftest.py index f34630c..b080761 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/send_alert_text/conftest.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/send_alert_text/conftest.py
@@ -4,10 +4,10 @@ @pytest.fixture(name="session") -def fixture_session(capabilities, session, create_window): +def fixture_session(capabilities, session): """Prevent dialog rate limits by running the test in a new window.""" original_handle = session.window_handle - session.window_handle = create_window() + session.window_handle = session.new_window() yield session @@ -17,7 +17,7 @@ pass try: - session.close() + session.window.close() except NoSuchWindowException: pass
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/support/fixtures.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/support/fixtures.py index 80ccfdd..364ede1 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/support/fixtures.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/support/fixtures.py
@@ -88,18 +88,6 @@ @pytest.fixture -def create_window(session): - """Open new window and return the window handle.""" - def create_window(): - windows_before = session.handles - name = session.execute_script("window.open()") - assert len(session.handles) == len(windows_before) + 1 - new_windows = list(set(session.handles) - set(windows_before)) - return new_windows.pop() - return create_window - - -@pytest.fixture def http(configuration): return HTTPRequest(configuration["host"], configuration["port"]) @@ -224,13 +212,13 @@ @pytest.fixture -def closed_window(session, create_window): +def closed_window(session): original_handle = session.window_handle + new_handle = session.new_window() - new_handle = create_window() session.window_handle = new_handle - session.close() + session.window.close() assert new_handle not in session.handles, "Unable to close window {}".format(new_handle) yield new_handle
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/support/helpers.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/support/helpers.py index 8bc53e7..f857083 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/support/helpers.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/support/helpers.py
@@ -70,7 +70,7 @@ for window in _windows(session, exclude=[current_window]): session.window_handle = window if len(session.handles) > 1: - session.close() + session.window.close() session.window_handle = current_window
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/switch_to_window/alerts.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/switch_to_window/alerts.py index 8824138..2fc390e 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/switch_to_window/alerts.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/switch_to_window/alerts.py
@@ -11,10 +11,10 @@ {"handle": handle}) -def test_retain_tab_modal_status(session, create_window): +def test_retain_tab_modal_status(session): handle = session.window_handle - new_handle = create_window() + new_handle = session.new_window() response = switch_to_window(session, new_handle) assert_success(response)
diff --git a/third_party/blink/web_tests/external/wpt/webdriver/tests/switch_to_window/switch.py b/third_party/blink/web_tests/external/wpt/webdriver/tests/switch_to_window/switch.py index 907be66..8fb80fb 100644 --- a/third_party/blink/web_tests/external/wpt/webdriver/tests/switch_to_window/switch.py +++ b/third_party/blink/web_tests/external/wpt/webdriver/tests/switch_to_window/switch.py
@@ -15,9 +15,7 @@ assert_error(Response.from_http(response), "invalid argument") -def test_null_response_value(session, create_window): - new_handle = create_window() - - response = switch_to_window(session, new_handle) +def test_null_response_value(session): + response = switch_to_window(session, session.new_window()) value = assert_success(response) assert value is None
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCDTMFSender-insertDTMF.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCDTMFSender-insertDTMF.https-expected.txt deleted file mode 100644 index 5bd1585..0000000 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCDTMFSender-insertDTMF.https-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -This is a testharness.js-based test. -PASS insertDTMF() should succeed if tones contains valid DTMF characters -PASS insertDTMF() should throw InvalidCharacterError if tones contains invalid DTMF characters -FAIL insertDTMF() should throw InvalidStateError if transceiver is stopped transceiver.stop is not a function -PASS insertDTMF() should throw InvalidStateError if transceiver.currentDirection is recvonly -PASS insertDTMF() should throw InvalidStateError if transceiver.currentDirection is inactive -PASS insertDTMF() should set toneBuffer to provided tones normalized, with old tones overridden -PASS insertDTMF() after remove and close should reject -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-createDataChannel-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-createDataChannel-expected.txt index b2f2fdb..e8ee8c6 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-createDataChannel-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-createDataChannel-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 52 tests; 46 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 50 tests; 46 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS createDataChannel with no argument should throw TypeError PASS createDataChannel with closed connection should throw InvalidStateError FAIL createDataChannel attribute default values assert_equals: expected "blob" but got "arraybuffer" @@ -47,10 +47,8 @@ PASS New datachannel should be in the connecting state after creation (after connection establishment) PASS addTrack, then creating datachannel, should negotiate properly PASS addTrack, then creating datachannel, should negotiate properly when max-bundle is used -FAIL Stopping the bundle-tag when there is a datachannel in the bundle should kill the DataChannel promise_test: Unhandled rejection with value: object "TypeError: pc2.getTransceivers(...)[0].stop is not a function" PASS New negotiated datachannel should be in the connecting state after creation (after connection establishment) PASS addTrack, then creating negotiated datachannel, should negotiate properly PASS addTrack, then creating negotiated datachannel, should negotiate properly when max-bundle is used -FAIL Stopping the bundle-tag when there is a negotiated datachannel in the bundle should kill the DataChannel promise_test: Unhandled rejection with value: object "TypeError: pc2.getTransceivers(...)[0].stop is not a function" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-createDataChannel.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-createDataChannel.html index 87867664..7ad8bf7 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-createDataChannel.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-createDataChannel.html
@@ -707,6 +707,11 @@ await createDataChannelPair(t, options, pc1); }, `addTrack, then creating ${mode}, should negotiate properly when max-bundle is used`); +/* +This test is disabled until https://github.com/w3c/webrtc-pc/issues/2562 +has been resolved; it presupposes that stopping the first transceiver +breaks the transport. + promise_test(async t => { const pc1 = new RTCPeerConnection({bundlePolicy: "max-bundle"}); const pc2 = new RTCPeerConnection(); @@ -726,6 +731,7 @@ await dc1Closed; }, `Stopping the bundle-tag when there is a ${mode} in the bundle ` + `should kill the DataChannel`); +*/ } /*
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceGatheringState.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceGatheringState.html index d9e3f42..88acf34 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceGatheringState.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-iceGatheringState.html
@@ -137,8 +137,12 @@ await pc1.setLocalDescription(await pc1.createOffer()); await pc2.setRemoteDescription(pc1.localDescription); await pc2.setLocalDescription(await pc2.createAnswer()); + assert_equals(pc2.getTransceivers().length, 0, + 'PC2 transceivers should be invisible after negotiation'); await iceGatheringStateTransitions(pc2, 'new'); await pc1.setRemoteDescription(pc2.localDescription); + assert_equals(pc1.getTransceivers().length, 0, + 'PC1 transceivers should be invisible after negotiation'); await iceGatheringStateTransitions(pc1, 'new'); }, 'renegotiation that closes all transports should result in ICE gathering state "new"');
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-removeTrack.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-removeTrack.https-expected.txt deleted file mode 100644 index b2be9c6..0000000 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-removeTrack.https-expected.txt +++ /dev/null
@@ -1,17 +0,0 @@ -This is a testharness.js-based test. -PASS addTransceiver - Calling removeTrack when connection is closed should throw InvalidStateError -PASS addTrack - Calling removeTrack when connection is closed should throw InvalidStateError -PASS addTransceiver - Calling removeTrack on different connection that is closed should throw InvalidStateError -PASS addTrack - Calling removeTrack on different connection that is closed should throw InvalidStateError -PASS addTransceiver - Calling removeTrack on different connection should throw InvalidAccessError -PASS addTrack - Calling removeTrack on different connection should throw InvalidAccessError -PASS addTransceiver - Calling removeTrack with valid sender should set sender.track to null -PASS addTrack - Calling removeTrack with valid sender should set sender.track to null -PASS Calling removeTrack with currentDirection sendrecv should set direction to recvonly -PASS Calling removeTrack with currentDirection sendonly should set direction to inactive -PASS Calling removeTrack with currentDirection recvonly should not change direction -PASS Calling removeTrack with currentDirection inactive should not change direction -FAIL Calling removeTrack on a stopped transceiver should be a no-op promise_test: Unhandled rejection with value: object "TypeError: pc.getTransceivers(...)[0].stop is not a function" -PASS Calling removeTrack on a null track should have no effect -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt index 77588ee..bee8749 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-setDescription-transceiver-expected.txt
@@ -4,6 +4,6 @@ PASS setLocalDescription(rollback) should unset transceiver.mid PASS setLocalDescription(rollback) should only unset transceiver mids associated with current round PASS setRemoteDescription(rollback) should remove newly created transceiver from transceiver list -FAIL setRemoteDescription should stop the transceiver if its corresponding m section is rejected promise_test: Unhandled rejection with value: object "TypeError: pc2.getTransceivers(...)[0].stop is not a function" +FAIL setRemoteDescription should stop the transceiver if its corresponding m section is rejected assert_true: Transceiver is stopped expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt index 484741a9..5431b22 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-replaceTrack.https-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. PASS Calling replaceTrack on closed connection should reject with InvalidStateError FAIL Calling replaceTrack with track of different kind should reject with TypeError promise_rejects_js: function "function() { throw e }" threw object "InvalidModificationError" ("InvalidModificationError") expected instance of function "function TypeError() { [native code] }" ("TypeError") -FAIL Calling replaceTrack on stopped sender should reject with InvalidStateError promise_test: Unhandled rejection with value: object "TypeError: transceiver.stop is not a function" +FAIL Calling replaceTrack on stopped sender should reject with InvalidStateError promise_rejects_dom: function "function() { throw e }" threw object "InvalidModificationError" that is not a DOMException InvalidStateError: property "code" is equal to 13, expected 11 PASS Calling replaceTrack on sender with null track and not set to session description should resolve with sender.track set to given track PASS Calling replaceTrack on sender not set to session description should resolve with sender.track set to given track PASS Calling replaceTrack(null) on sender not set to session description should resolve with sender.track set to null
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters-expected.txt deleted file mode 100644 index 2fc9877..0000000 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpSender-setParameters-expected.txt +++ /dev/null
@@ -1,4 +0,0 @@ -This is a testharness.js-based test. -FAIL setParameters() when transceiver is stopped should reject with InvalidStateError transceiver.stop is not a function -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt index 80df5031..d7e8b20 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCRtpTransceiver-stop-expected.txt
@@ -1,7 +1,7 @@ This is a testharness.js-based test. -FAIL A transceiver added and stopped before the initial offer generation should not trigger an offer m-section generation promise_test: Unhandled rejection with value: object "TypeError: pc1.getTransceivers(...)[0].stop is not a function" -FAIL During renegotiation, adding and stopping a transceiver should not trigger a renegotiated offer m-section generation promise_test: Unhandled rejection with value: object "TypeError: pc1.getTransceivers(...)[0].stop is not a function" -FAIL A stopped sendonly transceiver should generate a sendonly m-section in the offer promise_test: Unhandled rejection with value: object "TypeError: pc1.getTransceivers(...)[0].stop is not a function" -FAIL A stopped inactive transceiver should generate an inactive m-section in the offer promise_test: Unhandled rejection with value: object "TypeError: pc1.getTransceivers(...)[0].stop is not a function" +PASS A transceiver added and stopped before the initial offer generation should not trigger an offer m-section generation +PASS During renegotiation, adding and stopping a transceiver should not trigger a renegotiated offer m-section generation +FAIL A stopped sendonly transceiver should generate a sendonly m-section in the offer assert_true: The audio m-section should be sendonly expected true got false +PASS A stopped inactive transceiver should generate an inactive m-section in the offer Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt index d4c1de61..8b39ad8 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 496 tests; 477 PASS, 19 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 496 tests; 479 PASS, 17 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS idl_test validation PASS Test driver for asyncInitCertificate @@ -290,7 +290,7 @@ PASS RTCRtpTransceiver interface: attribute receiver PASS RTCRtpTransceiver interface: attribute direction PASS RTCRtpTransceiver interface: attribute currentDirection -FAIL RTCRtpTransceiver interface: operation stop() assert_own_property: interface prototype object missing non-static operation expected property "stop" missing +PASS RTCRtpTransceiver interface: operation stop() PASS RTCRtpTransceiver interface: operation setCodecPreferences(sequence<RTCRtpCodecCapability>) PASS RTCRtpTransceiver must be primary interface of new RTCPeerConnection().addTransceiver('audio') PASS Stringification of new RTCPeerConnection().addTransceiver('audio') @@ -299,7 +299,7 @@ PASS RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "receiver" with the proper type PASS RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "direction" with the proper type PASS RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "currentDirection" with the proper type -FAIL RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "stop()" with the proper type assert_inherits: property "stop" not found in prototype chain +PASS RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "stop()" with the proper type PASS RTCRtpTransceiver interface: new RTCPeerConnection().addTransceiver('audio') must inherit property "setCodecPreferences(sequence<RTCRtpCodecCapability>)" with the proper type PASS RTCRtpTransceiver interface: calling setCodecPreferences(sequence<RTCRtpCodecCapability>) on new RTCPeerConnection().addTransceiver('audio') with too few arguments must throw TypeError PASS RTCDtlsTransport interface: existence and properties of interface object
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-createDataChannel-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-createDataChannel-expected.txt deleted file mode 100644 index 5b09dab..0000000 --- a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-createDataChannel-expected.txt +++ /dev/null
@@ -1,56 +0,0 @@ -This is a testharness.js-based test. -Found 52 tests; 46 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. -PASS createDataChannel with no argument should throw TypeError -PASS createDataChannel with closed connection should throw InvalidStateError -FAIL createDataChannel attribute default values assert_equals: expected "blob" but got "arraybuffer" -FAIL createDataChannel with provided parameters should initialize attributes to provided values assert_equals: expected "blob" but got "arraybuffer" -PASS createDataChannel with label "foo" should succeed -PASS createDataChannel with label null should succeed -PASS createDataChannel with label undefined should succeed -PASS createDataChannel with label lone surrogate should succeed -PASS createDataChannel with ordered false should succeed -PASS createDataChannel with ordered null/undefined should succeed -PASS createDataChannel with maxPacketLifeTime 0 should succeed -PASS createDataChannel with maxRetransmits 0 should succeed -PASS createDataChannel with both maxPacketLifeTime and maxRetransmits undefined should succeed -PASS createDataChannel with both maxPacketLifeTime and maxRetransmits should throw TypeError -PASS createDataChannel with protocol "foo" should succeed -PASS createDataChannel with protocol null should succeed -PASS createDataChannel with protocol undefined should succeed -PASS createDataChannel with protocol lone surrogate should succeed -PASS createDataChannel with id 0 and negotiated not set should succeed, but not set the channel's id -PASS createDataChannel with id 1 and negotiated not set should succeed, but not set the channel's id -PASS createDataChannel with id 65534 and negotiated not set should succeed, but not set the channel's id -FAIL createDataChannel with id 65535 and negotiated not set should succeed, but not set the channel's id Failed to execute 'createDataChannel' on 'RTCPeerConnection': RTCDataChannel cannot have id > 65534 -PASS createDataChannel with id 0 and negotiated true should succeed, and set the channel's id -PASS createDataChannel with id 1 and negotiated true should succeed, and set the channel's id -FAIL createDataChannel with id 65534 and negotiated true should succeed, and set the channel's id Failed to execute 'createDataChannel' on 'RTCPeerConnection': RTCDataChannel creation failed -PASS createDataChannel with id -1 and negotiated not set should throw TypeError -PASS createDataChannel with id 65536 and negotiated not set should throw TypeError -PASS createDataChannel with id -1 should throw TypeError -PASS createDataChannel with id 65535 should throw TypeError -PASS createDataChannel with id 65536 should throw TypeError -PASS createDataChannel with too long label should throw TypeError -PASS createDataChannel with too long label (2 byte unicode) should throw TypeError -PASS createDataChannel with same label used twice should not throw -PASS createDataChannel with negotiated true and id should succeed -PASS createDataChannel with too long protocol should throw TypeError -PASS createDataChannel with too long protocol (2 byte unicode) should throw TypeError -PASS createDataChannel with maximum length label and protocol should succeed -PASS createDataChannel with negotiated false should succeed -PASS createDataChannel with negotiated false and id 42 should ignore the id -PASS createDataChannel with negotiated true and id not defined should throw TypeError -PASS Channels created (after setRemoteDescription) should have id assigned -PASS Reusing a data channel id that is in use should throw OperationError -PASS Reusing a data channel id that is in use (after setRemoteDescription) should throw OperationError -PASS Reusing a data channel id that is in use (after setRemoteDescription, negotiated via DCEP) should throw OperationError -PASS New datachannel should be in the connecting state after creation (after connection establishment) -PASS addTrack, then creating datachannel, should negotiate properly -PASS addTrack, then creating datachannel, should negotiate properly when max-bundle is used -FAIL Stopping the bundle-tag when there is a datachannel in the bundle should kill the DataChannel promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'stop' of undefined" -PASS New negotiated datachannel should be in the connecting state after creation (after connection establishment) -PASS addTrack, then creating negotiated datachannel, should negotiate properly -PASS addTrack, then creating negotiated datachannel, should negotiate properly when max-bundle is used -FAIL Stopping the bundle-tag when there is a negotiated datachannel in the bundle should kill the DataChannel promise_test: Unhandled rejection with value: object "TypeError: Cannot read property 'stop' of undefined" -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt index 5149a2d..a48e141 100644 --- a/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/virtual/webrtc-wpt-plan-b/external/wpt/webrtc/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 496 tests; 410 PASS, 86 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 496 tests; 411 PASS, 85 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS idl_test validation PASS Test driver for asyncInitCertificate @@ -290,7 +290,7 @@ PASS RTCRtpTransceiver interface: attribute receiver PASS RTCRtpTransceiver interface: attribute direction PASS RTCRtpTransceiver interface: attribute currentDirection -FAIL RTCRtpTransceiver interface: operation stop() assert_own_property: interface prototype object missing non-static operation expected property "stop" missing +PASS RTCRtpTransceiver interface: operation stop() PASS RTCRtpTransceiver interface: operation setCodecPreferences(sequence<RTCRtpCodecCapability>) FAIL RTCRtpTransceiver must be primary interface of new RTCPeerConnection().addTransceiver('audio') assert_equals: Unexpected exception when evaluating object expected null but got object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'." FAIL Stringification of new RTCPeerConnection().addTransceiver('audio') assert_equals: Unexpected exception when evaluating object expected null but got object "InvalidStateError: Failed to execute 'addTransceiver' on 'RTCPeerConnection': This operation is only supported in 'unified-plan'."
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 1971fdd..1610113b 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -6584,6 +6584,7 @@ getter stopped method constructor method setCodecPreferences + method stop setter direction interface RTCSctpTransport : EventTarget attribute @@toStringTag
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 9d1e453..093e9cc 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -28700,6 +28700,8 @@ <int value="3371" label="WindowClosed"/> <int value="3372" label="WrongBaselineOfMultiLineButton"/> <int value="3373" label="WrongBaselineOfEmptyLineButton"/> + <int value="3374" label="V8RTCRtpTransceiver_Stopped_AttributeGetter"/> + <int value="3375" label="V8RTCRtpTransceiver_Stop_Method"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -37177,6 +37179,9 @@ <int value="1" label="QR Code Image"/> <int value="2" label="History Entry"/> <int value="3" label="Reading List Entry"/> + <int value="4" label="Bookmarks Entry"/> + <int value="5" label="Most Visited Tile"/> + <int value="6" label="Recent Tabs Entry"/> </enum> <enum name="IOSContentSizeCategory"> @@ -39616,7 +39621,9 @@ <int value="1" label="Allowed"/> <int value="2" label="Navigation not eligibile"/> <int value="3" label="Blocklisted due to rebuffers"/> - <int value="4" label="Blocklisted due to reloads/back-forwards"/> + <int value="4" label="Blocklisted due to frequent reloads/back-forwards"/> + <int value="5" label="Blocklisted because page transition was a reload"/> + <int value="6" label="Blocklisted because page transition was back-forwards"/> </enum> <enum name="LiteVideoDecision"> @@ -40341,6 +40348,7 @@ <int value="-1734666001" label="SafeBrowsingEnhancedProtection:enabled"/> <int value="-1734254845" label="ash-enable-night-light"/> <int value="-1732888954" label="UseButtonTranslateBubbleUI:enabled"/> + <int value="-1732777136" label="SignInProfileCreationFlow:disabled"/> <int value="-1732561795" label="ConsistentOmniboxGeolocation:enabled"/> <int value="-1731267886" label="AutofillEnableStickyPaymentsBubble:enabled"/> <int value="-1731149013" label="AndroidMessagesIntegration:enabled"/> @@ -41508,6 +41516,7 @@ <int value="-520221221" label="UserDataSnapshot:enabled"/> <int value="-520004021" label="WebXRHitTest:disabled"/> <int value="-519960638" label="enable-site-engagement-service"/> + <int value="-519844731" label="SignInProfileCreationFlow:enabled"/> <int value="-518104091" label="NewAudioRenderingMixingStrategy:enabled"/> <int value="-516845951" label="enable-embedded-extension-options"/> <int value="-515913489" label="EphemeralTabUsingBottomSheet:disabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 37fe248..4a73645c 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -39114,19 +39114,18 @@ </summary> </histogram> -<histogram name="DemoMode.ActiveApp" enum="DemoModeApp" expires_after="M86"> - <owner>michaelpg@chromium.org</owner> - <owner>ovanieva@chromium.org</owner> - <owner>tbarzic@chromium.org</owner> +<histogram name="DemoMode.ActiveApp" enum="DemoModeApp" expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> The currently active app or window. Sampled during demo sessions and reported while the user remains active. </summary> </histogram> -<histogram name="DemoMode.AppLaunched" enum="DemoModeApp" expires_after="M86"> - <owner>danan@chromium.org</owner> - <owner>michaelpg@chromium.org</owner> +<histogram name="DemoMode.AppLaunched" enum="DemoModeApp" expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> Records apps that have been launched by a user using the device during Demo mode. The sample is recorded when each app is launched. For any given app @@ -39135,18 +39134,18 @@ </histogram> <histogram name="DemoMode.AppLaunchSource" enum="DemoModeAppLaunchSource" - expires_after="M86"> - <owner>danan@chromium.org</owner> - <owner>michaelpg@chromium.org</owner> + expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> The source of app launches in demo mode, either the shelf, the app list, or the highlights app. </summary> </histogram> -<histogram name="DemoMode.DwellTime" units="seconds" expires_after="2021-03-23"> - <owner>mlcui@google.com</owner> - <owner>cros-essential-apps-dev@chromium.org</owner> +<histogram name="DemoMode.DwellTime" units="seconds" expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> The duration the user spent interacting with the demo session, measured from the first user activity to the last user activity. This metric rounds the @@ -39156,10 +39155,9 @@ </histogram> <histogram name="DemoMode.IdleLogoutWarningEvent" - enum="DemoModeIdleLogoutWarningEvent" expires_after="M86"> - <owner>michaelpg@chromium.org</owner> - <owner>ovanieva@chromium.org</owner> - <owner>wzang@chromium.org</owner> + enum="DemoModeIdleLogoutWarningEvent" expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> Tracks whether the idle logout warning was canceled or proceeded to logout. Note: the count of "shown" includes both cases, so the count of @@ -39169,10 +39167,9 @@ </histogram> <histogram name="DemoMode.ResourcesRemoval.Reason" - enum="DemoModeResourcesRemovalReason" expires_after="M86"> - <owner>michaelpg@chromium.org</owner> - <owner>ovanieva@chromium.org</owner> - <owner>tbarzic@chromium.org</owner> + enum="DemoModeResourcesRemovalReason" expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> Tracks the reason for removal of pre-install demo resources. To support offline demo mode, factory Chrome OS devices will have a set of offline @@ -39182,10 +39179,9 @@ </histogram> <histogram name="DemoMode.ResourcesRemoval.Result" - enum="DemoModeResourcesRemovalResult" expires_after="M86"> - <owner>michaelpg@chromium.org</owner> - <owner>ovanieva@chromium.org</owner> - <owner>tbarzic@chromium.org</owner> + enum="DemoModeResourcesRemovalResult" expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> Tracks the result of requests to remove pre-installed demo resources. To support offline demo mode, factory Chrome OS devices will have a set of @@ -39197,10 +39193,9 @@ </summary> </histogram> -<histogram name="DemoMode.SessionLength" units="minutes" expires_after="M86"> - <owner>michaelpg@chromium.org</owner> - <owner>ovanieva@chromium.org</owner> - <owner>tbarzic@chromium.org</owner> +<histogram name="DemoMode.SessionLength" units="minutes" expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> A demo session starts when a user signs in using the policy-configured public account. It stops when the user signs out, either manually or after @@ -39212,9 +39207,9 @@ </histogram> <histogram name="DemoMode.Setup.DownloadDuration" units="minutes" - expires_after="2021-03-10"> - <owner>josephkimsh@chromium.org</owner> - <owner>cros-essential-apps-dev@chromium.org</owner> + expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> This records the time taken to download the demo mode resources when demo mode is setup for the first time. @@ -39222,9 +39217,9 @@ </histogram> <histogram name="DemoMode.Setup.EnrollDuration" units="minutes" - expires_after="2021-03-10"> - <owner>josephkimsh@chromium.org</owner> - <owner>cros-essential-apps-dev@chromium.org</owner> + expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> This records the time taken to enterprise-enroll the device when demo mode is setup for the first time. @@ -39232,9 +39227,9 @@ </histogram> <histogram name="DemoMode.Setup.LoadingDuration" units="minutes" - expires_after="2021-03-10"> - <owner>josephkimsh@chromium.org</owner> - <owner>cros-essential-apps-dev@chromium.org</owner> + expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> When demo mode is setup for the first time, it must download the demo mode resources and enterprise-enroll the device. This records the time taken for @@ -39243,10 +39238,9 @@ </summary> </histogram> -<histogram name="DemoMode.Setup.NumRetries" units="units" - expires_after="2021-03-10"> - <owner>josephkimsh@chromium.org</owner> - <owner>cros-essential-apps-dev@chromium.org</owner> +<histogram name="DemoMode.Setup.NumRetries" units="units" expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> Records the number of times an operator has encountered an error during the loading screen and been required to retry setup. This is only recorded after @@ -39254,9 +39248,9 @@ </summary> </histogram> -<histogram name="DemoMode.UniqueAppsLaunched" units="units" expires_after="M86"> - <owner>danan@chromium.org</owner> - <owner>michaelpg@chromium.org</owner> +<histogram name="DemoMode.UniqueAppsLaunched" units="units" expires_after="M92"> + <owner>drcrash@chromium.org</owner> + <owner>cros-demo-mode-eng@google.com</owner> <summary> Records how many unique apps have been launched by a user using the device during Demo mode. The sample is recorded when the DemoMode session closes.
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 6875b77..78076f9 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@ { "trace_processor_shell": { "win": { - "hash": "a14d44137d62d3834efde135040e01bc3b007171", - "remote_path": "perfetto_binaries/trace_processor_shell/win/c4451adcce85638c2c52dbcc8606c04144500aa8/trace_processor_shell.exe" + "hash": "44fcb6a2624a01261a18b1c94746d06fed032a08", + "remote_path": "perfetto_binaries/trace_processor_shell/win/5697d3550bc824284097e5578ba540ec606c05fb/trace_processor_shell.exe" }, "mac": { - "hash": "615a5c6df75ce8c660c7d05b6cc2f77c4c72aac6", - "remote_path": "perfetto_binaries/trace_processor_shell/mac/c4451adcce85638c2c52dbcc8606c04144500aa8/trace_processor_shell" + "hash": "491d5aee4a10985c3a1111db30daa00f10314b69", + "remote_path": "perfetto_binaries/trace_processor_shell/mac/09afd88dfed8bbe701e0eaa096efe7b681ac12f7/trace_processor_shell" }, "linux": { - "hash": "460d53e87f53ffd242cceb35f071d41e0e7b5b90", - "remote_path": "perfetto_binaries/trace_processor_shell/linux/c4451adcce85638c2c52dbcc8606c04144500aa8/trace_processor_shell" + "hash": "5afe1dad71cc6ead4121b34f3a8d79b033524a1f", + "remote_path": "perfetto_binaries/trace_processor_shell/linux/5697d3550bc824284097e5578ba540ec606c05fb/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index af7f130..41985f56 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -3861,13 +3861,17 @@ } void AXPlatformNodeAuraLinux::OnSortDirectionChanged() { - // TODO(crbug.com/1074380) fire correct event for aria-sort change. - // AtkObject* atk_object = GetOrCreateAtkObject(); - // if (!atk_object) - // return; + AXPlatformNodeBase* table = GetTable(); + if (!table) + return; - // std::string sort; - // GetStringAttribute(ax::mojom::StringAttribute::kSortDirection, &sort); + AtkObject* atk_table = table->GetNativeViewAccessible(); + DCHECK(ATK_IS_TABLE(atk_table)); + + if (GetData().role == ax::mojom::Role::kColumnHeader) + g_signal_emit_by_name(atk_table, "row-reordered"); + else if (GetData().role == ax::mojom::Role::kRowHeader) + g_signal_emit_by_name(atk_table, "column-reordered"); } void AXPlatformNodeAuraLinux::OnValueChanged() {
diff --git a/ui/gl/gl_implementation.h b/ui/gl/gl_implementation.h index 4e8dafe..ffe19f448 100644 --- a/ui/gl/gl_implementation.h +++ b/ui/gl/gl_implementation.h
@@ -47,7 +47,8 @@ kNull = 5, kVulkan = 6, kSwiftShader = 7, - kMaxValue = kSwiftShader, + kMetal = 8, + kMaxValue = kMetal, }; struct GL_EXPORT GLWindowSystemBindingInfo {
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc index 6fe9cda..327df79 100644 --- a/ui/gl/gl_surface_egl.cc +++ b/ui/gl/gl_surface_egl.cc
@@ -116,6 +116,11 @@ #define EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE 0x3450 #endif /* EGL_ANGLE_platform_angle_vulkan */ +#ifndef EGL_ANGLE_platform_angle_metal +#define EGL_ANGLE_platform_angle_metal 1 +#define EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE 0x3489 +#endif /* EGL_ANGLE_platform_angle_metal */ + #ifndef EGL_ANGLE_x11_visual #define EGL_ANGLE_x11_visual 1 #define EGL_X11_VISUAL_ID_ANGLE 0x33A3 @@ -462,6 +467,19 @@ native_display, EGL_PLATFORM_ANGLE_TYPE_VULKAN_ANGLE, enabled_angle_features, disabled_angle_features, extra_display_attribs); + case ANGLE_METAL: + return GetPlatformANGLEDisplay( + native_display, EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, + enabled_angle_features, disabled_angle_features, + extra_display_attribs); + case ANGLE_METAL_NULL: + extra_display_attribs.push_back(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE); + extra_display_attribs.push_back( + EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE); + return GetPlatformANGLEDisplay( + native_display, EGL_PLATFORM_ANGLE_TYPE_METAL_ANGLE, + enabled_angle_features, disabled_angle_features, + extra_display_attribs); default: NOTREACHED(); return EGL_NO_DISPLAY; @@ -490,6 +508,9 @@ return ANGLEImplementation::kVulkan; case ANGLE_SWIFTSHADER: return ANGLEImplementation::kSwiftShader; + case ANGLE_METAL: + case ANGLE_METAL_NULL: + return ANGLEImplementation::kMetal; default: return ANGLEImplementation::kNone; } @@ -529,6 +550,10 @@ return "OpenGLEGL"; case ANGLE_OPENGLES_EGL: return "OpenGLESEGL"; + case ANGLE_METAL: + return "Metal"; + case ANGLE_METAL_NULL: + return "MetalNull"; default: NOTREACHED(); return "Err"; @@ -753,6 +778,7 @@ bool supports_angle_vulkan, bool supports_angle_swiftshader, bool supports_angle_egl, + bool supports_angle_metal, const base::CommandLine* command_line, std::vector<DisplayType>* init_displays) { // SwiftShader does not use the platform extensions @@ -851,6 +877,18 @@ } } + if (supports_angle_metal) { + if (use_angle_default) { + if (!supports_angle_opengl) { + AddInitDisplay(init_displays, ANGLE_METAL); + } + } else if (requested_renderer == kANGLEImplementationMetalName) { + AddInitDisplay(init_displays, ANGLE_METAL); + } else if (requested_renderer == kANGLEImplementationMetalNULLName) { + AddInitDisplay(init_displays, ANGLE_METAL_NULL); + } + } + // If no displays are available due to missing angle extensions or invalid // flags, request the default display. if (init_displays->empty()) { @@ -1185,6 +1223,7 @@ bool supports_angle_vulkan = false; bool supports_angle_swiftshader = false; bool supports_angle_egl = false; + bool supports_angle_metal = false; // Check for availability of ANGLE extensions. if (client_extensions && ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle")) { @@ -1200,11 +1239,13 @@ client_extensions, "EGL_ANGLE_platform_angle_device_type_swiftshader"); supports_angle_egl = ExtensionsContain( client_extensions, "EGL_ANGLE_platform_angle_device_type_egl_angle"); + supports_angle_metal = + ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_metal"); } bool supports_angle = supports_angle_d3d || supports_angle_opengl || supports_angle_null || supports_angle_vulkan || - supports_angle_swiftshader; + supports_angle_swiftshader || supports_angle_metal; if (client_extensions) { g_egl_angle_feature_control_supported = @@ -1216,7 +1257,7 @@ GetEGLInitDisplays(supports_angle_d3d, supports_angle_opengl, supports_angle_null, supports_angle_vulkan, supports_angle_swiftshader, supports_angle_egl, - command_line, &init_displays); + supports_angle_metal, command_line, &init_displays); std::vector<std::string> enabled_angle_features = GetStringVectorFromCommandLine(command_line,
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h index 6d14ed7c..34924467 100644 --- a/ui/gl/gl_surface_egl.h +++ b/ui/gl/gl_surface_egl.h
@@ -70,7 +70,9 @@ ANGLE_SWIFTSHADER = 14, ANGLE_OPENGL_EGL = 15, ANGLE_OPENGLES_EGL = 16, - DISPLAY_TYPE_MAX = 17, + ANGLE_METAL = 17, + ANGLE_METAL_NULL = 18, + DISPLAY_TYPE_MAX = 19, }; GL_EXPORT void GetEGLInitDisplays(bool supports_angle_d3d, @@ -79,6 +81,7 @@ bool supports_angle_vulkan, bool supports_angle_swiftshader, bool supports_angle_egl, + bool supports_angle_metal, const base::CommandLine* command_line, std::vector<DisplayType>* init_displays);
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc index 742c813..10ea27f 100644 --- a/ui/gl/gl_switches.cc +++ b/ui/gl/gl_switches.cc
@@ -29,12 +29,14 @@ const char kANGLEImplementationNullName[] = "null"; const char kANGLEImplementationVulkanName[] = "vulkan"; const char kANGLEImplementationSwiftShaderName[] = "swiftshader"; +const char kANGLEImplementationMetalName[] = "metal"; // Special switches for "NULL"/stub driver implementations. const char kANGLEImplementationD3D11NULLName[] = "d3d11-null"; const char kANGLEImplementationOpenGLNULLName[] = "gl-null"; const char kANGLEImplementationOpenGLESNULLName[] = "gles-null"; const char kANGLEImplementationVulkanNULLName[] = "vulkan-null"; +const char kANGLEImplementationMetalNULLName[] = "metal-null"; // The command decoder names that can be passed to --use-cmd-decoder. const char kCmdDecoderValidatingName[] = "validating";
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h index 6b21c9e..e2c9fafc 100644 --- a/ui/gl/gl_switches.h +++ b/ui/gl/gl_switches.h
@@ -34,11 +34,13 @@ GL_EXPORT extern const char kANGLEImplementationNullName[]; GL_EXPORT extern const char kANGLEImplementationVulkanName[]; GL_EXPORT extern const char kANGLEImplementationSwiftShaderName[]; +GL_EXPORT extern const char kANGLEImplementationMetalName[]; GL_EXPORT extern const char kANGLEImplementationD3D11NULLName[]; GL_EXPORT extern const char kANGLEImplementationOpenGLNULLName[]; GL_EXPORT extern const char kANGLEImplementationOpenGLESNULLName[]; GL_EXPORT extern const char kANGLEImplementationVulkanNULLName[]; +GL_EXPORT extern const char kANGLEImplementationMetalNULLName[]; GL_EXPORT extern const char kCmdDecoderValidatingName[]; GL_EXPORT extern const char kCmdDecoderPassthroughName[];
diff --git a/ui/gl/gl_version_info.cc b/ui/gl/gl_version_info.cc index 2d4368a..a8cf656 100644 --- a/ui/gl/gl_version_info.cc +++ b/ui/gl/gl_version_info.cc
@@ -49,6 +49,7 @@ is_angle_swiftshader = renderer_string.find("SwiftShader Device") != std::string::npos; is_angle_vulkan = renderer_string.find("Vulkan") != std::string::npos; + is_angle_metal = renderer_string.find("Metal") != std::string::npos; } is_swiftshader = base::StartsWith(renderer_str, "Google SwiftShader", @@ -192,6 +193,9 @@ DCHECK(base::StartsWith(rstr, "SwiftShader", base::CompareCase::SENSITIVE)); driver_vendor = "ANGLE (Google)"; } + if (is_angle_metal) { + DCHECK(base::StartsWith(rstr, "Metal", base::CompareCase::SENSITIVE)); + } if (base::StartsWith(rstr, "NVIDIA ", base::CompareCase::SENSITIVE)) driver_vendor = "ANGLE (NVIDIA)"; else if (base::StartsWith(rstr, "Radeon ", base::CompareCase::SENSITIVE))
diff --git a/ui/gl/gl_version_info.h b/ui/gl/gl_version_info.h index 843236b..63ceab9 100644 --- a/ui/gl/gl_version_info.h +++ b/ui/gl/gl_version_info.h
@@ -65,6 +65,7 @@ bool is_d3d = false; bool is_mesa = false; bool is_swiftshader = false; + bool is_angle_metal = false; bool is_angle_swiftshader = false; bool is_angle_vulkan = false; unsigned major_version = 0;
diff --git a/ui/gl/test/egl_initialization_displays_unittest.cc b/ui/gl/test/egl_initialization_displays_unittest.cc index 0ed3173..8007744 100644 --- a/ui/gl/test/egl_initialization_displays_unittest.cc +++ b/ui/gl/test/egl_initialization_displays_unittest.cc
@@ -17,8 +17,8 @@ // using --disable-d3d11 with the default --use-angle should never return // D3D11. command_line->AppendSwitch(switches::kDisableD3D11); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_FALSE(base::Contains(displays, gl::ANGLE_D3D11)); // Specifically requesting D3D11 should always return it if the extension is @@ -26,16 +26,16 @@ command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationD3D11Name); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::ANGLE_D3D11)); EXPECT_EQ(displays.size(), 1u); // Specifically requesting D3D11 should not return D3D11 if the extension is // not available displays.clear(); - GetEGLInitDisplays(false, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(false, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_FALSE(base::Contains(displays, gl::ANGLE_D3D11)); } @@ -49,8 +49,8 @@ command_line->AppendSwitchASCII(switches::kUseGL, gl::kGLImplementationSwiftShaderForWebGLName); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::SWIFT_SHADER)); EXPECT_EQ(displays.size(), 1u); @@ -58,8 +58,8 @@ command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationD3D11Name); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::SWIFT_SHADER)); EXPECT_EQ(displays.size(), 1u); } @@ -70,16 +70,16 @@ // Default without --use-angle flag std::vector<gl::DisplayType> default_no_flag_displays; - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &default_no_flag_displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &default_no_flag_displays); EXPECT_FALSE(default_no_flag_displays.empty()); // Default with --use-angle flag command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationDefaultName); std::vector<gl::DisplayType> default_with_flag_displays; - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &default_with_flag_displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &default_with_flag_displays); EXPECT_FALSE(default_with_flag_displays.empty()); // Make sure the same results are returned @@ -96,8 +96,8 @@ command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationOpenGLName); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::ANGLE_OPENGL)); EXPECT_EQ(displays.size(), 1u); @@ -105,8 +105,8 @@ command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationOpenGLESName); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::ANGLE_OPENGLES)); EXPECT_EQ(displays.size(), 1u); @@ -114,8 +114,8 @@ command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationNullName); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::ANGLE_NULL)); EXPECT_EQ(displays.size(), 1u); @@ -123,8 +123,8 @@ command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationVulkanName); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::ANGLE_VULKAN)); EXPECT_EQ(displays.size(), 1u); @@ -132,8 +132,8 @@ command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationSwiftShaderName); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::ANGLE_SWIFTSHADER)); EXPECT_EQ(displays.size(), 1u); @@ -141,8 +141,8 @@ command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationOpenGLEGLName); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::ANGLE_OPENGL_EGL)); EXPECT_EQ(displays.size(), 1u); @@ -150,10 +150,19 @@ command_line->AppendSwitchASCII(switches::kUseANGLE, gl::kANGLEImplementationOpenGLESEGLName); displays.clear(); - GetEGLInitDisplays(true, true, true, true, true, true, command_line.get(), - &displays); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::ANGLE_OPENGLES_EGL)); EXPECT_EQ(displays.size(), 1u); + + // Metal + command_line->AppendSwitchASCII(switches::kUseANGLE, + gl::kANGLEImplementationMetalName); + displays.clear(); + GetEGLInitDisplays(true, true, true, true, true, true, true, + command_line.get(), &displays); + EXPECT_TRUE(base::Contains(displays, gl::ANGLE_METAL)); + EXPECT_EQ(displays.size(), 1u); } TEST(EGLInitializationDisplaysTest, NoExtensions) { @@ -162,7 +171,7 @@ // With no angle platform extensions, only DEFAULT should be available std::vector<gl::DisplayType> displays; - GetEGLInitDisplays(false, false, false, false, false, false, + GetEGLInitDisplays(false, false, false, false, false, false, false, command_line.get(), &displays); EXPECT_TRUE(base::Contains(displays, gl::DEFAULT)); EXPECT_EQ(displays.size(), 1u);
diff --git a/ui/gl/yuv_to_rgb_converter.cc b/ui/gl/yuv_to_rgb_converter.cc index e76c941..d086804 100644 --- a/ui/gl/yuv_to_rgb_converter.cc +++ b/ui/gl/yuv_to_rgb_converter.cc
@@ -129,11 +129,12 @@ // On MacOS, the default texture target for native GpuMemoryBuffers is // GL_TEXTURE_RECTANGLE_ARB. This is due to CGL's requirements for creating - // a GL surface. However, when ANGLE is used on top of SwiftShader, it's - // necessary to use GL_TEXTURE_2D instead. + // a GL surface. However, when ANGLE is used on top of SwiftShader or Metal, + // it's necessary to use GL_TEXTURE_2D instead. // TODO(crbug.com/1056312): The proper behavior is to check the config // parameter set by the EGL_ANGLE_iosurface_client_buffer extension - bool is_rect = !gl_version_info.is_angle_swiftshader; + bool is_rect = + !gl_version_info.is_angle_swiftshader && !gl_version_info.is_angle_metal; source_texture_target_ = (is_rect ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D); const char* fragment_header = nullptr;
diff --git a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc index c4de6cc..3877bce8 100644 --- a/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc +++ b/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc
@@ -416,9 +416,8 @@ InitDrmStatesAndControllers(crtc_states); ui::HardwareDisplayController* controller = window_->GetController(); - controller->AddCrtc( - std::unique_ptr<ui::CrtcController>(new ui::CrtcController( - drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1))); + controller->AddCrtc(std::make_unique<ui::CrtcController>( + drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1)); ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode)); @@ -462,9 +461,8 @@ InitDrmStatesAndControllers(crtc_states); ui::HardwareDisplayController* controller = window_->GetController(); - controller->AddCrtc( - std::unique_ptr<ui::CrtcController>(new ui::CrtcController( - drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1))); + controller->AddCrtc(std::make_unique<ui::CrtcController>( + drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1)); ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode)); @@ -505,9 +503,8 @@ InitDrmStatesAndControllers(crtc_states); ui::HardwareDisplayController* controller = window_->GetController(); - controller->AddCrtc( - std::unique_ptr<ui::CrtcController>(new ui::CrtcController( - drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1))); + controller->AddCrtc(std::make_unique<ui::CrtcController>( + drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1)); ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode)); @@ -548,9 +545,8 @@ InitDrmStatesAndControllers(crtc_states); ui::HardwareDisplayController* controller = window_->GetController(); - controller->AddCrtc( - std::unique_ptr<ui::CrtcController>(new ui::CrtcController( - drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1))); + controller->AddCrtc(std::make_unique<ui::CrtcController>( + drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1)); ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode)); @@ -585,9 +581,8 @@ InitDrmStatesAndControllers(crtc_states); ui::HardwareDisplayController* controller = window_->GetController(); - controller->AddCrtc( - std::unique_ptr<ui::CrtcController>(new ui::CrtcController( - drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1))); + controller->AddCrtc(std::make_unique<ui::CrtcController>( + drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1)); ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode)); @@ -621,9 +616,8 @@ InitDrmStatesAndControllers(crtc_states); ui::HardwareDisplayController* controller = window_->GetController(); - controller->AddCrtc( - std::unique_ptr<ui::CrtcController>(new ui::CrtcController( - drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1))); + controller->AddCrtc(std::make_unique<ui::CrtcController>( + drm_.get(), kCrtcIdBase + 1, kConnectorIdBase + 1)); ui::DrmOverlayPlane plane1(CreateBuffer(), nullptr); EXPECT_TRUE(controller->Modeset(plane1, kDefaultMode));
diff --git a/ui/ozone/platform/drm/gpu/drm_window_unittest.cc b/ui/ozone/platform/drm/gpu/drm_window_unittest.cc index 824992a..ffb8ffb 100644 --- a/ui/ozone/platform/drm/gpu/drm_window_unittest.cc +++ b/ui/ozone/platform/drm/gpu/drm_window_unittest.cc
@@ -34,8 +34,8 @@ namespace { // Mode of size 6x4. -const drmModeModeInfo kDefaultMode = - {0, 6, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, {'\0'}}; +const drmModeModeInfo kDefaultMode = {0, 6, 0, 0, 0, 0, 4, 0, + 0, 0, 0, 0, 0, 0, {'\0'}}; const gfx::AcceleratedWidget kDefaultWidgetHandle = 1; const uint32_t kDefaultCrtc = 1; @@ -68,7 +68,7 @@ class DrmWindowTest : public testing::Test { public: - DrmWindowTest() {} + DrmWindowTest() = default; void SetUp() override; void TearDown() override;
diff --git a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc index 577cfa7..2cbc6a6 100644 --- a/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc +++ b/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -44,8 +44,8 @@ class ScreenManagerTest : public testing::Test { public: - ScreenManagerTest() {} - ~ScreenManagerTest() override {} + ScreenManagerTest() = default; + ~ScreenManagerTest() override = default; gfx::Rect GetPrimaryBounds() const { return gfx::Rect(0, 0, kDefaultMode.hdisplay, kDefaultMode.vdisplay);
diff --git a/ui/platform_window/handlers/BUILD.gn b/ui/platform_window/handlers/BUILD.gn index d026dded..48fe42ba 100644 --- a/ui/platform_window/handlers/BUILD.gn +++ b/ui/platform_window/handlers/BUILD.gn
@@ -14,10 +14,9 @@ "wm_move_loop_handler.h", "wm_move_resize_handler.cc", "wm_move_resize_handler.h", - "wm_platform_export.h", ] - defines = [ "PLATFORM_WINDOW_HANDLER_IMPLEMENTATION" ] + defines = [ "IS_HANDLERS_IMPL" ] deps = [ "//ui/base",
diff --git a/ui/platform_window/handlers/wm_drag_handler.h b/ui/platform_window/handlers/wm_drag_handler.h index ff667a02..67e9eeb 100644 --- a/ui/platform_window/handlers/wm_drag_handler.h +++ b/ui/platform_window/handlers/wm_drag_handler.h
@@ -5,17 +5,19 @@ #ifndef UI_PLATFORM_WINDOW_HANDLERS_WM_DRAG_HANDLER_H_ #define UI_PLATFORM_WINDOW_HANDLERS_WM_DRAG_HANDLER_H_ -#include "base/bind.h" +#include "base/component_export.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/handlers/wm_platform_export.h" + +namespace gfx { +class Point; +} namespace ui { class PlatformWindow; class OSExchangeData; -class WM_PLATFORM_EXPORT WmDragHandler { +class COMPONENT_EXPORT(HANDLERS) WmDragHandler { public: // During the drag operation, the handler may send updates class Delegate { @@ -57,10 +59,11 @@ virtual void CancelDrag() = 0; }; -WM_PLATFORM_EXPORT void SetWmDragHandler(PlatformWindow* platform_window, - WmDragHandler* drag_handler); -WM_PLATFORM_EXPORT WmDragHandler* GetWmDragHandler( - const PlatformWindow& platform_window); +COMPONENT_EXPORT(HANDLERS) +void SetWmDragHandler(PlatformWindow* platform_window, + WmDragHandler* drag_handler); +COMPONENT_EXPORT(HANDLERS) +WmDragHandler* GetWmDragHandler(const PlatformWindow& platform_window); } // namespace ui
diff --git a/ui/platform_window/handlers/wm_drop_handler.h b/ui/platform_window/handlers/wm_drop_handler.h index 9a00a68..bd8fd35 100644 --- a/ui/platform_window/handlers/wm_drop_handler.h +++ b/ui/platform_window/handlers/wm_drop_handler.h
@@ -7,8 +7,7 @@ #include <memory> -#include "ui/gfx/native_widget_types.h" -#include "ui/platform_window/handlers/wm_platform_export.h" +#include "base/component_export.h" namespace gfx { class PointF; @@ -18,7 +17,7 @@ class PlatformWindow; class OSExchangeData; -class WM_PLATFORM_EXPORT WmDropHandler { +class COMPONENT_EXPORT(HANDLERS) WmDropHandler { public: // Notifies that drag has entered the window. // |point| is in the coordinate space of the PlatformWindow. @@ -43,7 +42,7 @@ // of the drop is the location of the latest DragEnter/DragMotion. If // OSExchangeData is provided on OnDragEnter, the |data| should be same as it. // |modifiers| contains bitmask of ui::EventFlags that accompany the event. - virtual void OnDragDrop(std::unique_ptr<ui::OSExchangeData> data, + virtual void OnDragDrop(std::unique_ptr<OSExchangeData> data, int modifiers) = 0; // Notifies that dragging is left. Must be called before @@ -51,13 +50,14 @@ virtual void OnDragLeave() = 0; protected: - virtual ~WmDropHandler() {} + virtual ~WmDropHandler() = default; }; -WM_PLATFORM_EXPORT void SetWmDropHandler(PlatformWindow* platform_window, - WmDropHandler* drop_handler); -WM_PLATFORM_EXPORT WmDropHandler* GetWmDropHandler( - const PlatformWindow& platform_window); +COMPONENT_EXPORT(HANDLERS) +void SetWmDropHandler(PlatformWindow* platform_window, + WmDropHandler* drop_handler); +COMPONENT_EXPORT(HANDLERS) +WmDropHandler* GetWmDropHandler(const PlatformWindow& platform_window); } // namespace ui
diff --git a/ui/platform_window/handlers/wm_move_loop_handler.h b/ui/platform_window/handlers/wm_move_loop_handler.h index 49b2d2f..cbe0c21 100644 --- a/ui/platform_window/handlers/wm_move_loop_handler.h +++ b/ui/platform_window/handlers/wm_move_loop_handler.h
@@ -5,7 +5,7 @@ #ifndef UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_LOOP_HANDLER_H_ #define UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_LOOP_HANDLER_H_ -#include "ui/platform_window/handlers/wm_platform_export.h" +#include "base/component_export.h" namespace gfx { class Vector2d; @@ -16,7 +16,7 @@ class PlatformWindow; // Handler that starts interactive move loop for the PlatformWindow. -class WM_PLATFORM_EXPORT WmMoveLoopHandler { +class COMPONENT_EXPORT(HANDLERS) WmMoveLoopHandler { public: // Starts a move loop for tab drag controller. Returns true on success or // false on fail/cancel. @@ -29,10 +29,11 @@ virtual ~WmMoveLoopHandler() {} }; -WM_PLATFORM_EXPORT void SetWmMoveLoopHandler(PlatformWindow* platform_window, - WmMoveLoopHandler* drag_handler); -WM_PLATFORM_EXPORT WmMoveLoopHandler* GetWmMoveLoopHandler( - const PlatformWindow& platform_window); +COMPONENT_EXPORT(HANDLERS) +void SetWmMoveLoopHandler(PlatformWindow* platform_window, + WmMoveLoopHandler* drag_handler); +COMPONENT_EXPORT(HANDLERS) +WmMoveLoopHandler* GetWmMoveLoopHandler(const PlatformWindow& platform_window); } // namespace ui
diff --git a/ui/platform_window/handlers/wm_move_resize_handler.h b/ui/platform_window/handlers/wm_move_resize_handler.h index dd40e58..436fecc 100644 --- a/ui/platform_window/handlers/wm_move_resize_handler.h +++ b/ui/platform_window/handlers/wm_move_resize_handler.h
@@ -5,7 +5,7 @@ #ifndef UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_RESIZE_HANDLER_H_ #define UI_PLATFORM_WINDOW_HANDLERS_WM_MOVE_RESIZE_HANDLER_H_ -#include "ui/platform_window/handlers/wm_platform_export.h" +#include "base/component_export.h" namespace gfx { class Point; @@ -15,7 +15,7 @@ class PlatformWindow; -class WmMoveResizeHandler { +class COMPONENT_EXPORT(HANDLERS) WmMoveResizeHandler { public: // A system window manager starts interactive drag or resize of a window based // on the |hittest| value. The |hittest| value identifies in which direction @@ -52,10 +52,11 @@ virtual ~WmMoveResizeHandler() {} }; -WM_PLATFORM_EXPORT void SetWmMoveResizeHandler( - PlatformWindow* platform_window, - WmMoveResizeHandler* move_resize_handler); -WM_PLATFORM_EXPORT WmMoveResizeHandler* GetWmMoveResizeHandler( +COMPONENT_EXPORT(HANDLERS) +void SetWmMoveResizeHandler(PlatformWindow* platform_window, + WmMoveResizeHandler* move_resize_handler); +COMPONENT_EXPORT(HANDLERS) +WmMoveResizeHandler* GetWmMoveResizeHandler( const PlatformWindow& platform_window); } // namespace ui
diff --git a/ui/platform_window/handlers/wm_platform_export.h b/ui/platform_window/handlers/wm_platform_export.h deleted file mode 100644 index 26b560d..0000000 --- a/ui/platform_window/handlers/wm_platform_export.h +++ /dev/null
@@ -1,32 +0,0 @@ -// Copyright 2018 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef 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. - -#if defined(COMPONENT_BUILD) -#if defined(WIN32) - -#if defined(PLATFORM_WINDOW_HANDLER_IMPLEMENTATION) -#define WM_PLATFORM_EXPORT __declspec(dllexport) -#else -#define WM_PLATFORM_EXPORT __declspec(dllimport) -#endif // defined(WM_PLATFORM_IMPLEMENTATION) - -#else // defined(WIN32) -#if defined(PLATFORM_WINDOW_HANDLER_IMPLEMENTATION) -#define WM_PLATFORM_EXPORT __attribute__((visibility("default"))) -#else -#define WM_PLATFORM_EXPORT -#endif -#endif - -#else // defined(COMPONENT_BUILD) -#define WM_PLATFORM_EXPORT -#endif - -#endif // UI_PLATFORM_WINDOW_HANDLERS_WM_PLATFORM_EXPORT_H_
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc index b8d7c93..ce0c5a83 100644 --- a/ui/views/controls/menu/menu_controller.cc +++ b/ui/views/controls/menu/menu_controller.cc
@@ -1381,7 +1381,7 @@ StartShowTimer(); // Notify an accessibility focus event on all menu items except for the root. - if (menu_item && + if (menu_item && pending_item_changed && (MenuDepth(menu_item) != 1 || menu_item->GetType() != MenuItemView::Type::kSubMenu || (menu_item->GetType() == MenuItemView::Type::kActionableSubMenu && @@ -3117,16 +3117,19 @@ SetInitialHotTrackedView(to_select, direction); } -void MenuController::SetHotTrackedButton(Button* hot_button) { +void MenuController::SetHotTrackedButton(Button* new_hot_button) { + if (hot_button_ == new_hot_button) + return; + // If we're providing a new hot-tracked button, first remove the existing one. - if (hot_button_ && hot_button_ != hot_button) { + if (hot_button_) { hot_button_->SetHotTracked(false); hot_button_->GetViewAccessibility().EndPopupFocusOverride(); } // Then set the new one. - hot_button_ = hot_button; - if (hot_button_ && !hot_button_->IsHotTracked()) { + hot_button_ = new_hot_button; + if (hot_button_) { hot_button_->GetViewAccessibility().SetPopupFocusOverride(); hot_button_->SetHotTracked(true); hot_button_->NotifyAccessibilityEvent(ax::mojom::Event::kSelection, true);
diff --git a/ui/views/controls/menu/menu_controller.h b/ui/views/controls/menu/menu_controller.h index 18a3100..d362f68d 100644 --- a/ui/views/controls/menu/menu_controller.h +++ b/ui/views/controls/menu/menu_controller.h
@@ -612,7 +612,7 @@ SelectionIncrementDirectionType direction); // Updates the current |hot_button_| and its hot tracked state. - void SetHotTrackedButton(Button* hot_button); + void SetHotTrackedButton(Button* new_hot_button); // Returns whether typing a new character will continue the existing prefix // selection. If this returns false, typing a new character will start a new
diff --git a/weblayer/shell/android/shell_apk/res/layout/shell_browser_controls.xml b/weblayer/shell/android/shell_apk/res/layout/shell_browser_controls.xml index 1b457f9..e0d661e 100644 --- a/weblayer/shell/android/shell_apk/res/layout/shell_browser_controls.xml +++ b/weblayer/shell/android/shell_apk/res/layout/shell_browser_controls.xml
@@ -18,7 +18,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentStart="true" - android:layout_toStartOf="@+id/menu_button" + android:layout_toStartOf="@+id/app_menu_button" android:paddingStart="5dp"> <EditText