diff --git a/AUTHORS b/AUTHORS index 30c9988..376a9b3 100644 --- a/AUTHORS +++ b/AUTHORS
@@ -637,6 +637,7 @@ Matthew Demarest <demarem@amazon.com> Matthew Robertson <matthewrobertson03@gmail.com> Matthew Turk <matthewturk@gmail.com> +Matthew Webb <mwebbmwebb@gmail.com> Matthew Willis <appamatto@gmail.com> Matthias Reitinger <reimarvin@gmail.com> Matthieu Rigolot <matthieu.rigolot@gmail.com>
diff --git a/DEPS b/DEPS index d56c2f3..0a6b4f0 100644 --- a/DEPS +++ b/DEPS
@@ -175,11 +175,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '4045cd82e75548918692b72f97eb89b125478a50', + 'skia_revision': '6a5187a8895807f2412f6a4a1a209a859d4e93fb', # 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': '703b9d4881faf3dd412fafbe339a27fcccaacdcc', + 'v8_revision': '3d1d9352dd510535d6a0feff640d8d2147658823', # 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. @@ -302,7 +302,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. - 'dawn_revision': '9d2de1d6d45f4dfd006a8d6d70ffdf5fb44aed84', + 'dawn_revision': '7119a0278da3ae1044a0dcaaf979a2b5294a10ee', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -525,7 +525,7 @@ }, 'src/ios/third_party/material_components_ios/src': { - 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + 'c7ff69c0bd9b7d62491066f56b9c3d953a4a7f4b', + 'url': Var('chromium_git') + '/external/github.com/material-components/material-components-ios.git' + '@' + '4454d0be942d588fcea5a390fb78711c07513a6c', 'condition': 'checkout_ios', }, @@ -856,7 +856,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'ca6b5b7a178116b8f514462b7b8c27bdd7cc4e4c', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'eb17dbb23599aadf015f4b5cee7d592a0910e6eb', 'condition': 'checkout_linux', }, @@ -1218,7 +1218,7 @@ Var('chromium_git') + '/external/github.com/cisco/openh264' + '@' + '6f26bce0b1c4e8ce0e13332f7c0083788def5fdf', 'src/third_party/openscreen/src': - Var('chromium_git') + '/openscreen' + '@' + '94b61ee5c25c872920f45e5581442e4bf1a5a7ea', + Var('chromium_git') + '/openscreen' + '@' + 'e998a6b46dddfecde30aa25642bad41a7e5d9780', 'src/third_party/openxr/src': { 'url': Var('chromium_git') + '/external/github.com/KhronosGroup/OpenXR-SDK' + '@' + '9e97b73e7dd2bfc07745489d728f6a36665c648f', @@ -1465,7 +1465,7 @@ }, 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'dfae553e3a6928c9cf71121650bd4b605c359587', + Var('webrtc_git') + '/src.git' + '@' + 'f7065f4414856c15038f8bdbe4ef84e54056f9d6', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1540,7 +1540,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@08494419674464d45d9d0f6d8ebfddc15286d992', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@6e3984a4c68ea883e183a3e8118f14b6a315ef2f', 'condition': 'checkout_src_internal', },
diff --git a/base/check_unittest.cc b/base/check_unittest.cc index 8f7095f..6cdc372b 100644 --- a/base/check_unittest.cc +++ b/base/check_unittest.cc
@@ -7,6 +7,7 @@ #include "base/logging.h" #include "base/strings/string_piece.h" #include "base/test/gtest_util.h" +#include "base/test/scoped_feature_list.h" #include "build/build_config.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -181,14 +182,15 @@ #if defined(DCHECK_IS_CONFIGURABLE) class ScopedDcheckSeverity { public: - ScopedDcheckSeverity(LogSeverity new_severity) : old_severity_(LOG_DCHECK) { - LOG_DCHECK = new_severity; + ScopedDcheckSeverity(logging::LogSeverity new_severity) + : old_severity_(logging::LOG_DCHECK) { + logging::LOG_DCHECK = new_severity; } - ~ScopedDcheckSeverity() { LOG_DCHECK = old_severity_; } + ~ScopedDcheckSeverity() { logging::LOG_DCHECK = old_severity_; } private: - LogSeverity old_severity_; + logging::LogSeverity old_severity_; }; #endif // defined(DCHECK_IS_CONFIGURABLE) @@ -203,7 +205,7 @@ // DCHECKs are enabled, and LOG_DCHECK is mutable, but defaults to non-fatal. // Set it to LOG_FATAL to get the expected behavior from the rest of this // test. - ScopedDcheckSeverity dcheck_severity(LOG_FATAL); + ScopedDcheckSeverity dcheck_severity(logging::LOG_FATAL); #endif // defined(DCHECK_IS_CONFIGURABLE) #if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON) @@ -305,16 +307,16 @@ // Verify that DCHECKs default to non-fatal in configurable-DCHECK builds. // Note that we require only that DCHECK is non-fatal by default, rather // than requiring that it be exactly INFO, ERROR, etc level. - EXPECT_LT(LOG_DCHECK, LOG_FATAL); + EXPECT_LT(logging::LOG_DCHECK, logging::LOG_FATAL); DCHECK(false); // Verify that DCHECK* aren't hard-wired to crash on failure. - LOG_DCHECK = LOG_INFO; + logging::LOG_DCHECK = logging::LOG_INFO; DCHECK(false); DCHECK_EQ(1, 2); // Verify that DCHECK does crash if LOG_DCHECK is set to LOG_FATAL. - LOG_DCHECK = LOG_FATAL; + logging::LOG_DCHECK = logging::LOG_FATAL; EXPECT_CHECK("Check failed: false. ", DCHECK(false)); EXPECT_CHECK("Check failed: 1 == 2 (1 vs. 2)", DCHECK_EQ(1, 2)); } @@ -327,20 +329,20 @@ { base::test::ScopedFeatureList feature_list; feature_list.InitFromCommandLine("DcheckIsFatal", ""); - EXPECT_EQ(LOG_DCHECK, LOG_FATAL); + EXPECT_EQ(logging::LOG_DCHECK, logging::LOG_FATAL); } { base::test::ScopedFeatureList feature_list; feature_list.InitFromCommandLine("", "DcheckIsFatal"); - EXPECT_LT(LOG_DCHECK, LOG_FATAL); + EXPECT_LT(logging::LOG_DCHECK, logging::LOG_FATAL); } // The default case is last, so we leave LOG_DCHECK in the default state. { base::test::ScopedFeatureList feature_list; feature_list.InitFromCommandLine("", ""); - EXPECT_LT(LOG_DCHECK, LOG_FATAL); + EXPECT_LT(logging::LOG_DCHECK, logging::LOG_FATAL); } } #endif // defined(DCHECK_IS_CONFIGURABLE)
diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index f4af27f..2dd2937 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni
@@ -875,12 +875,12 @@ # own dependencies. # # Variables + # sources: List of resource files for this target. # deps: Specifies the dependencies of this target. Any Android resources # listed in deps will be included by libraries/apks that depend on this # target. # alternative_android_sdk_dep: Optional. Alternative Android system # android java target to use. - # resource_dirs: List of directories containing resources for this target. # android_manifest: AndroidManifest.xml for this target (optional). Will be # merged into apks that directly or indirectly depend on this target. # android_manifest_dep: Target that generates AndroidManifest (if applicable) @@ -918,7 +918,10 @@ not_needed(invoker, [ "v14_skip" ]) } - _pass_resource_files = defined(invoker.sources) + assert(!defined(invoker.resource_dirs) || defined(invoker.sources), + "resource_dirs in android_resources is deprecated. Please use " + + "sources=[] and list resource files instead. Details: " + + "https://crbug.com/1026378") _res_sources_path = "$target_gen_dir/${invoker.target_name}.res.sources" _resources_zip = "$target_out_dir/$target_name.resources.zip" @@ -941,19 +944,11 @@ _deps += [ "//third_party/android_sdk:android_sdk_java" ] } - if (_pass_resource_files) { - _resource_files = invoker.sources - } else { - _sources_build_rel = [] - - if (invoker.resource_dirs != []) { - _sources_build_rel += - exec_script("//build/android/gyp/find.py", - rebase_path(invoker.resource_dirs, root_build_dir), - "list lines") - } - _resource_files = rebase_path(_sources_build_rel, ".", root_build_dir) + _resource_files = [] + if (defined(invoker.sources)) { + _resource_files += invoker.sources } + _rebased_resource_files = rebase_path(_resource_files, root_build_dir) write_file(_res_sources_path, _rebased_resource_files)
diff --git a/build/config/fuchsia/build_cmx_from_fragment.py b/build/config/fuchsia/build_cmx_from_fragment.py new file mode 100644 index 0000000..ac7e349 --- /dev/null +++ b/build/config/fuchsia/build_cmx_from_fragment.py
@@ -0,0 +1,49 @@ +# 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. +"""Creates a complete CMX (v1) component manifest, from a program name and + manifest fragment file.""" + +import argparse +import json +import sys + + +def BuildCmxFromFragment(output_file, fragment_file, program_binary): + """Reads a CMX fragment specifying e.g. features & sandbox, and a program + binary's filename, and writes out the full CMX. + + output_file: Build-relative filename at which to write the full CMX. + fragment_file: Build-relative filename of the CMX fragment to read from. + program_binary: Package-relative filename of the program binary. + """ + + with open(output_file, 'w') as component_manifest_file: + component_manifest = json.load(open(fragment_file, 'r')) + component_manifest.update({ + 'program': { + 'binary': program_binary + }, + }) + json.dump(component_manifest, component_manifest_file) + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument( + '--cmx-fragment', + required=True, + help='Path to the CMX fragment to read from') + parser.add_argument( + '--cmx', required=True, help='Path to write the complete CMX file to') + parser.add_argument( + '--program', + required=True, + help='Package-relative path to the program binary') + args = parser.parse_args() + + return BuildCmxFromFragment(args.cmx, args.cmx_fragment, args.program) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/build/config/fuchsia/elfinfo.py b/build/config/fuchsia/elfinfo.py deleted file mode 100644 index ec3a57a..0000000 --- a/build/config/fuchsia/elfinfo.py +++ /dev/null
@@ -1,423 +0,0 @@ -# Copyright 2019 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. -"""Parses ELF information without relying external tools. - -This file was originally copied and adapted from: -https://fuchsia.googlesource.com/fuchsia/+/827f9fe/build/images/elfinfo.py -""" - -from contextlib import contextmanager -from collections import namedtuple -import mmap -import os -import struct -import uuid - -# Standard ELF constants. -ELFMAG = '\x7fELF' -EI_CLASS = 4 -ELFCLASS32 = 1 -ELFCLASS64 = 2 -EI_DATA = 5 -ELFDATA2LSB = 1 -ELFDATA2MSB = 2 -EM_386 = 3 -EM_ARM = 40 -EM_X86_64 = 62 -EM_AARCH64 = 183 -PT_LOAD = 1 -PT_DYNAMIC = 2 -PT_INTERP = 3 -PT_NOTE = 4 -DT_NEEDED = 1 -DT_STRTAB = 5 -DT_SONAME = 14 -NT_GNU_BUILD_ID = 3 -SHT_SYMTAB = 2 - - -class elf_note(namedtuple('elf_note', [ - 'name', - 'type', - 'desc', -])): - - # An ELF note is identified by (name_string, type_integer). - def ident(self): - return (self.name, self.type) - - def is_build_id(self): - return self.ident() == ('GNU\0', NT_GNU_BUILD_ID) - - def build_id_hex(self): - if self.is_build_id(): - return ''.join(('%02x' % ord(byte)) for byte in self.desc) - return None - - def __repr__(self): - return ('elf_note(%r, %#x, <%d bytes>)' % (self.name, self.type, - len(self.desc))) - - -def gen_elf(): - # { 'Struct1': (ELFCLASS32 fields, ELFCLASS64 fields), - # 'Struct2': fields_same_for_both, ... } - elf_types = { - 'Ehdr': ([ - ('e_ident', '16s'), - ('e_type', 'H'), - ('e_machine', 'H'), - ('e_version', 'I'), - ('e_entry', 'I'), - ('e_phoff', 'I'), - ('e_shoff', 'I'), - ('e_flags', 'I'), - ('e_ehsize', 'H'), - ('e_phentsize', 'H'), - ('e_phnum', 'H'), - ('e_shentsize', 'H'), - ('e_shnum', 'H'), - ('e_shstrndx', 'H'), - ], [ - ('e_ident', '16s'), - ('e_type', 'H'), - ('e_machine', 'H'), - ('e_version', 'I'), - ('e_entry', 'Q'), - ('e_phoff', 'Q'), - ('e_shoff', 'Q'), - ('e_flags', 'I'), - ('e_ehsize', 'H'), - ('e_phentsize', 'H'), - ('e_phnum', 'H'), - ('e_shentsize', 'H'), - ('e_shnum', 'H'), - ('e_shstrndx', 'H'), - ]), - 'Phdr': ([ - ('p_type', 'I'), - ('p_offset', 'I'), - ('p_vaddr', 'I'), - ('p_paddr', 'I'), - ('p_filesz', 'I'), - ('p_memsz', 'I'), - ('p_flags', 'I'), - ('p_align', 'I'), - ], [ - ('p_type', 'I'), - ('p_flags', 'I'), - ('p_offset', 'Q'), - ('p_vaddr', 'Q'), - ('p_paddr', 'Q'), - ('p_filesz', 'Q'), - ('p_memsz', 'Q'), - ('p_align', 'Q'), - ]), - 'Shdr': ([ - ('sh_name', 'L'), - ('sh_type', 'L'), - ('sh_flags', 'L'), - ('sh_addr', 'L'), - ('sh_offset', 'L'), - ('sh_size', 'L'), - ('sh_link', 'L'), - ('sh_info', 'L'), - ('sh_addralign', 'L'), - ('sh_entsize', 'L'), - ], [ - ('sh_name', 'L'), - ('sh_type', 'L'), - ('sh_flags', 'Q'), - ('sh_addr', 'Q'), - ('sh_offset', 'Q'), - ('sh_size', 'Q'), - ('sh_link', 'L'), - ('sh_info', 'L'), - ('sh_addralign', 'Q'), - ('sh_entsize', 'Q'), - ]), - 'Dyn': ([ - ('d_tag', 'i'), - ('d_val', 'I'), - ], [ - ('d_tag', 'q'), - ('d_val', 'Q'), - ]), - 'Nhdr': [ - ('n_namesz', 'I'), - ('n_descsz', 'I'), - ('n_type', 'I'), - ], - 'dwarf2_line_header': [ - ('unit_length', 'L'), - ('version', 'H'), - ('header_length', 'L'), - ('minimum_instruction_length', 'B'), - ('default_is_stmt', 'B'), - ('line_base', 'b'), - ('line_range', 'B'), - ('opcode_base', 'B'), - ], - 'dwarf4_line_header': [ - ('unit_length', 'L'), - ('version', 'H'), - ('header_length', 'L'), - ('minimum_instruction_length', 'B'), - ('maximum_operations_per_instruction', 'B'), - ('default_is_stmt', 'B'), - ('line_base', 'b'), - ('line_range', 'b'), - ('opcode_base', 'B'), - ], - } - - # There is an accessor for each struct, e.g. Ehdr. - # Ehdr.read is a function like Struct.unpack_from. - # Ehdr.size is the size of the struct. - elf_accessor = namedtuple('elf_accessor', ['size', 'read', 'write', 'pack']) - - # All the accessors for a format (class, byte-order) form one elf, - # e.g. use elf.Ehdr and elf.Phdr. - elf = namedtuple('elf', elf_types.keys()) - - def gen_accessors(is64, struct_byte_order): - - def make_accessor(type, decoder): - return elf_accessor( - size=decoder.size, - read=lambda buffer, offset=0: type._make( - decoder.unpack_from(buffer, offset)), - write=lambda buffer, offset, x: decoder.pack_into( - buffer, offset, *x), - pack=lambda x: decoder.pack(*x)) - - for name, fields in elf_types.iteritems(): - if isinstance(fields, tuple): - fields = fields[1 if is64 else 0] - type = namedtuple(name, [field_name for field_name, fmt in fields]) - decoder = struct.Struct(struct_byte_order + ''.join( - fmt for field_name, fmt in fields)) - yield make_accessor(type, decoder) - - for elfclass, is64 in [(ELFCLASS32, False), (ELFCLASS64, True)]: - for elf_bo, struct_bo in [(ELFDATA2LSB, '<'), (ELFDATA2MSB, '>')]: - yield ((chr(elfclass), chr(elf_bo)), elf(*gen_accessors(is64, struct_bo))) - - -# e.g. ELF[file[EI_CLASS], file[EI_DATA]].Ehdr.read(file).e_phnum -ELF = dict(gen_elf()) - - -def get_elf_accessor(file): - # If it looks like an ELF file, whip out the decoder ring. - if file[:len(ELFMAG)] == ELFMAG: - return ELF[file[EI_CLASS], file[EI_DATA]] - return None - - -def gen_phdrs(file, elf, ehdr): - for pos in xrange(0, ehdr.e_phnum * elf.Phdr.size, elf.Phdr.size): - yield elf.Phdr.read(file, ehdr.e_phoff + pos) - - -def gen_shdrs(file, elf, ehdr): - for pos in xrange(0, ehdr.e_shnum * elf.Shdr.size, elf.Shdr.size): - yield elf.Shdr.read(file, ehdr.e_shoff + pos) - - -cpu = namedtuple( - 'cpu', - [ - 'e_machine', # ELF e_machine int - 'llvm', # LLVM triple CPU component - 'gn', # GN target_cpu - ]) - -ELF_MACHINE_TO_CPU = { - elf: cpu(elf, llvm, gn) for elf, llvm, gn in [ - (EM_386, 'i386', 'x86'), - (EM_ARM, 'arm', 'arm'), - (EM_X86_64, 'x86_64', 'x64'), - (EM_AARCH64, 'aarch64', 'arm64'), - ] -} - - -@contextmanager -def mmapper(filename): - """A context manager that yields (fd, file_contents) given a file name. -This ensures that the mmap and file objects are closed at the end of the -'with' statement.""" - fileobj = open(filename, 'rb') - fd = fileobj.fileno() - if os.fstat(fd).st_size == 0: - # mmap can't handle empty files. - try: - yield fd, '' - finally: - fileobj.close() - else: - mmapobj = mmap.mmap(fd, 0, access=mmap.ACCESS_READ) - try: - yield fd, mmapobj - finally: - mmapobj.close() - fileobj.close() - - -elf_info = namedtuple( - 'elf_info', - [ - 'filename', - 'cpu', # cpu tuple - 'notes', # list of (ident, desc): selected notes - 'build_id', # string: lowercase hex - 'stripped', # bool: Has no symbols or .debug_* sections - 'interp', # string or None: PT_INTERP (without \0) - 'soname', # string or None: DT_SONAME - 'needed', # list of strings: DT_NEEDED - ]) - - -def get_elf_info(filename, match_notes=False): - file = None - elf = None - ehdr = None - phdrs = None - - # Yields an elf_note for each note in any PT_NOTE segment. - def gen_notes(): - - def round_up_to(size): - return ((size + 3) / 4) * 4 - - for phdr in phdrs: - if phdr.p_type == PT_NOTE: - pos = phdr.p_offset - while pos < phdr.p_offset + phdr.p_filesz: - nhdr = elf.Nhdr.read(file, pos) - pos += elf.Nhdr.size - name = file[pos:pos + nhdr.n_namesz] - pos += round_up_to(nhdr.n_namesz) - desc = file[pos:pos + nhdr.n_descsz] - pos += round_up_to(nhdr.n_descsz) - yield elf_note(name, nhdr.n_type, desc) - - def gen_sections(): - shdrs = list(gen_shdrs(file, elf, ehdr)) - if not shdrs: - return - strtab_shdr = shdrs[ehdr.e_shstrndx] - for shdr, i in zip(shdrs, xrange(len(shdrs))): - if i == 0: - continue - assert shdr.sh_name < strtab_shdr.sh_size, ( - "%s: invalid sh_name" % filename) - yield (shdr, extract_C_string(strtab_shdr.sh_offset + shdr.sh_name)) - - # Generates '\0'-terminated strings starting at the given offset, - # until an empty string. - def gen_strings(start): - while True: - end = file.find('\0', start) - assert end >= start, ( - "%s: Unterminated string at %#x" % (filename, start)) - if start == end: - break - yield file[start:end] - start = end + 1 - - def extract_C_string(start): - for string in gen_strings(start): - return string - return '' - - # Returns a string of hex digits (or None). - def get_build_id(): - build_id = None - for note in gen_notes(): - # Note that the last build_id note needs to be used due to TO-442. - possible_build_id = note.build_id_hex() - if possible_build_id: - build_id = possible_build_id - return build_id - - # Returns a list of elf_note objects. - def get_matching_notes(): - if isinstance(match_notes, bool): - if match_notes: - return list(gen_notes()) - else: - return [] - # If not a bool, it's an iterable of ident pairs. - return [note for note in gen_notes() if note.ident() in match_notes] - - # Returns a string (without trailing '\0'), or None. - def get_interp(): - # PT_INTERP points directly to a string in the file. - for interp in (phdr for phdr in phdrs if phdr.p_type == PT_INTERP): - interp = file[interp.p_offset:interp.p_offset + interp.p_filesz] - if interp[-1:] == '\0': - interp = interp[:-1] - return interp - return None - - # Returns a set of strings. - def get_soname_and_needed(): - # Each DT_NEEDED or DT_SONAME points to a string in the .dynstr table. - def GenDTStrings(tag): - return (extract_C_string(strtab_offset + dt.d_val) - for dt in dyn - if dt.d_tag == tag) - - # PT_DYNAMIC points to the list of ElfNN_Dyn tags. - for dynamic in (phdr for phdr in phdrs if phdr.p_type == PT_DYNAMIC): - dyn = [ - elf.Dyn.read(file, dynamic.p_offset + dyn_offset) - for dyn_offset in xrange(0, dynamic.p_filesz, elf.Dyn.size) - ] - - # DT_STRTAB points to the string table's vaddr (.dynstr). - [strtab_vaddr] = [dt.d_val for dt in dyn if dt.d_tag == DT_STRTAB] - - # Find the PT_LOAD containing the vaddr to compute the file offset. - [strtab_offset] = [ - strtab_vaddr - phdr.p_vaddr + phdr.p_offset - for phdr in phdrs - if (phdr.p_type == PT_LOAD and phdr.p_vaddr <= strtab_vaddr and - strtab_vaddr - phdr.p_vaddr < phdr.p_filesz) - ] - - soname = None - for soname in GenDTStrings(DT_SONAME): - break - - return soname, set(GenDTStrings(DT_NEEDED)) - return None, set() - - def get_stripped(): - return all(shdr.sh_type != SHT_SYMTAB and not name.startswith('.debug_') - for shdr, name in gen_sections()) - - def get_cpu(): - return ELF_MACHINE_TO_CPU.get(ehdr.e_machine) - - # Map in the whole file's contents and use it as a string. - with mmapper(filename) as mapped: - fd, file = mapped - elf = get_elf_accessor(file) - if elf is not None: - # ELF header leads to program headers. - ehdr = elf.Ehdr.read(file) - assert ehdr.e_phentsize == elf.Phdr.size, ( - "%s: invalid e_phentsize" % filename) - phdrs = list(gen_phdrs(file, elf, ehdr)) - return elf_info(filename, get_cpu(), get_matching_notes(), get_build_id(), - get_stripped(), get_interp(), *get_soname_and_needed()) - - return None - - -# Module public API. -__all__ = ['cpu', 'elf_info', 'elf_note', 'get_elf_accessor', 'get_elf_info']
diff --git a/build/config/fuchsia/generate_runner_scripts.gni b/build/config/fuchsia/generate_runner_scripts.gni index 3d45f12..1afbfa4 100644 --- a/build/config/fuchsia/generate_runner_scripts.gni +++ b/build/config/fuchsia/generate_runner_scripts.gni
@@ -81,12 +81,17 @@ } wrapper_script = generated_run_pkg_script_path - deps = [ invoker.package ] - if (defined(invoker.deps)) { - deps += invoker.deps - } + data_deps = [ + invoker.package, - data_deps = [ invoker.package ] + # Runner scripts require access to "ids.txt" for symbolization, and to + # the "package" from which to get the name & version to deploy, which + # are outputs of the archive manifest generation action. + invoker.package + "__archive-manifest", + ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps + } # Declares the files that are needed for test execution on the # swarming test client. @@ -133,7 +138,10 @@ package_dep_target = package_dep[0] package_dep_name = package_dep[1] - deps += [ package_dep_target ] + data_deps += [ + package_dep_target, + package_dep_target + "__archive-manifest", + ] package_dep_path = rebase_path( get_label_info(package_dep_target, "target_gen_dir") + "/" + package_dep_name + "/" + package_dep_name + ".far", @@ -178,9 +186,9 @@ executable = rebase_path("//build/fuchsia/deploy_to_amber_repo.py") wrapper_script = generated_install_pkg_script_path - deps = [ invoker.package ] - if (defined(invoker.deps)) { - deps += invoker.deps + data_deps = [ invoker.package ] + if (defined(invoker.data_deps)) { + data_deps += invoker.data_deps } # Build a list of all packages to install, and pass the list to the runner @@ -191,7 +199,7 @@ package_dep_target = package_dep[0] package_dep_name = package_dep[1] - deps += [ package_dep_target ] + data_deps += [ package_dep_target ] package_dep_path = rebase_path( get_label_info(package_dep_target, "target_gen_dir") + "/" + package_dep_name + "/" + package_dep_name + ".far",
diff --git a/build/config/fuchsia/package.gni b/build/config/fuchsia/package.gni index 8fe34fe0..e7bca25 100644 --- a/build/config/fuchsia/package.gni +++ b/build/config/fuchsia/package.gni
@@ -2,8 +2,12 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -import("//build/config/sysroot.gni") +import("//third_party/fuchsia-sdk/sdk/build/component.gni") +import("//third_party/fuchsia-sdk/sdk/build/package.gni") +# DEPRECATED: Use the Fuchsia SDK's fuchsia_component() and fuchsia_package() +# templates directly, in new code. +# # Creates a Fuchsia .far package file containing a Fuchsia component. # # Parameters are: @@ -28,210 +32,107 @@ # # TODO(https://crbug.com/1050703): Migrate consumers to GN SDK equivalents. template("cr_fuchsia_package") { - pkg = { - forward_variables_from(invoker, "*") + assert(defined(invoker.binary)) - if (defined(package_name_override)) { - package_name = package_name_override - } else { - package_name = invoker.target_name - } + if (defined(invoker.package_name_override)) { + _package_name = invoker.package_name_override + } else { + _package_name = invoker.target_name + } - if (defined(archive_name_override)) { - archive_filename = archive_name_override - } else { - archive_filename = package_name - } + _package_contents = [ invoker.binary ] + if (defined(invoker.deps)) { + _package_contents += invoker.deps + } - if (!defined(manifest)) { + _component_cmx_target = target_name + "__cr-component-cmx" + _component_target = target_name + "__cr-component" + _package_components = [ ":${_component_target}" ] + _component_manifest = "${target_gen_dir}/${target_name}.cmx" + + # Process the CMX fragment in |manifest| to get a full manifest. + action(_component_cmx_target) { + forward_variables_from(invoker, [ "testonly" ]) + + if (!defined(invoker.manifest)) { assert(testonly == true) # TODO(1019938): switch the default to tests.cmx which doesn't request # the deprecated-ambient-replace-as-executable feature. - manifest = "//build/config/fuchsia/tests-with-exec.cmx" + _manifest_fragment = "//build/config/fuchsia/tests-with-exec.cmx" + } else { + _manifest_fragment = invoker.manifest + } + + script = "//build/config/fuchsia/build_cmx_from_fragment.py" + inputs = [ _manifest_fragment ] + outputs = [ _component_manifest ] + + args = [ + "--cmx-fragment", + rebase_path(_manifest_fragment), + "--cmx", + rebase_path(_component_manifest), + "--program", + get_label_info(invoker.binary, "name"), + ] + } + + # Declare the primary component for this package. + fuchsia_component(_component_target) { + forward_variables_from(invoker, [ "testonly" ]) + + deps = [ ":${_component_cmx_target}" ] + manifest = _component_manifest + + if (defined(invoker.component_name_override)) { + manifest_output_name = "${invoker.component_name_override}" + } else { + manifest_output_name = "${_package_name}" + } + + data_deps = _package_contents + } + + # Bundle manifests providing additional entrypoints into the package. + if (defined(invoker.additional_manifests)) { + foreach(filename, invoker.additional_manifests) { + _additional_component_target = target_name + "_" + filename + _package_components += [ ":${_additional_component_target}" ] + fuchsia_component(_additional_component_target) { + forward_variables_from(invoker, [ "testonly" ]) + data_deps = _package_contents + manifest = filename + } } } - assert(defined(pkg.binary)) - _pm_tool_path = "//third_party/fuchsia-sdk/sdk/tools/pm" - - _pkg_out_dir = "${target_gen_dir}/${pkg.archive_filename}" - _runtime_deps_file = "$_pkg_out_dir/${pkg.archive_filename}.runtime_deps" - _archive_manifest = "$_pkg_out_dir/${pkg.archive_filename}.archive_manifest" - _build_ids_file = "$_pkg_out_dir/ids.txt" - _meta_far_file = "$_pkg_out_dir/meta.far" - _combined_far_file = "$_pkg_out_dir/${pkg.package_name}-0.far" - _final_far_file = "$_pkg_out_dir/${pkg.archive_filename}.far" - _package_info_path = "$_pkg_out_dir/package" - - if (defined(pkg.component_name_override)) { - _generated_cmx = "$_pkg_out_dir/${pkg.component_name_override}.cmx" + # Generate a Fuchsia ARchive (FAR) of the requested name. + if (defined(invoker.archive_name_override)) { + _archive_name = invoker.archive_name_override } else { - _generated_cmx = "$_pkg_out_dir/${pkg.package_name}.cmx" + _archive_name = _package_name } - _write_manifest_target = "${pkg.package_name}__write_manifest" - _package_target = "${pkg.package_name}__pkg" - _bundle_target = "${pkg.package_name}__bundle" + if (_archive_name != _package_name) { + _archive_target = target_name + "__cr-archive" - # Generates a manifest file based on the GN runtime deps - # suitable for "pm" tool consumption. - action(_write_manifest_target) { - _depfile = "${target_gen_dir}/${target_name}_stamp.d" - - forward_variables_from(invoker, - [ - "data", - "deps", - "testonly", - ]) - - script = "//build/config/fuchsia/prepare_package_inputs.py" - - inputs = [ - _runtime_deps_file, - pkg.manifest, - ] - - outputs = [ - _archive_manifest, - _build_ids_file, - _generated_cmx, - ] - - if (!defined(deps)) { - deps = [] + copy(target_name) { + deps = [ ":${_archive_target}" ] + _pkg_out_dir = "${target_gen_dir}/${_package_name}" + sources = [ "${_pkg_out_dir}/${_package_name}.far" ] + outputs = [ "${_pkg_out_dir}/${_archive_name}.far" ] } - deps += [ pkg.binary ] - data_deps = deps - - # Use a depfile to trigger package rebuilds if any of the files (static - # assets, shared libraries, etc.) included by the package have changed. - depfile = _depfile - - args = [ - "--root-dir", - rebase_path("//", root_build_dir), - "--out-dir", - rebase_path(root_out_dir, root_build_dir), - "--app-name", - pkg.package_name, - "--app-filename", - get_label_info(pkg.binary, "name"), - "--manifest-input-path", - rebase_path(pkg.manifest, root_build_dir), - "--runtime-deps-file", - rebase_path(_runtime_deps_file, root_build_dir), - "--depfile-path", - rebase_path(_depfile, root_build_dir), - "--package-manifest-path", - rebase_path(_archive_manifest, root_build_dir), - "--component-manifest-path", - rebase_path(_generated_cmx, root_build_dir), - "--build-ids-file", - rebase_path(_build_ids_file, root_build_dir), - ] - - if (defined(pkg.excluded_files)) { - foreach(filename, pkg.excluded_files) { - args += [ - "--exclude-file", - filename, - ] - } - } - - if (defined(pkg.additional_manifests)) { - foreach(filename, pkg.additional_manifests) { - args += [ - "--additional-manifest", - rebase_path(filename), - ] - } - } - - write_runtime_deps = _runtime_deps_file + } else { + _archive_target = target_name } - # Creates a signed Fuchsia metadata package. - action(_package_target) { + fuchsia_package(_archive_target) { forward_variables_from(invoker, [ "testonly" ]) - - script = "//build/gn_run_binary.py" - - deps = [ ":$_write_manifest_target" ] - - inputs = [ - # Depend on the SDK hash, to ensure rebuild if the SDK tools change. - "//third_party/fuchsia-sdk/sdk/.hash", - ] - - if (defined(pkg.additional_manifests)) { - inputs += pkg.additional_manifests + package_name = _package_name + if (defined(invoker.excluded_files)) { + excluded_files = invoker.excluded_files } - - outputs = [ _meta_far_file ] - - args = [ - rebase_path(_pm_tool_path, root_build_dir), - "-o", - rebase_path(_pkg_out_dir, root_build_dir), - "-m", - rebase_path(_archive_manifest, root_build_dir), - "build", - ] - } - - # Creates a package containing the metadata archive and blob data. - action(_bundle_target) { - forward_variables_from(invoker, [ "testonly" ]) - - script = "//build/gn_run_binary.py" - - deps = [ - ":$_package_target", - ":$_write_manifest_target", - ] - - inputs = [ - # Depend on the SDK hash, to ensure rebuild if the SDK tools change. - "//third_party/fuchsia-sdk/sdk/.hash", - _meta_far_file, - _archive_manifest, - ] - - outputs = [ _combined_far_file ] - - args = [ - rebase_path(_pm_tool_path, root_build_dir), - "-o", - rebase_path(_pkg_out_dir, root_build_dir), - "-m", - rebase_path(_archive_manifest, root_build_dir), - "archive", - ] - } - - # Copies the archive to a well-known path. - # TODO(kmarshall): Use a 'pm' output flag to write directly to the desired - # file path instead. - copy(target_name) { - forward_variables_from(invoker, [ "testonly" ]) - - # Allows dependent targets to make use of "ids.txt". - public_deps = [ ":$_write_manifest_target" ] - - deps = [ ":$_bundle_target" ] - - data = [ - _final_far_file, - - # Files specified here so that they can be read by isolated testbots. - _package_info_path, - _build_ids_file, - ] - - sources = [ _combined_far_file ] - outputs = [ _final_far_file ] + deps = _package_components } }
diff --git a/build/config/fuchsia/prepare_package_inputs.py b/build/config/fuchsia/prepare_package_inputs.py deleted file mode 100644 index 741dd3e3..0000000 --- a/build/config/fuchsia/prepare_package_inputs.py +++ /dev/null
@@ -1,201 +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. - -"""Creates a archive manifest used for Fuchsia package generation.""" - -import argparse -import elfinfo -import json -import os -import re -import subprocess -import sys -import tempfile - - -def MakePackagePath(file_path, roots): - """Computes a path for |file_path| that is relative to one of the directory - paths in |roots|. - - file_path: The file path to relativize. - roots: A list of directory paths which may serve as a relative root - for |file_path|. - - Examples: - - >>> MakePackagePath('/foo/bar.txt', ['/foo/']) - 'bar.txt' - - >>> MakePackagePath('/foo/dir/bar.txt', ['/foo/']) - 'dir/bar.txt' - - >>> MakePackagePath('/foo/out/Debug/bar.exe', ['/foo/', '/foo/out/Debug/']) - 'bar.exe' - """ - - # Prevents greedily matching against a shallow path when a deeper, better - # matching path exists. - roots.sort(key=len, reverse=True) - - for next_root in roots: - if not next_root.endswith(os.sep): - next_root += os.sep - - if file_path.startswith(next_root): - relative_path = file_path[len(next_root):] - - return relative_path - - return file_path - - -def _GetStrippedPath(bin_path): - """Finds the stripped version of the binary |bin_path| in the build - output directory.""" - - return bin_path.replace('lib.unstripped/', 'lib/').replace( - 'exe.unstripped/', '') - - -def _IsBinary(path): - """Checks if the file at |path| is an ELF executable by inspecting its FourCC - header.""" - - with open(path, 'rb') as f: - file_tag = f.read(4) - return file_tag == '\x7fELF' - - -def _WriteBuildIdsTxt(binary_paths, ids_txt_path): - """Writes an index text file that maps build IDs to the paths of unstripped - binaries.""" - - with open(ids_txt_path, 'w') as ids_file: - for binary_path in binary_paths: - # Paths to the unstripped executables listed in "ids.txt" are specified - # as relative paths to that file. - relative_path = os.path.relpath( - os.path.abspath(binary_path), - os.path.dirname(os.path.abspath(ids_txt_path))) - - info = elfinfo.get_elf_info(_GetStrippedPath(binary_path)) - ids_file.write(info.build_id + ' ' + relative_path + '\n') - - -def BuildManifest(args): - binaries = [] - with open(args.package_manifest_path, 'w') as package_manifest, \ - open(args.depfile_path, 'w') as depfile: - # Process the runtime deps file for file paths, recursively walking - # directories as needed. - # MakePackagePath() may relativize to either the source root or output - # directory. - # runtime_deps may contain duplicate paths, so use a set for - # de-duplication. - expanded_files = set() - for next_path in open(args.runtime_deps_file, 'r'): - next_path = next_path.strip() - if os.path.isdir(next_path): - for root, _, files in os.walk(next_path): - for current_file in files: - if current_file.startswith('.'): - continue - expanded_files.add( - os.path.join(root, current_file)) - else: - expanded_files.add(next_path) - - # Format and write out the manifest contents. - gen_dir = os.path.normpath(os.path.join(args.out_dir, "gen")) - app_found = False - excluded_files_set = set(args.exclude_file) - for current_file in expanded_files: - if _IsBinary(current_file): - binaries.append(current_file) - current_file = _GetStrippedPath(current_file) - - in_package_path = MakePackagePath(current_file, - [gen_dir, args.root_dir, args.out_dir]) - if in_package_path == args.app_filename: - app_found = True - - if in_package_path in excluded_files_set: - excluded_files_set.remove(in_package_path) - continue - - package_manifest.write('%s=%s\n' % (in_package_path, current_file)) - - if len(excluded_files_set) > 0: - raise Exception('Some files were excluded with --exclude-file, but ' - 'not found in the deps list: %s' % - ', '.join(excluded_files_set)); - - if not app_found: - raise Exception('Could not locate executable inside runtime_deps.') - - # Write meta/package manifest file. - with open(os.path.join(os.path.dirname(args.package_manifest_path), - 'package'), 'w') as package_json: - json.dump({'version': '0', 'name': args.app_name}, package_json) - package_manifest.write('meta/package=%s\n' % os.path.relpath( - package_json.name, args.out_dir)) - - # Write component manifest file. - with open(args.component_manifest_path, 'w') as component_manifest_file: - component_manifest = json.load(open(args.manifest_input_path, 'r')) - component_manifest.update({ - 'program': { 'binary': args.app_filename }, - }) - json.dump(component_manifest, component_manifest_file) - - package_manifest.write( - 'meta/%s=%s\n' % (os.path.basename(component_manifest_file.name), - os.path.relpath(args.component_manifest_path, - args.out_dir))) - - for component_manifest in args.additional_manifest: - package_manifest.write( - 'meta/%s=%s\n' % (os.path.basename(component_manifest), - os.path.relpath(component_manifest, args.out_dir))) - - depfile.write( - "%s: %s" % (os.path.relpath(args.package_manifest_path, args.out_dir), - " ".join([os.path.relpath(f, args.out_dir) - for f in expanded_files]))) - - _WriteBuildIdsTxt(binaries, args.build_ids_file) - - return 0 - - -def main(): - parser = argparse.ArgumentParser() - parser.add_argument('--root-dir', required=True, help='Build root directory') - parser.add_argument('--out-dir', required=True, help='Build output directory') - parser.add_argument('--app-name', required=True, help='Package name') - parser.add_argument('--app-filename', required=True, - help='Path to the main application binary relative to the output dir.') - parser.add_argument('--manifest-input-path', required=True, - help='Path to the manifest file relative to the output dir.') - parser.add_argument('--runtime-deps-file', required=True, - help='File with the list of runtime dependencies.') - parser.add_argument('--depfile-path', required=True, - help='Path to write GN deps file.') - parser.add_argument('--exclude-file', action='append', default=[], - help='Package-relative file path to exclude from the package.') - parser.add_argument('--additional-manifest', action='append', default=[], - help='Additional component manifest file to include in the package.') - parser.add_argument('--package-manifest-path', required=True, - help='Package manifest (file listing) output path.') - parser.add_argument('--component-manifest-path', required=True, - help='Component manifest (.cmx) output path.') - parser.add_argument('--build-ids-file', required=True, - help='Debug symbol index path.') - - args = parser.parse_args() - - return BuildManifest(args) - -if __name__ == '__main__': - sys.exit(main())
diff --git a/build/config/fuchsia/symbol_archive.gni b/build/config/fuchsia/symbol_archive.gni index 28fa248..9dcb53c 100644 --- a/build/config/fuchsia/symbol_archive.gni +++ b/build/config/fuchsia/symbol_archive.gni
@@ -8,6 +8,7 @@ # ".build_ids" convention used by the symbolizer and GNU GDB. # # Parameters: +# deps: Must all be cr_fuchsia_package() or fuchsia_package() targets. # ids_txt: The "ids.txt" file which lists the relative paths to unstripped # executables and libraries, along with their build IDs. # archive_name: The path to the compressed tarball that will be generated. @@ -24,7 +25,16 @@ outputs = [ _build_ids ] - deps = invoker.deps + # For each package in |deps| it is necessary to additionally depend upon + # the corresponding archive-manifest target, which is what creates the + # ids.txt file. + deps = [] + foreach(package, invoker.deps) { + deps += [ + package, + package + "__archive-manifest", + ] + } args = [ rebase_path(_ids_txt),
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 16bcf906..6c224f8 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -1628,7 +1628,7 @@ "//components/minidump_uploader:minidump_uploader_java", "//components/paint_preview/player/android:player_java_test_support", "//content/public/test/android:content_java_test_support", - "//ui/android:ui_javatests", + "//ui/android:clipboard_java_test_support", ] }
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index c454ecd..0096116 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -424,6 +424,7 @@ "java/src/org/chromium/chrome/browser/customtabs/CustomTabNavigationEventObserver.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabNightModeStateController.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabObserver.java", + "java/src/org/chromium/chrome/browser/customtabs/CustomTabOrientationController.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabSessionHandler.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabStatusBarColorProvider.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabTabPersistencePolicy.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index 6ad5bbb..a20cf34 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -18,7 +18,6 @@ "javatests/src/org/chromium/chrome/browser/FocusedEditableTextFieldZoomTest.java", "javatests/src/org/chromium/chrome/browser/HTTPSTabsOpenedFromExternalAppTest.java", "javatests/src/org/chromium/chrome/browser/InstalledAppTest.java", - "javatests/src/org/chromium/chrome/browser/InstantStartTest.java", "javatests/src/org/chromium/chrome/browser/IntentHandlerTest.java", "javatests/src/org/chromium/chrome/browser/JavaScriptEvalChromeTest.java", "javatests/src/org/chromium/chrome/browser/LauncherShortcutTest.java",
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataNativeDelegate.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataNativeDelegate.java index 0ff520f..2e7b3ed 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataNativeDelegate.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/user_data/AssistantCollectUserDataNativeDelegate.java
@@ -33,19 +33,10 @@ @Override public void onContactInfoChanged(@Nullable AutofillContact contact) { if (mNativeAssistantCollectUserDataDelegate != 0) { - String name = null; - String phone = null; - String email = null; - - if (contact != null) { - name = contact.getPayerName(); - phone = contact.getPayerPhone(); - email = contact.getPayerEmail(); - } - AssistantCollectUserDataNativeDelegateJni.get().onContactInfoChanged( mNativeAssistantCollectUserDataDelegate, - AssistantCollectUserDataNativeDelegate.this, name, phone, email); + AssistantCollectUserDataNativeDelegate.this, + contact != null ? contact.getProfile() : null); } } @@ -186,8 +177,8 @@ @NativeMethods interface Natives { void onContactInfoChanged(long nativeAssistantCollectUserDataDelegate, - AssistantCollectUserDataNativeDelegate caller, @Nullable String payerName, - @Nullable String payerPhone, @Nullable String payerEmail); + AssistantCollectUserDataNativeDelegate caller, + @Nullable PersonalDataManager.AutofillProfile contactProfile); void onShippingAddressChanged(long nativeAssistantCollectUserDataDelegate, AssistantCollectUserDataNativeDelegate caller, @Nullable PersonalDataManager.AutofillProfile address);
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java index fde7a1e5..e73dc3f 100644 --- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java +++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantPersonalDataManagerTest.java
@@ -10,6 +10,7 @@ import static android.support.test.espresso.action.ViewActions.click; import static android.support.test.espresso.action.ViewActions.scrollTo; import static android.support.test.espresso.action.ViewActions.typeText; +import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; import static android.support.test.espresso.assertion.ViewAssertions.matches; import static android.support.test.espresso.matcher.RootMatchers.withDecorView; import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; @@ -170,6 +171,68 @@ } /** + * Add a contact with Autofill Assistant UI, then edit the profile multiple times (see + * b/153139772). + */ + @Test + @MediumTest + public void testCreateAndEditProfileMultipleTimes() throws Exception { + ArrayList<ActionProto> list = new ArrayList<>(); + list.add( + (ActionProto) ActionProto.newBuilder() + .setCollectUserData( + CollectUserDataProto.newBuilder() + .setContactDetails(ContactDetailsProto.newBuilder() + .setContactDetailsName("contact") + .setRequestPayerName(true) + .setRequestPayerEmail(true) + .setRequestPayerPhone(false)) + .setRequestTermsAndConditions(false)) + .build()); + AutofillAssistantTestScript script = new AutofillAssistantTestScript( + (SupportedScriptProto) SupportedScriptProto.newBuilder() + .setPath("form_target_website.html") + .setPresentation(PresentationProto.newBuilder().setAutostart(true).setChip( + ChipProto.newBuilder().setText("Address"))) + .build(), + list); + runScript(script); + + waitUntilViewMatchesCondition( + allOf(withId(R.id.section_title_add_button_label), withText("Add contact info")), + isCompletelyDisplayed()); + onView(allOf(withId(R.id.section_title_add_button_label), withText("Add contact info"))) + .perform(click()); + waitUntilViewMatchesCondition( + withContentDescription("Name*"), allOf(isDisplayed(), isEnabled())); + onView(withContentDescription("Name*")).perform(typeText("John Doe")); + waitUntilViewMatchesCondition( + withContentDescription("Email*"), allOf(isDisplayed(), isEnabled())); + onView(withContentDescription("Email*")).perform(typeText("doe@google.com")); + onView(withId(org.chromium.chrome.R.id.editor_dialog_done_button)).perform(click()); + waitUntilViewMatchesCondition(withText("Continue"), isEnabled()); + + // First edit: no changes. + onView(withText("Contact info")).perform(click()); + onView(withContentDescription("Edit contact info")).perform(click()); + waitUntilViewMatchesCondition( + withContentDescription("Name*"), allOf(isDisplayed(), isEnabled())); + onView(withId(org.chromium.chrome.R.id.editor_dialog_done_button)).perform(click()); + + // Second edit: change name from John Doe to Jane Doe. + onView(withContentDescription("Edit contact info")).perform(click()); + waitUntilViewMatchesCondition( + withContentDescription("Name*"), allOf(isDisplayed(), isEnabled())); + onView(withContentDescription("Name*")).perform(clearText(), typeText("Jane Doe")); + onView(withId(org.chromium.chrome.R.id.editor_dialog_done_button)).perform(click()); + + // There used to be a bug where consecutive edits of the same profile would create a + // duplicate profile, which would break the following checks. + onView(withText(containsString("John Doe"))).check(doesNotExist()); + onView(withText(containsString("Jane Doe"))).check(matches(isDisplayed())); + } + + /** * Catch the insert of a profile added outside of the Autofill Assistant, e.g. with the Chrome * settings UI, and fill it into the form. */
diff --git a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java index 5f90465..cc21289 100644 --- a/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java +++ b/chrome/android/features/start_surface/internal/java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java
@@ -422,7 +422,7 @@ private void reportAnimationPerf(boolean isShrinking) { int frameRendered = mFrameCount - mStartFrame; long elapsedMs = SystemClock.elapsedRealtime() - mStartTime; - long lastDirty = mTabListDelegate.getLastDirtyTimeForTesting(); + long lastDirty = mTabListDelegate.getLastDirtyTime(); int dirtySpan = (int) (lastDirty - mStartTime); float fps = 1000.f * frameRendered / elapsedMs; String message = String.format(Locale.US,
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/InstantStartTest.java b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java similarity index 96% rename from chrome/android/javatests/src/org/chromium/chrome/browser/InstantStartTest.java rename to chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java index e1b9524..bb335f8f 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/InstantStartTest.java +++ b/chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser; +package org.chromium.chrome.features.start_surface; import static com.google.common.truth.Truth.assertThat; @@ -40,8 +40,6 @@ import org.chromium.chrome.browser.tasks.pseudotab.TabAttributeCache; import org.chromium.chrome.browser.tasks.tab_management.TabManagementDelegate; import org.chromium.chrome.browser.tasks.tab_management.TabManagementModuleProvider; -import org.chromium.chrome.features.start_surface.StartSurface; -import org.chromium.chrome.features.start_surface.StartSurfaceLayout; import org.chromium.chrome.tab_ui.R; import org.chromium.chrome.test.ChromeJUnit4ClassRunner; import org.chromium.chrome.test.ChromeTabbedActivityTestRule; @@ -153,8 +151,15 @@ */ @Test @SmallTest - @CommandLineFlags.Add(ChromeSwitches.DISABLE_NATIVE_INITIALIZATION) + // clang-format off + @Features.EnableFeatures({ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID + "<Study"}) + @CommandLineFlags.Add({ChromeSwitches.DISABLE_NATIVE_INITIALIZATION, + "force-fieldtrials=Study/Group", + "force-fieldtrial-params=Study.Group:allow_to_refetch/true/thumbnail_aspect_ratio/2.0"}) public void fetchThumbnailsPreNativeTest() { + // clang-format on + Assert.assertTrue(TabContentManager.ALLOW_TO_REFETCH_TAB_THUMBNAIL_VARIATION.getValue()); + int tabId = 0; mThumbnailFetchCount = 0; Callback<Bitmap> thumbnailFetchListener = (bitmap) -> {
diff --git a/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni b/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni index df6c744..92bb05ab 100644 --- a/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni +++ b/chrome/android/features/start_surface/internal/javatests/start_surface_test_java_sources.gni
@@ -5,6 +5,7 @@ start_surface_test_java_sources = [ "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/BottomBarViewBinderTest.java", "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/ExploreSurfaceViewBinderTest.java", + "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/InstantStartTest.java", "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinderTest.java", "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutPerfTest.java", "//chrome/android/features/start_surface/internal/javatests/src/org/chromium/chrome/features/start_surface/StartSurfaceLayoutTest.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherCoordinator.java index e950ddf..09b44cd 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/SingleTabSwitcherCoordinator.java
@@ -51,7 +51,7 @@ } @Override - public long getLastDirtyTimeForTesting() { + public long getLastDirtyTime() { assert false : "should not reach here"; return 0; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java index 1fefcb7..f7ad37b 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListCoordinator.java
@@ -388,8 +388,8 @@ return mRecyclerView.getResourceId(); } - long getLastDirtyTimeForTesting() { - return mRecyclerView.getLastDirtyTimeForTesting(); + long getLastDirtyTime() { + return mRecyclerView.getLastDirtyTime(); } /**
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java index 4517d87..890e283 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListRecyclerView.java
@@ -266,7 +266,7 @@ return mResourceId; } - long getLastDirtyTimeForTesting() { + long getLastDirtyTime() { return mLastDirtyTime; }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java index a0967892..f51f27ff 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcher.java
@@ -142,7 +142,7 @@ * @return The timestamp of last dirty event of {@link ViewResourceAdapter} of * {@link TabListRecyclerView}. */ - long getLastDirtyTimeForTesting(); + long getLastDirtyTime(); /** * Before calling {@link Controller#showOverview} to start showing the
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java index 0bad646..13654c9 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabSwitcherCoordinator.java
@@ -308,8 +308,8 @@ } @Override - public long getLastDirtyTimeForTesting() { - return mTabListCoordinator.getLastDirtyTimeForTesting(); + public long getLastDirtyTime() { + return mTabListCoordinator.getLastDirtyTime(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/TwaSplashController.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/TwaSplashController.java index 449d7f0..63238be 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/TwaSplashController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/trustedwebactivityui/splashscreen/TwaSplashController.java
@@ -13,7 +13,6 @@ import android.graphics.Bitmap; import android.graphics.Color; import android.graphics.Matrix; -import android.os.Build; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; @@ -25,14 +24,14 @@ import org.chromium.base.IntentUtils; import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider; +import org.chromium.chrome.browser.customtabs.BaseCustomTabActivity; +import org.chromium.chrome.browser.customtabs.CustomTabOrientationController; import org.chromium.chrome.browser.customtabs.TranslucentCustomTabActivity; import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; import org.chromium.chrome.browser.lifecycle.InflationObserver; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.webapps.SplashController; import org.chromium.chrome.browser.webapps.SplashDelegate; -import org.chromium.chrome.browser.webapps.SplashscreenObserver; -import org.chromium.content_public.browser.ScreenOrientationProvider; import org.chromium.ui.base.ActivityWindowAndroid; import org.chromium.ui.util.ColorUtils; @@ -64,9 +63,7 @@ * gc-ed when it finishes its job (to that end, it removes all observers it has set). * If these lifecycle assumptions change, consider whether @ActivityScope needs to be added. */ -public class TwaSplashController - implements InflationObserver, SplashDelegate, SplashscreenObserver { - +public class TwaSplashController implements InflationObserver, SplashDelegate { // TODO(pshmakov): move this to AndroidX. private static final String KEY_SHOWN_IN_CLIENT = "androidx.browser.trusted.KEY_SPLASH_SCREEN_SHOWN_IN_CLIENT"; @@ -75,7 +72,6 @@ private final Activity mActivity; private final ActivityWindowAndroid mActivityWindowAndroid; private final ActivityLifecycleDispatcher mLifecycleDispatcher; - private final ScreenOrientationProvider mScreenOrientationProvider; private final SplashImageHolder mSplashImageCache; private final BrowserServicesIntentDataProvider mIntentDataProvider; @@ -83,31 +79,27 @@ public TwaSplashController(SplashController splashController, Activity activity, ActivityWindowAndroid activityWindowAndroid, ActivityLifecycleDispatcher lifecycleDispatcher, - ScreenOrientationProvider screenOrientationProvider, SplashImageHolder splashImageCache, + CustomTabOrientationController orientationController, + SplashImageHolder splashImageCache, BrowserServicesIntentDataProvider intentDataProvider) { mSplashController = splashController; mActivity = activity; mActivityWindowAndroid = activityWindowAndroid; mLifecycleDispatcher = lifecycleDispatcher; - mScreenOrientationProvider = screenOrientationProvider; mSplashImageCache = splashImageCache; mIntentDataProvider = intentDataProvider; long splashHideAnimationDurationMs = IntentUtils.safeGetInt( getSplashScreenParamsFromIntent(), SplashScreenParamKey.KEY_FADE_OUT_DURATION_MS, 0); - boolean isWindowInitiallyTranslucent = mActivity instanceof TranslucentCustomTabActivity; + boolean isWindowInitiallyTranslucent = + BaseCustomTabActivity.isWindowInitiallyTranslucent(activity); mSplashController.setConfig( this, isWindowInitiallyTranslucent, splashHideAnimationDurationMs); + orientationController.delayOrientationRequestsIfNeeded( + mSplashController, isWindowInitiallyTranslucent); - mSplashController.addObserver(this); lifecycleDispatcher.register(this); - - // Setting the screen orientation while the activity is translucent throws an exception on - // O (but not on O MR1). Delay setting it. - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O) { - mScreenOrientationProvider.delayOrientationRequests(mActivityWindowAndroid); - } } @Override @@ -142,14 +134,6 @@ mSplashController.bringSplashBackToFront(); } - @Override - public void onTranslucencyRemoved() { - mScreenOrientationProvider.runDelayedOrientationRequests(mActivityWindowAndroid); - } - - @Override - public void onSplashscreenHidden(long startTimestamp, long endTimestamp) {} - private void applyCustomizationsToSplashScreenView(ImageView imageView) { Bundle params = getSplashScreenParamsFromIntent();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java index 45477d8d..d878740 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/content/TabContentManager.java
@@ -79,7 +79,7 @@ @VisibleForTesting public static final String UMA_THUMBNAIL_FETCHING_RESULT = "GridTabSwitcher.ThumbnailFetchingResult"; - private Set<Integer> mRefectchedTabIds; + private final Set<Integer> mRefectchedTabIds = new HashSet<>(); private float mThumbnailScale; private int mFullResThumbnailsMaxSize; @@ -160,18 +160,43 @@ mContentOffsetProvider = contentOffsetProvider; mTabFinder = tabFinder; mSnapshotsEnabled = snapshotsEnabled; - } - /** - * Called after native library is loaded. - */ - public void initWithNative() { // Override the cache size on the command line with --thumbnails=100 int defaultCacheSize = getIntegerResourceWithOverride( mContext, R.integer.default_thumbnail_cache_size, ChromeSwitches.THUMBNAILS); mFullResThumbnailsMaxSize = defaultCacheSize; + float thumbnailScale = 1.f; + DisplayAndroid display = DisplayAndroid.getNonMultiDisplay(mContext); + float deviceDensity = display.getDipScale(); + if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(mContext)) { + // Scale all tablets to MDPI. + thumbnailScale = 1.f / deviceDensity; + } else { + // For phones, reduce the amount of memory usage by capturing a lower-res thumbnail for + // devices with resolution higher than HDPI (crbug.com/357740). + if (deviceDensity > 1.5f) { + thumbnailScale = 1.5f / deviceDensity; + } + } + mThumbnailScale = thumbnailScale; + + mPriorityTabIds = new int[mFullResThumbnailsMaxSize]; + + if (TabUiFeatureUtilities.isTabThumbnailAspectRatioNotOne() + || ALLOW_TO_REFETCH_TAB_THUMBNAIL_VARIATION.getValue()) { + mExpectedThumbnailAspectRatio = + (float) TabUiFeatureUtilities.THUMBNAIL_ASPECT_RATIO.getValue(); + mExpectedThumbnailAspectRatio = + MathUtils.clamp(mExpectedThumbnailAspectRatio, 0.5f, 2.0f); + } + } + + /** + * Called after native library is loaded. + */ + public void initWithNative() { int compressionQueueMaxSize = mContext.getResources().getInteger(R.integer.default_compression_queue_size); int writeQueueMaxSize = @@ -183,40 +208,12 @@ R.integer.default_approximation_thumbnail_cache_size, ChromeSwitches.APPROXIMATION_THUMBNAILS); - float thumbnailScale = 1.f; - boolean useApproximationThumbnails; + boolean useApproximationThumbnails = + !DeviceFormFactor.isNonMultiDisplayContextOnTablet(mContext); boolean saveJpegThumbnails = TabUiFeatureUtilities.isGridTabSwitcherEnabled(); - DisplayAndroid display = DisplayAndroid.getNonMultiDisplay(mContext); - float deviceDensity = display.getDipScale(); - if (DeviceFormFactor.isNonMultiDisplayContextOnTablet(mContext)) { - // Scale all tablets to MDPI. - thumbnailScale = 1.f / deviceDensity; - useApproximationThumbnails = false; - } else { - // For phones, reduce the amount of memory usage by capturing a lower-res thumbnail for - // devices with resolution higher than HDPI (crbug.com/357740). - if (deviceDensity > 1.5f) { - thumbnailScale = 1.5f / deviceDensity; - } - useApproximationThumbnails = true; - } - mThumbnailScale = thumbnailScale; - - mPriorityTabIds = new int[mFullResThumbnailsMaxSize]; - - if (TabUiFeatureUtilities.isTabThumbnailAspectRatioNotOne() - || ALLOW_TO_REFETCH_TAB_THUMBNAIL_VARIATION.getValue()) { - mRefectchedTabIds = new HashSet<>(); - mExpectedThumbnailAspectRatio = - (float) ChromeFeatureList.getFieldTrialParamByFeatureAsDouble( - ChromeFeatureList.TAB_GRID_LAYOUT_ANDROID, "thumbnail_aspect_ratio", - 1.0); - mExpectedThumbnailAspectRatio = - MathUtils.clamp(mExpectedThumbnailAspectRatio, 0.5f, 2.0f); - } mNativeTabContentManager = TabContentManagerJni.get().init(TabContentManager.this, - defaultCacheSize, approximationCacheSize, compressionQueueMaxSize, + mFullResThumbnailsMaxSize, approximationCacheSize, compressionQueueMaxSize, writeQueueMaxSize, useApproximationThumbnails, saveJpegThumbnails); } @@ -467,8 +464,14 @@ >= ASPECT_RATIO_PRECISION) { recordThumbnailFetchingResult( ThumbnailFetchingResult.GOT_DIFFERENT_ASPECT_RATIO_JPEG); + + if (mNativeTabContentManager == 0) { + callback.onResult(jpeg); + return; + } + if (!mSnapshotsEnabled) return; + mRefectchedTabIds.add(tabId); - if (mNativeTabContentManager == 0 || !mSnapshotsEnabled) return; TabContentManagerJni.get().getEtc1TabThumbnail(mNativeTabContentManager, TabContentManager.this, tabId, (etc1) -> callback.onResult(etc1));
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java index f81fbb7..fe1268e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/BaseCustomTabActivity.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.customtabs; +import android.app.Activity; import android.content.Intent; import android.util.Pair; import android.view.KeyEvent; @@ -32,6 +33,7 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.chrome.browser.tabmodel.TabModelSelectorImpl; import org.chromium.chrome.browser.ui.RootUiCoordinator; +import org.chromium.chrome.browser.webapps.SameTaskWebApkActivity; import org.chromium.chrome.browser.webapps.WebappActivityCoordinator; /** @@ -63,6 +65,14 @@ @VisibleForTesting public abstract BrowserServicesIntentDataProvider getIntentDataProvider(); + /** + * @return Whether the activity window is initially translucent. + */ + public static boolean isWindowInitiallyTranslucent(Activity activity) { + return activity instanceof TranslucentCustomTabActivity + || activity instanceof SameTaskWebApkActivity; + } + @Override protected RootUiCoordinator createRootUiCoordinator() { return new BaseCustomTabRootUiCoordinator(this, getShareDelegateSupplier(),
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabOrientationController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabOrientationController.java new file mode 100644 index 0000000..906880e --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabOrientationController.java
@@ -0,0 +1,86 @@ +// 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.customtabs; + +import android.os.Build; + +import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider; +import org.chromium.chrome.browser.dependency_injection.ActivityScope; +import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; +import org.chromium.chrome.browser.lifecycle.InflationObserver; +import org.chromium.chrome.browser.webapps.SplashController; +import org.chromium.chrome.browser.webapps.SplashscreenObserver; +import org.chromium.chrome.browser.webapps.WebappExtras; +import org.chromium.content_public.browser.ScreenOrientationProvider; +import org.chromium.content_public.common.ScreenOrientationValues; +import org.chromium.ui.base.ActivityWindowAndroid; + +import javax.inject.Inject; + +/** + * Manages setting the initial screen orientation for the custom tab. + * Delays all screen orientation requests till the activity translucency is removed. + */ +@ActivityScope +public class CustomTabOrientationController implements InflationObserver { + private final ActivityWindowAndroid mActivityWindowAndroid; + private final ActivityLifecycleDispatcher mLifecycleDispatcher; + + private @ScreenOrientationValues int mLockScreenOrientation = ScreenOrientationValues.DEFAULT; + + @Inject + public CustomTabOrientationController(ActivityWindowAndroid activityWindowAndroid, + BrowserServicesIntentDataProvider intentDataProvider, + ActivityLifecycleDispatcher lifecycleDispatcher) { + mActivityWindowAndroid = activityWindowAndroid; + mLifecycleDispatcher = lifecycleDispatcher; + + WebappExtras webappExtras = intentDataProvider.getWebappExtras(); + if (webappExtras != null) { + mLockScreenOrientation = webappExtras.orientation; + mLifecycleDispatcher.register(this); + } + } + + /** + * Delays screen orientation requests if the activity window's initial translucency and the + * Android OS version requires it. + * Should be called: + * - Prior to pre inflation startup occurring. + * - Only if the splash screen is shown for the activity. + */ + public void delayOrientationRequestsIfNeeded( + SplashController splashController, boolean isWindowInitiallyTranslucent) { + // Setting the screen orientation while the activity is translucent throws an exception on + // O (but not on O MR1). + if (!isWindowInitiallyTranslucent || Build.VERSION.SDK_INT != Build.VERSION_CODES.O) return; + + ScreenOrientationProvider.getInstance().delayOrientationRequests(mActivityWindowAndroid); + + splashController.addObserver(new SplashscreenObserver() { + @Override + public void onTranslucencyRemoved() { + ScreenOrientationProvider.getInstance().runDelayedOrientationRequests( + mActivityWindowAndroid); + } + + @Override + public void onSplashscreenHidden(long startTimestamp, long endTimestamp) {} + }); + } + + @Override + public void onPreInflationStartup() { + mLifecycleDispatcher.unregister(this); + + // Queue up default screen orientation request now because the web page might change it via + // JavaScript. + ScreenOrientationProvider.getInstance().lockOrientation( + mActivityWindowAndroid, (byte) mLockScreenOrientation); + } + + @Override + public void onPostInflationStartup() {} +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java index 14c08a5..ac9a0d0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/page_info/PageInfoController.java
@@ -300,8 +300,11 @@ CookieControlsView.CookieControlsParams cookieControlsParams = new CookieControlsView.CookieControlsParams(); cookieControlsParams.onUiClosingCallback = mBridge::onUiClosing; - cookieControlsParams.onCheckedChangedCallback = - mBridge::setThirdPartyCookieBlockingEnabledForSite; + cookieControlsParams.onCheckedChangedCallback = (Boolean blockCookies) -> { + recordAction(blockCookies ? PageInfoAction.PAGE_INFO_COOKIE_BLOCKED_FOR_SITE + : PageInfoAction.PAGE_INFO_COOKIE_ALLOWED_FOR_SITE); + mBridge.setThirdPartyCookieBlockingEnabledForSite(blockCookies); + }; mView.getCookieControlsView().setParams(cookieControlsParams); mWebContentsObserver = new WebContentsObserver(webContents) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkExtras.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkExtras.java index e577f794..06d141f 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkExtras.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkExtras.java
@@ -4,9 +4,12 @@ package org.chromium.chrome.browser.webapps; +import androidx.annotation.NonNull; + import org.chromium.chrome.browser.webapps.WebApkInfo.ShareTarget; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; import java.util.Map; @@ -22,6 +25,7 @@ /** * Icon to use for the splash screen. */ + @NonNull public final WebappIcon splashIcon; /** @@ -50,6 +54,7 @@ /** * Map of the WebAPK's icon URLs to Murmur2 hashes of the icon untransformed bytes. */ + @NonNull public final Map<String, String> iconUrlToMurmur2HashMap; /** @@ -57,6 +62,7 @@ * TODO(pkotwicz): Remove this property in favor of * {@link BrowserServicesIntentDataProvider#shareTarget()} */ + @NonNull public final ShareTarget shareTarget; /** @@ -70,6 +76,7 @@ /** * The list of the WebAPK's shortcuts. */ + @NonNull public final List<ShortcutItem> shortcutItems; /** @@ -99,16 +106,16 @@ return new WebApkExtras(null /* webApkPackageName */, new WebappIcon(), false /* isSplashIconMaskable */, 0 /* shellApkVersion */, null /* manifestUrl */, null /* manifestStartUrl */, WebApkDistributor.OTHER, - null /* iconUrlToMurmur2HashMap */, new ShareTarget(), + new HashMap<String, String>() /* iconUrlToMurmur2HashMap */, new ShareTarget(), false /* isSplashProvidedByWebApk */, new ArrayList<>() /* shortcutItems */, 0 /* webApkVersionCode */); } - public WebApkExtras(String webApkPackageName, WebappIcon splashIcon, + public WebApkExtras(String webApkPackageName, @NonNull WebappIcon splashIcon, boolean isSplashIconMaskable, int shellApkVersion, String manifestUrl, String manifestStartUrl, @WebApkDistributor int distributor, - Map<String, String> iconUrlToMurmur2HashMap, ShareTarget shareTarget, - boolean isSplashProvidedByWebApk, List<ShortcutItem> shortcutItems, + @NonNull Map<String, String> iconUrlToMurmur2HashMap, @NonNull ShareTarget shareTarget, + boolean isSplashProvidedByWebApk, @NonNull List<ShortcutItem> shortcutItems, int webApkVersionCode) { this.webApkPackageName = webApkPackageName; this.splashIcon = splashIcon;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java index bf8a091..5aabe5ea 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebApkInfo.java
@@ -10,10 +10,8 @@ import androidx.annotation.Nullable; import androidx.browser.trusted.sharing.ShareData; -import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider; import org.chromium.chrome.browser.webapps.WebApkExtras.ShortcutItem; -import org.chromium.webapk.lib.common.WebApkConstants; import java.util.Arrays; import java.util.List; @@ -180,96 +178,12 @@ return (provider != null) ? new WebApkInfo(provider) : null; } - public WebApkInfo(@NonNull BrowserServicesIntentDataProvider provider) { - super(provider); - } - - /** - * Returns the splash icon in Bitmap form. - */ - public WebappIcon splashIcon() { - return getWebApkExtras().splashIcon; - } - - public boolean isSplashIconMaskable() { - return getWebApkExtras().isSplashIconMaskable; - } - - /** Returns data about the WebAPK's share intent handlers. */ - public ShareTarget shareTarget() { - return getWebApkExtras().shareTarget; - } - - /** - * Returns the WebAPK's version code. - */ - public int webApkVersionCode() { - return getWebApkExtras().webApkVersionCode; - } - - @Override - public boolean isForWebApk() { - return true; - } - - @Override - public String webApkPackageName() { - return getWebApkExtras().webApkPackageName; - } - - @Override - public boolean isSplashProvidedByWebApk() { - return getWebApkExtras().isSplashProvidedByWebApk; - } - - public int shellApkVersion() { - return getWebApkExtras().shellApkVersion; - } - - public String manifestUrl() { - return getWebApkExtras().manifestUrl; - } - - public String manifestStartUrl() { - return getWebApkExtras().manifestStartUrl; - } - - public @WebApkDistributor int distributor() { - return getWebApkExtras().distributor; - } - - public Map<String, String> iconUrlToMurmur2HashMap() { - return getWebApkExtras().iconUrlToMurmur2HashMap; - } - - public ShareData shareData() { - return mProvider.getShareData(); - } - - public List<ShortcutItem> shortcutItems() { - return getWebApkExtras().shortcutItems; - } - - private WebApkExtras getWebApkExtras() { - WebApkExtras extras = mProvider.getWebApkExtras(); - assert extras != null; - return extras; - } - - @Override - public void setWebappIntentExtras(Intent intent) { - // For launching a WebAPK Activity. - intent.putExtra(ShortcutHelper.EXTRA_ID, id()); - intent.putExtra(ShortcutHelper.EXTRA_URL, url()); - intent.putExtra(ShortcutHelper.EXTRA_SOURCE, source()); - intent.putExtra(ShortcutHelper.EXTRA_FORCE_NAVIGATION, shouldForceNavigation()); - intent.putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, webApkPackageName()); - intent.putExtra( - WebApkConstants.EXTRA_SPLASH_PROVIDED_BY_WEBAPK, isSplashProvidedByWebApk()); - } - /** Returns the value if it is non-null. Returns an empty string otherwise. */ private static String replaceNullWithEmpty(String value) { return (value == null) ? "" : value; } + + public WebApkInfo(@NonNull BrowserServicesIntentDataProvider provider) { + super(provider); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java index afe05fb0..336b1854 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -11,7 +11,6 @@ import android.graphics.PixelFormat; import android.graphics.drawable.Drawable; import android.net.Uri; -import android.os.Build; import android.os.StrictMode; import android.text.TextUtils; import android.view.ViewGroup; @@ -51,7 +50,6 @@ import org.chromium.chrome.browser.webapps.dependency_injection.WebappActivityModule; import org.chromium.components.embedder_support.delegate.WebContentsDelegateAndroid; import org.chromium.content_public.browser.NavigationHandle; -import org.chromium.content_public.browser.ScreenOrientationProvider; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.webapk.lib.common.WebApkConstants; @@ -294,8 +292,6 @@ super.performPreInflationStartup(); - applyScreenOrientation(); - if (mWebappInfo.displayMode() == WebDisplayMode.FULLSCREEN) { new ImmersiveModeController(getLifecycleDispatcher(), this).enterImmersiveMode( LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT, false /*sticky*/); @@ -517,39 +513,13 @@ /** Inits the splash screen */ private void initSplash() { // Splash screen is shown after preInflationStartup() is run and the delegate is set. - boolean isWindowInitiallyTranslucent = mWebappInfo.isSplashProvidedByWebApk(); + boolean isWindowInitiallyTranslucent = + BaseCustomTabActivity.isWindowInitiallyTranslucent(this); mSplashController.setConfig( new WebappSplashDelegate(this, mTabObserverRegistrar, mWebappInfo), isWindowInitiallyTranslucent, WebappSplashDelegate.HIDE_ANIMATION_DURATION_MS); } - /** Sets the screen orientation. */ - private void applyScreenOrientation() { - if (mWebappInfo.isSplashProvidedByWebApk() - && Build.VERSION.SDK_INT == Build.VERSION_CODES.O) { - // When the splash screen is provided by the WebAPK, the activity is initially - // translucent. Setting the screen orientation while the activity is translucent - // throws an exception on O (but not O MR1). Delay setting it. - ScreenOrientationProvider.getInstance().delayOrientationRequests(getWindowAndroid()); - - mSplashController.addObserver(new SplashscreenObserver() { - @Override - public void onTranslucencyRemoved() { - ScreenOrientationProvider.getInstance().runDelayedOrientationRequests( - getWindowAndroid()); - } - - @Override - public void onSplashscreenHidden(long startTimestamp, long endTimestamp) {} - }); - - // Fall through and queue up request for the default screen orientation because the web - // page might change it via JavaScript. - } - ScreenOrientationProvider.getInstance().lockOrientation( - getWindowAndroid(), (byte) mWebappInfo.orientation()); - } - @Override public void onUpdateStateChanged() {} }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivityCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivityCoordinator.java index 3541c82..94625a1e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivityCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivityCoordinator.java
@@ -12,6 +12,8 @@ import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.CurrentPageVerifier; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.TrustedWebActivityBrowserControlsVisibilityManager; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.controller.Verifier; +import org.chromium.chrome.browser.customtabs.BaseCustomTabActivity; +import org.chromium.chrome.browser.customtabs.CustomTabOrientationController; import org.chromium.chrome.browser.customtabs.ExternalIntentsPolicyProvider; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController; import org.chromium.chrome.browser.dependency_injection.ActivityScope; @@ -41,6 +43,7 @@ ActivityTabProvider activityTabProvider, CurrentPageVerifier currentPageVerifier, Verifier verifier, CustomTabActivityNavigationController navigationController, ExternalIntentsPolicyProvider externalIntentsPolicyProvider, + CustomTabOrientationController orientationController, SplashController splashController, WebappDeferredStartupWithStorageHandler deferredStartupWithStorageHandler, WebappActionsNotificationManager actionsNotificationManager, ActivityLifecycleDispatcher lifecycleDispatcher, @@ -70,6 +73,9 @@ } }); + orientationController.delayOrientationRequestsIfNeeded( + splashController, BaseCustomTabActivity.isWindowInitiallyTranslucent(activity)); + currentPageVerifier.addVerificationObserver(this::onVerificationUpdate); lifecycleDispatcher.register(this); }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java index 33fa8a0..5537fa2 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappDataStorage.java
@@ -263,12 +263,11 @@ editor.putInt(KEY_VERSION, ShortcutHelper.WEBAPP_SHORTCUT_VERSION); if (info.isForWebApk()) { - WebApkInfo webApkInfo = (WebApkInfo) info; - editor.putString(KEY_WEBAPK_PACKAGE_NAME, webApkInfo.webApkPackageName()); - editor.putString(KEY_WEBAPK_MANIFEST_URL, webApkInfo.manifestUrl()); - editor.putInt(KEY_WEBAPK_VERSION_CODE, webApkInfo.webApkVersionCode()); + editor.putString(KEY_WEBAPK_PACKAGE_NAME, info.webApkPackageName()); + editor.putString(KEY_WEBAPK_MANIFEST_URL, info.manifestUrl()); + editor.putInt(KEY_WEBAPK_VERSION_CODE, info.webApkVersionCode()); editor.putLong(KEY_WEBAPK_INSTALL_TIMESTAMP, - fetchWebApkInstallTimestamp(webApkInfo.webApkPackageName())); + fetchWebApkInstallTimestamp(info.webApkPackageName())); } else { editor.putString(KEY_NAME, info.name()); editor.putString(KEY_SHORT_NAME, info.shortName());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappExtras.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappExtras.java index 401f48a8..00c802ff 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappExtras.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappExtras.java
@@ -6,6 +6,8 @@ import android.graphics.Color; +import androidx.annotation.NonNull; + import org.chromium.chrome.browser.ShortcutSource; import org.chromium.content_public.common.ScreenOrientationValues; @@ -28,6 +30,7 @@ /** * The webapp's launcher icon. */ + @NonNull public final WebappIcon icon; /** @@ -87,10 +90,10 @@ false /* isIconAdaptive */, false /* shouldForceNavigation */); } - public WebappExtras(String id, String url, String scopeUrl, WebappIcon icon, String name, - String shortName, @WebDisplayMode int displayMode, int orientation, int source, - Integer backgroundColor, int defaultBackgroundColor, boolean isIconGenerated, - boolean isIconAdaptive, boolean shouldForceNavigation) { + public WebappExtras(String id, String url, String scopeUrl, @NonNull WebappIcon icon, + String name, String shortName, @WebDisplayMode int displayMode, int orientation, + int source, Integer backgroundColor, int defaultBackgroundColor, + boolean isIconGenerated, boolean isIconAdaptive, boolean shouldForceNavigation) { this.id = id; this.url = url; this.scopeUrl = scopeUrl;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java index 5b470ce..c6d60ed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappInfo.java
@@ -5,18 +5,27 @@ package org.chromium.chrome.browser.webapps; import android.content.Intent; +import android.text.TextUtils; import androidx.annotation.NonNull; +import androidx.browser.trusted.sharing.ShareData; import org.chromium.chrome.browser.ShortcutHelper; import org.chromium.chrome.browser.ShortcutSource; import org.chromium.chrome.browser.browserservices.BrowserServicesIntentDataProvider; +import org.chromium.chrome.browser.webapps.WebApkExtras.ShortcutItem; +import org.chromium.chrome.browser.webapps.WebApkInfo.ShareTarget; +import org.chromium.webapk.lib.common.WebApkConstants; + +import java.util.List; +import java.util.Map; /** * Stores info about a web app. */ public class WebappInfo { - protected final BrowserServicesIntentDataProvider mProvider; + private final @NonNull BrowserServicesIntentDataProvider mProvider; + private final @NonNull WebApkExtras mWebApkExtras; public static WebappInfo createEmpty() { return new WebappInfo( @@ -36,6 +45,8 @@ protected WebappInfo(@NonNull BrowserServicesIntentDataProvider provider) { mProvider = provider; + WebApkExtras webApkExtras = provider.getWebApkExtras(); + mWebApkExtras = (webApkExtras != null) ? webApkExtras : WebApkExtras.createEmpty(); } @NonNull @@ -76,11 +87,11 @@ } public boolean isForWebApk() { - return false; + return !TextUtils.isEmpty(webApkPackageName()); } public String webApkPackageName() { - return null; + return mWebApkExtras.webApkPackageName; } public int orientation() { @@ -136,6 +147,7 @@ /** * Returns the icon. */ + @NonNull public WebappIcon icon() { return getWebappExtras().icon; } @@ -159,7 +171,62 @@ * and (2) has a content provider which provides a screenshot of the splash screen. */ public boolean isSplashProvidedByWebApk() { - return false; + return mWebApkExtras.isSplashProvidedByWebApk; + } + + /** + * Returns the WebAPK's splash icon. + */ + @NonNull + public WebappIcon splashIcon() { + return mWebApkExtras.splashIcon; + } + + public boolean isSplashIconMaskable() { + return mWebApkExtras.isSplashIconMaskable; + } + + /** Returns data about the WebAPK's share intent handlers. */ + @NonNull + public ShareTarget shareTarget() { + return mWebApkExtras.shareTarget; + } + + /** + * Returns the WebAPK's version code. + */ + public int webApkVersionCode() { + return mWebApkExtras.webApkVersionCode; + } + + public int shellApkVersion() { + return mWebApkExtras.shellApkVersion; + } + + public String manifestUrl() { + return mWebApkExtras.manifestUrl; + } + + public String manifestStartUrl() { + return mWebApkExtras.manifestStartUrl; + } + + public @WebApkDistributor int distributor() { + return mWebApkExtras.distributor; + } + + @NonNull + public Map<String, String> iconUrlToMurmur2HashMap() { + return mWebApkExtras.iconUrlToMurmur2HashMap; + } + + public ShareData shareData() { + return mProvider.getShareData(); + } + + @NonNull + public List<ShortcutItem> shortcutItems() { + return mWebApkExtras.shortcutItems; } /** @@ -170,18 +237,24 @@ intent.putExtra(ShortcutHelper.EXTRA_ID, id()); intent.putExtra(ShortcutHelper.EXTRA_URL, url()); intent.putExtra(ShortcutHelper.EXTRA_FORCE_NAVIGATION, shouldForceNavigation()); - intent.putExtra(ShortcutHelper.EXTRA_SCOPE, scopeUrl()); - intent.putExtra(ShortcutHelper.EXTRA_ICON, icon().encoded()); - intent.putExtra(ShortcutHelper.EXTRA_VERSION, ShortcutHelper.WEBAPP_SHORTCUT_VERSION); - intent.putExtra(ShortcutHelper.EXTRA_NAME, name()); - intent.putExtra(ShortcutHelper.EXTRA_SHORT_NAME, shortName()); - intent.putExtra(ShortcutHelper.EXTRA_DISPLAY_MODE, displayMode()); - intent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, orientation()); intent.putExtra(ShortcutHelper.EXTRA_SOURCE, source()); - intent.putExtra(ShortcutHelper.EXTRA_THEME_COLOR, toolbarColor()); - intent.putExtra(ShortcutHelper.EXTRA_BACKGROUND_COLOR, backgroundColor()); - intent.putExtra(ShortcutHelper.EXTRA_IS_ICON_GENERATED, isIconGenerated()); - intent.putExtra(ShortcutHelper.EXTRA_IS_ICON_ADAPTIVE, isIconAdaptive()); + if (isForWebApk()) { + intent.putExtra(WebApkConstants.EXTRA_WEBAPK_PACKAGE_NAME, webApkPackageName()); + intent.putExtra( + WebApkConstants.EXTRA_SPLASH_PROVIDED_BY_WEBAPK, isSplashProvidedByWebApk()); + } else { + intent.putExtra(ShortcutHelper.EXTRA_SCOPE, scopeUrl()); + intent.putExtra(ShortcutHelper.EXTRA_ICON, icon().encoded()); + intent.putExtra(ShortcutHelper.EXTRA_VERSION, ShortcutHelper.WEBAPP_SHORTCUT_VERSION); + intent.putExtra(ShortcutHelper.EXTRA_NAME, name()); + intent.putExtra(ShortcutHelper.EXTRA_SHORT_NAME, shortName()); + intent.putExtra(ShortcutHelper.EXTRA_DISPLAY_MODE, displayMode()); + intent.putExtra(ShortcutHelper.EXTRA_ORIENTATION, orientation()); + intent.putExtra(ShortcutHelper.EXTRA_THEME_COLOR, toolbarColor()); + intent.putExtra(ShortcutHelper.EXTRA_BACKGROUND_COLOR, backgroundColor()); + intent.putExtra(ShortcutHelper.EXTRA_IS_ICON_GENERATED, isIconGenerated()); + intent.putExtra(ShortcutHelper.EXTRA_IS_ICON_ADAPTIVE, isIconAdaptive()); + } } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java index 75df241..1498880 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappLauncherActivity.java
@@ -65,7 +65,7 @@ private static final String TAG = "webapps"; /** Creates intent to relaunch WebAPK. */ - public static Intent createRelaunchWebApkIntent(Intent sourceIntent, WebApkInfo webApkInfo) { + public static Intent createRelaunchWebApkIntent(Intent sourceIntent, WebappInfo webApkInfo) { assert webApkInfo != null; Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(webApkInfo.url())); @@ -215,7 +215,7 @@ /** Relaunches WebAPK. */ private static void relaunchWebApk( Activity launchingActivity, Intent sourceIntent, @NonNull WebappInfo info) { - Intent launchIntent = createRelaunchWebApkIntent(sourceIntent, (WebApkInfo) info); + Intent launchIntent = createRelaunchWebApkIntent(sourceIntent, info); launchAfterDelay( launchingActivity.getApplicationContext(), launchIntent, WEBAPK_LAUNCH_DELAY_MS); ApiCompatibilityUtils.finishAndRemoveTask(launchingActivity);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java index 9f253b190..e17a3f0d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappSplashDelegate.java
@@ -77,9 +77,8 @@ splashScreen.setBackgroundColor(backgroundColor); if (mWebappInfo.isForWebApk()) { - WebApkInfo webApkInfo = (WebApkInfo) mWebappInfo; initializeWebApkInfoSplashLayout(splashScreen, backgroundColor, - webApkInfo.splashIcon().bitmap(), webApkInfo.isSplashIconMaskable()); + mWebappInfo.splashIcon().bitmap(), mWebappInfo.isSplashIconMaskable()); return splashScreen; }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/CookieControlsViewTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/CookieControlsViewTest.java index 036c3f8..159e8d7 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/CookieControlsViewTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/page_info/CookieControlsViewTest.java
@@ -17,12 +17,14 @@ import android.support.test.filters.MediumTest; import org.junit.After; +import org.junit.Assert; import org.junit.Before; import org.junit.ClassRule; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -68,6 +70,14 @@ }); } + private int getTotalPageActionHistogramCount() { + return RecordHistogram.getHistogramTotalCountForTesting("WebsiteSettings.Action"); + } + + private int getPageActionHistogramCount(@PageInfoAction int action) { + return RecordHistogram.getHistogramValueCountForTesting("WebsiteSettings.Action", action); + } + @Before public void setUp() throws InterruptedException { mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); @@ -121,17 +131,33 @@ @Test @MediumTest public void testUpdate() { + Assert.assertEquals(0, getTotalPageActionHistogramCount()); + setThirdPartyCookieBlocking(true); loadUrlAndOpenPageInfo(mTestServer.getURLWithHostName("foo.com", mPath)); + Assert.assertEquals(1, getTotalPageActionHistogramCount()); + Assert.assertEquals(1, getPageActionHistogramCount(PageInfoAction.PAGE_INFO_OPENED)); int switch_id = R.id.cookie_controls_block_cookies_switch; onView(withId(switch_id)).check(matches(isChecked())); onView(withId(switch_id)).perform(click()); onView(withId(switch_id)).check(matches(isNotChecked())); + Assert.assertEquals(2, getTotalPageActionHistogramCount()); + Assert.assertEquals( + 1, getPageActionHistogramCount(PageInfoAction.PAGE_INFO_COOKIE_ALLOWED_FOR_SITE)); + // Load a different page. loadUrlAndOpenPageInfo(mTestServer.getURLWithHostName("bar.com", mPath)); onView(withId(switch_id)).check(matches(isChecked())); + // Go back to foo.com. loadUrlAndOpenPageInfo(mTestServer.getURLWithHostName("foo.com", mPath)); onView(withId(switch_id)).check(matches(isNotChecked())); + onView(withId(switch_id)).perform(click()); + onView(withId(switch_id)).check(matches(isChecked())); + Assert.assertEquals(5, getTotalPageActionHistogramCount()); + + Assert.assertEquals( + 1, getPageActionHistogramCount(PageInfoAction.PAGE_INFO_COOKIE_BLOCKED_FOR_SITE)); + Assert.assertEquals(3, getPageActionHistogramCount(PageInfoAction.PAGE_INFO_OPENED)); } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java index 80a2fdd..5356be0 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/AndroidPaymentAppFinderTest.java
@@ -39,6 +39,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.Set; @@ -1290,9 +1291,7 @@ mockTwaAndItsInstaller("com.merchant.twa", "com.android.vending"); findApps(methods); - Assert.assertEquals("2 app should still match the query", 2, mPaymentApps.size()); - Assert.assertEquals("com.merchant.twa", mPaymentApps.get(0).getIdentifier()); - Assert.assertEquals("com.bobpay", mPaymentApps.get(1).getIdentifier()); + assertPaymentAppsHaveIdentifiers("com.merchant.twa", "com.bobpay"); } /** @@ -1507,4 +1506,23 @@ mPackageManager.setMockTrustedWebActivity(twaPackageName); mPackageManager.mockInstallerForPackage(twaPackageName, installerPackageName); } + + private void assertPaymentAppsHaveIdentifiers(String... expectedIds) { + Set<String> ids = new HashSet<>(); + for (PaymentApp app : mPaymentApps) { + ids.add(app.getIdentifier()); + } + Assert.assertEquals( + String.format(Locale.getDefault(), "Expected %d apps, but got %d apps instead.", + expectedIds.length, ids.size()), + expectedIds.length, ids.size()); + for (String expectedId : expectedIds) { + Assert.assertTrue(String.format(Locale.getDefault(), + "Expected id %s is not found. " + + "Expected identifiers: %s. " + + "Actual identifiers: %s", + expectedId, expectedIds.toString(), ids.toString()), + ids.contains(expectedId)); + } + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/WebPaymentIntentHelperTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/WebPaymentIntentHelperTest.java index d48b549..44296229 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/WebPaymentIntentHelperTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/WebPaymentIntentHelperTest.java
@@ -59,14 +59,14 @@ extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_DETAILS, "\"key\":\"value\"}"); extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_METHOD_NAME, "maxPay"); Bundle addressBundle = new Bundle(); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_COUNTRY, "Canada"); + addressBundle.putString(Address.EXTRA_ADDRESS_COUNTRY, "Canada"); String[] addressLine = {"111 Richmond Street West"}; - addressBundle.putStringArray(WebPaymentIntentHelper.EXTRA_ADDRESS_LINES, addressLine); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_REGION, "Ontario"); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_CITY, "Toronto"); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_POSTAL_CODE, "M5H2G4"); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_RECIPIENT, "John Smith"); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_PHONE, "4169158200"); + addressBundle.putStringArray(Address.EXTRA_ADDRESS_LINES, addressLine); + addressBundle.putString(Address.EXTRA_ADDRESS_REGION, "Ontario"); + addressBundle.putString(Address.EXTRA_ADDRESS_CITY, "Toronto"); + addressBundle.putString(Address.EXTRA_ADDRESS_POSTAL_CODE, "M5H2G4"); + addressBundle.putString(Address.EXTRA_ADDRESS_RECIPIENT, "John Smith"); + addressBundle.putString(Address.EXTRA_ADDRESS_PHONE, "4169158200"); extras.putBundle(WebPaymentIntentHelper.EXTRA_SHIPPING_ADDRESS, addressBundle); extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_PAYER_NAME, "John Smith"); extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_PAYER_PHONE, "4169158200"); @@ -743,14 +743,14 @@ extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_DETAILS, "\"key\":\"value\"}"); extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_METHOD_NAME, "maxPay"); Bundle addressBundle = new Bundle(); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_COUNTRY, "Canada"); + addressBundle.putString(Address.EXTRA_ADDRESS_COUNTRY, "Canada"); String[] addressLine = {"111 Richmond Street West"}; - addressBundle.putStringArray(WebPaymentIntentHelper.EXTRA_ADDRESS_LINES, addressLine); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_REGION, "Ontario"); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_CITY, "Toronto"); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_POSTAL_CODE, "M5H2G4"); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_RECIPIENT, "John Smith"); - addressBundle.putString(WebPaymentIntentHelper.EXTRA_ADDRESS_PHONE, "4169158200"); + addressBundle.putStringArray(Address.EXTRA_ADDRESS_LINES, addressLine); + addressBundle.putString(Address.EXTRA_ADDRESS_REGION, "Ontario"); + addressBundle.putString(Address.EXTRA_ADDRESS_CITY, "Toronto"); + addressBundle.putString(Address.EXTRA_ADDRESS_POSTAL_CODE, "M5H2G4"); + addressBundle.putString(Address.EXTRA_ADDRESS_RECIPIENT, "John Smith"); + addressBundle.putString(Address.EXTRA_ADDRESS_PHONE, "4169158200"); extras.putBundle(WebPaymentIntentHelper.EXTRA_SHIPPING_ADDRESS, addressBundle); extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_PAYER_NAME, "John Smith"); extras.putString(WebPaymentIntentHelper.EXTRA_RESPONSE_PAYER_PHONE, "4169158200");
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkInitializationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkInitializationTest.java index 84eca9e..f61455b 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkInitializationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/webapps/WebApkInitializationTest.java
@@ -17,6 +17,7 @@ import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.customtabs.CustomTabOrientationController; import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule; import org.chromium.chrome.browser.dependency_injection.ModuleOverridesRule; import org.chromium.chrome.browser.flags.ChromeSwitches; @@ -97,8 +98,9 @@ /** * Test that {@link WebappActionsNotificationManager}, - * {@link WebappDisclosureSnackbarController} and {@link WebApkActivityLifecycleUmaTracker} are - * constructed when a WebAPK Activity is launched. + * {@link WebappDisclosureSnackbarController}, {@link WebApkActivityLifecycleUmaTracker} and + * {@link CustomTabOrientationController} are constructed when a {@link WebApkActivity} is + * launched. */ @Test @LargeTest @@ -119,6 +121,8 @@ WebappDisclosureSnackbarController.class.getName())); assertTrue(registeredObserverClassNames.contains( WebApkActivityLifecycleUmaTracker.class.getName())); + assertTrue(registeredObserverClassNames.contains( + CustomTabOrientationController.class.getName())); // Test that WebappActiveTabUmaTracker is hooked up. assertTrue(0 < RecordHistogram.getHistogramTotalCountForTesting(
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 45fe507..32541cb 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -864,15 +864,9 @@ <message name="IDS_LOGIN_RECOMMEND_APPS_INSTALL" desc="The label on the button that installs the user selected apps"> Install & continue </message> - <message name="IDS_LOGIN_RECOMMEND_APPS_RETRY" desc="The label on the button that tries to load the app list again"> - Retry - </message> <message name="IDS_LOGIN_RECOMMEND_APPS_SCREEN_LOADING" desc="Message shown while the recommended app list is being downloaded."> Please wait... </message> - <message name="IDS_LOGIN_RECOMMEND_APPS_SCREEN_ERROR" desc="Load error message of the Recommend Apps OOBE dialog."> - The list of apps cannot be loaded. Please retry. - </message> <message name="IDS_LOGIN_APP_DOWNLOADING_SCREEN_TITLE_SINGULAR" desc="The title of the dialog that tells the user the selected Android App is downloading."> We'll install that app for you </message>
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 2b49f07..0a825de 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -2506,20 +2506,6 @@ </message> </if> - <!-- Web Share Target picker dialog --> - <message name="IDS_WEBSHARE_TARGET_PICKER_TITLE" desc="Title of the dialog to choose a target for sharing."> - Share via - </message> - <message name="IDS_WEBSHARE_TARGET_PICKER_LABEL" desc="Text of the main label in the dialog to choose a target for sharing."> - Choose an app to share to: - </message> - <message name="IDS_WEBSHARE_TARGET_PICKER_COMMIT" desc="Title of the button to share content to the chosen application."> - Share - </message> - <message name="IDS_WEBSHARE_TARGET_DIALOG_ITEM_TEXT" desc="Text for a Web Share Target item in the Web Share Target dialog."> - <ph name="APP_NAME">$1<ex>Google Maps</ex></ph> (<ph name="APP_URL">$2<ex>https://google.com/maps</ex></ph>) - </message> - <!-- Content blocking strings --> <message name="IDS_MANAGE" desc="Text for a button on permission bubbles, which opens a more detailed content settings page where users can manage that particular setting."> Manage @@ -10028,12 +10014,6 @@ <message name="IDS_WEBAUTHN_GENERIC_TITLE" desc="Title of most dialogs shown while the user is authenticating on a web site using a security key."> Use your security key with <ph name="APP_NAME">$1<ex>google.com</ex></ph> </message> - <message name="IDS_WEBAUTHN_WELCOME_SCREEN_TITLE" desc="Title of the dialog shown the very first time the user wants to authenticate on a web site using a security key."> - <ph name="APP_NAME">$1<ex>google.com</ex></ph> wants to verify your identity - </message> - <message name="IDS_WEBAUTHN_WELCOME_SCREEN_DESCRIPTION" desc="Description in the dialog shown the very first time the user wants to authenticate on a web site using a security key."> - Verifying your identity helps protect your personal information - </message> <message name="IDS_WEBAUTHN_WELCOME_SCREEN_NEXT" desc="Button text to continue using a security key for authentication on the web for the very first time."> Continue </message> @@ -10266,12 +10246,6 @@ </message> <!-- WebAuthn account selection for resident keys --> - <message name="IDS_WEBAUTHN_ACCOUNT_COLUMN" desc="The title of a column in a table under which will be a list of usernames or email addresses, e.g. joe@gmail.com."> - Account - </message> - <message name="IDS_WEBAUTHN_NAME_COLUMN" desc="The title of a column in a table under which will be a list of names on accounts, i.e. names of people. For example, Joe Smith."> - Name - </message> <message name="IDS_WEBAUTHN_SELECT_ACCOUNT" desc="The title on a dialog where the user is expected to select an account from a list. For example, the list may include several identities, e.g. joe@gmail.com, mary@gmail.com, and the user has to select one to login as."> Select an account to sign in </message>
diff --git a/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.cc b/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.cc index 946f8c3..a4d6b29 100644 --- a/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.cc +++ b/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.cc
@@ -38,39 +38,16 @@ void AssistantCollectUserDataDelegate::OnContactInfoChanged( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller, - const base::android::JavaParamRef<jstring>& jpayer_name, - const base::android::JavaParamRef<jstring>& jpayer_phone, - const base::android::JavaParamRef<jstring>& jpayer_email) { - if (!jpayer_name && !jpayer_phone && !jpayer_email) { + const base::android::JavaParamRef<jobject>& jcontact_profile) { + if (!jcontact_profile) { ui_controller_->OnContactInfoChanged(nullptr); return; } - std::string name = ui_controller_android_utils::SafeConvertJavaStringToNative( - env, jpayer_name); - std::string phone = - ui_controller_android_utils::SafeConvertJavaStringToNative(env, - jpayer_phone); - std::string email = - ui_controller_android_utils::SafeConvertJavaStringToNative(env, - jpayer_email); - auto contact_profile = std::make_unique<autofill::AutofillProfile>(); - contact_profile->SetRawInfo(autofill::ServerFieldType::NAME_FULL, - base::UTF8ToUTF16(name)); - autofill::data_util::NameParts parts = - autofill::data_util::SplitName(base::UTF8ToUTF16(name)); - contact_profile->SetRawInfo(autofill::ServerFieldType::NAME_FIRST, - parts.given); - contact_profile->SetRawInfo(autofill::ServerFieldType::NAME_MIDDLE, - parts.middle); - contact_profile->SetRawInfo(autofill::ServerFieldType::NAME_LAST, - parts.family); - contact_profile->SetRawInfo(autofill::ServerFieldType::EMAIL_ADDRESS, - base::UTF8ToUTF16(email)); - contact_profile->SetRawInfo( - autofill::ServerFieldType::PHONE_HOME_WHOLE_NUMBER, - base::UTF8ToUTF16(phone)); + autofill::PersonalDataManagerAndroid::PopulateNativeProfileFromJava( + jcontact_profile, env, contact_profile.get()); + ui_controller_->OnContactInfoChanged(std::move(contact_profile)); }
diff --git a/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.h b/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.h index 4f682ef..8dc3abe94 100644 --- a/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.h +++ b/chrome/browser/android/autofill_assistant/assistant_collect_user_data_delegate.h
@@ -18,9 +18,7 @@ void OnContactInfoChanged( JNIEnv* env, const base::android::JavaParamRef<jobject>& jcaller, - const base::android::JavaParamRef<jstring>& jpayer_name, - const base::android::JavaParamRef<jstring>& jpayer_phone, - const base::android::JavaParamRef<jstring>& jpayer_email); + const base::android::JavaParamRef<jobject>& jcontact_profile); void OnShippingAddressChanged( JNIEnv* env,
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index 1d84022..6c39819c 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -311,6 +311,7 @@ KeepAliveRegistry::GetInstance()->AddObserver(this); #endif // !defined(OS_ANDROID) + MigrateObsoleteLocalStatePrefs(local_state()); pref_change_registrar_.Init(local_state()); // Initialize the notification for the default browser setting policy.
diff --git a/chrome/browser/chrome_back_forward_cache_browsertest.cc b/chrome/browser/chrome_back_forward_cache_browsertest.cc index aa23d155..73dbf1c8 100644 --- a/chrome/browser/chrome_back_forward_cache_browsertest.cc +++ b/chrome/browser/chrome_back_forward_cache_browsertest.cc
@@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/auto_reset.h" #include "base/command_line.h" #include "base/macros.h" #include "base/test/mock_callback.h" @@ -10,18 +9,15 @@ #include "build/build_config.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/permissions/permission_manager_factory.h" -#include "chrome/browser/printing/print_view_manager_common.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" -#include "chrome/browser/ui/webui/print_preview/print_preview_ui.h" #include "chrome/test/base/in_process_browser_test.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_types.h" #include "components/network_session_configurator/common/network_switches.h" #include "components/permissions/permission_manager.h" -#include "components/printing/common/print.mojom.h" #include "content/public/browser/render_process_host.h" #include "content/public/common/content_features.h" #include "content/public/common/content_switches.h" @@ -32,7 +28,6 @@ #include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "net/dns/mock_host_resolver.h" #include "net/test/embedded_test_server/embedded_test_server.h" -#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/mojom/webshare/webshare.mojom.h" class ChromeBackForwardCacheBrowserTest : public InProcessBrowserTest { @@ -247,120 +242,6 @@ delete_observer_rfh_a.WaitUntilDeleted(); } -class PrintPreviewObserver : printing::PrintPreviewUI::TestDelegate { - public: - explicit PrintPreviewObserver(bool wait_for_loaded) { - if (wait_for_loaded) - queue_.emplace(); // DOMMessageQueue doesn't allow assignment - printing::PrintPreviewUI::SetDelegateForTesting(this); - } - - ~PrintPreviewObserver() override { - printing::PrintPreviewUI::SetDelegateForTesting(nullptr); - } - - void WaitUntilPreviewIsReady() { - if (rendered_page_count_ >= total_page_count_) - return; - - base::RunLoop run_loop; - base::AutoReset<base::RunLoop*> auto_reset(&run_loop_, &run_loop); - run_loop.Run(); - - if (queue_.has_value()) { - std::string message; - EXPECT_TRUE(queue_->WaitForMessage(&message)); - EXPECT_EQ("\"success\"", message); - } - } - - private: - // PrintPreviewUI::TestDelegate: - void DidGetPreviewPageCount(int page_count) override { - total_page_count_ = page_count; - } - - // PrintPreviewUI::TestDelegate: - void DidRenderPreviewPage(content::WebContents* preview_dialog) override { - ++rendered_page_count_; - CHECK(rendered_page_count_ <= total_page_count_); - if (rendered_page_count_ == total_page_count_ && run_loop_) { - run_loop_->Quit(); - - if (queue_.has_value()) { - content::ExecuteScriptAsync( - preview_dialog, - "window.addEventListener('message', event => {" - " if (event.data.type === 'documentLoaded') {" - " domAutomationController.send(event.data.load_state);" - " }" - "});"); - } - } - } - - base::Optional<content::DOMMessageQueue> queue_; - int total_page_count_ = 1; - int rendered_page_count_ = 0; - base::RunLoop* run_loop_ = nullptr; - - DISALLOW_COPY_AND_ASSIGN(PrintPreviewObserver); -}; - -class ChromeBackForwardCacheBrowserTestWithPrinting - : public ChromeBackForwardCacheBrowserTest { - public: - ChromeBackForwardCacheBrowserTestWithPrinting() = default; - ~ChromeBackForwardCacheBrowserTestWithPrinting() override = default; - - void PrintAndWaitUntilPreviewIsReady(bool print_only_selection) { - PrintPreviewObserver print_preview_observer(/*wait_for_loaded=*/true); - printing::StartPrint(browser()->tab_strip_model()->GetActiveWebContents(), - /*print_renderer=*/mojo::NullAssociatedRemote(), - /*print_preview_disabled=*/false, - print_only_selection); - print_preview_observer.WaitUntilPreviewIsReady(); - } - - void WaitUntilMessagesReceived() { - run_loop_ = std::make_unique<base::RunLoop>(); - run_loop_->Run(); - } - - static mojo::AssociatedRemote<printing::mojom::PrintRenderFrame> - GetPrintRenderFrame(content::RenderFrameHost* rfh) { - mojo::AssociatedRemote<printing::mojom::PrintRenderFrame> remote; - rfh->GetRemoteAssociatedInterfaces()->GetInterface(&remote); - return remote; - } - - private: - std::unique_ptr<base::RunLoop> run_loop_; -}; - -IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTestWithPrinting, - DoesNotCacheIfPrinting) { - ASSERT_TRUE(embedded_test_server()->Start()); - - // 1) Navigate to A. - EXPECT_TRUE(content::NavigateToURL( - web_contents(), embedded_test_server()->GetURL("/printing/test1.html"))); - content::RenderFrameHost* rfh_a = current_frame_host(); - content::RenderFrameDeletedObserver delete_observer_rfh_a(rfh_a); - PrintAndWaitUntilPreviewIsReady(/*print_only_selection=*/false); - - // 2) Navigate to B. - EXPECT_TRUE(content::NavigateToURL(web_contents(), GetURL("b.com"))); - content::RenderFrameHost* rfh_b = current_frame_host(); - content::RenderFrameDeletedObserver delete_observer_rfh_b(rfh_b); - // A is not cached because of printing. - EXPECT_TRUE(delete_observer_rfh_a.deleted()); - - // 3) Navigate back. - web_contents()->GetController().GoBack(); - EXPECT_TRUE(content::WaitForLoadStop(web_contents())); -} - #if defined(OS_ANDROID) IN_PROC_BROWSER_TEST_F(ChromeBackForwardCacheBrowserTest, DoesNotCacheIfWebShare) {
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index 2cdc9273..16a3e9fe 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -2207,8 +2207,6 @@ "release_notes/release_notes_storage.cc", "release_notes/release_notes_storage.h", "reset/metrics.h", - "resource_reporter/resource_reporter.cc", - "resource_reporter/resource_reporter.h", "scheduler_configuration_manager.cc", "scheduler_configuration_manager.h", "secure_channel/secure_channel_client_provider.cc", @@ -3132,7 +3130,6 @@ "proxy_config_service_impl_unittest.cc", "release_notes/release_notes_notification_unittest.cc", "release_notes/release_notes_storage_unittest.cc", - "resource_reporter/resource_reporter_unittest.cc", "scheduler_configuration_manager_unittest.cc", "session_length_limiter_unittest.cc", "settings/cros_settings_unittest.cc",
diff --git a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc index 8238225..621c59e 100644 --- a/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc +++ b/chrome/browser/chromeos/accessibility/spoken_feedback_browsertest.cc
@@ -529,6 +529,12 @@ // Press Search+/ to enter ChromeVox's "find in page". sm_.Call([this]() { SendKeyPressWithSearch(ui::VKEY_OEM_2); }); sm_.ExpectSpeech("Find in page"); + sm_.ExpectSpeech("Search"); + sm_.ExpectSpeech( + "Type to search the page. Press enter to jump to the result, up or down " + "arrows to browse results, keep typing to change your search, or escape " + "to cancel."); + sm_.Replay(); }
diff --git a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc index 0e5f6f7..895aa01f 100644 --- a/chrome/browser/chromeos/chrome_browser_main_chromeos.cc +++ b/chrome/browser/chromeos/chrome_browser_main_chromeos.cc
@@ -107,7 +107,6 @@ #include "chrome/browser/chromeos/power/smart_charging/smart_charging_manager.h" #include "chrome/browser/chromeos/printing/bulk_printers_calculator_factory.h" #include "chrome/browser/chromeos/profiles/profile_helper.h" -#include "chrome/browser/chromeos/resource_reporter/resource_reporter.h" #include "chrome/browser/chromeos/scheduler_configuration_manager.h" #include "chrome/browser/chromeos/settings/device_settings_service.h" #include "chrome/browser/chromeos/settings/shutdown_policy_forwarder.h" @@ -578,9 +577,6 @@ network_throttling_observer_.reset( new NetworkThrottlingObserver(g_browser_process->local_state())); - ResourceReporter::GetInstance()->StartMonitoring( - task_manager::TaskManagerInterface::GetTaskManager()); - discover_manager_ = std::make_unique<DiscoverManager>(); g_browser_process->platform_part()->InitializeSchedulerConfigurationManager(); @@ -1005,8 +1001,6 @@ void ChromeBrowserMainPartsChromeos::PostMainMessageLoopRun() { crostini_unsupported_action_notifier_.reset(); - ResourceReporter::GetInstance()->StopMonitoring(); - BootTimesRecorder::Get()->AddLogoutTimeMarker("UIMessageLoopEnded", true); if (lock_screen_apps_state_controller_)
diff --git a/chrome/browser/chromeos/login/eula_browsertest.cc b/chrome/browser/chromeos/login/eula_browsertest.cc index 923ecc05..9d6ef2f 100644 --- a/chrome/browser/chromeos/login/eula_browsertest.cc +++ b/chrome/browser/chromeos/login/eula_browsertest.cc
@@ -15,6 +15,7 @@ #include "base/strings/stringprintf.h" #include "base/task/post_task.h" #include "base/test/bind_test_util.h" +#include "base/test/metrics/histogram_tester.h" #include "build/branding_buildflags.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/login/test/dialog_window_waiter.h" @@ -43,12 +44,14 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" +#include "testing/gmock/include/gmock/gmock.h" #include "ui/base/l10n/l10n_util.h" #include "url/gurl.h" using net::test_server::BasicHttpResponse; using net::test_server::HttpRequest; using net::test_server::HttpResponse; +using ::testing::ElementsAre; namespace chromeos { namespace { @@ -302,6 +305,7 @@ // Tests that clicking on "System security settings" button opens a dialog // showing the TPM password. IN_PROC_BROWSER_TEST_F(EulaTest, DisplaysTpmPassword) { + base::HistogramTester histogram_tester; ShowEulaScreen(); NonPolymerOobeJS().TapOnPath({"oobe-eula-md", "installationSettings"}); @@ -315,12 +319,16 @@ test::OobeJS().ExpectEQ( "$('oobe-eula-md').$$('#eula-password').textContent.trim()", std::string(FakeCryptohomeClient::kStubTpmPassword)); + EXPECT_THAT( + histogram_tester.GetAllSamples("OOBE.EulaScreen.UserActions"), + ElementsAre(base::Bucket( + static_cast<int>(EulaScreen::UserAction::kShowSecuritySettings), 1))); } // Verifies statistic collection accepted flow. // Advaces to the next screen and verifies stats collection is enabled. -// Flaky on LSAN/ASAN: crbug.com/952482. IN_PROC_BROWSER_TEST_F(EulaTest, EnableUsageStats) { + base::HistogramTester histogram_tester; ShowEulaScreen(); // Verify that toggle is enabled by default. @@ -340,6 +348,9 @@ auto subscription = StatsReportingController::Get()->AddObserver(runloop.QuitClosure()); + // Enable and disable usageStats that to see that metrics are recorded. + NonPolymerOobeJS().TapOnPath({"oobe-eula-md", "usageStats"}); + NonPolymerOobeJS().TapOnPath({"oobe-eula-md", "usageStats"}); // Advance to the next screen for changes to take effect. test::OobeJS().TapOnPath({"oobe-eula-md", "acceptButton"}); @@ -351,11 +362,22 @@ EXPECT_TRUE(g_browser_process->local_state()->GetBoolean( metrics::prefs::kMetricsReportingEnabled)); EXPECT_TRUE(GetGoogleCollectStatsConsent()); + EXPECT_THAT( + histogram_tester.GetAllSamples("OOBE.EulaScreen.UserActions"), + ElementsAre( + base::Bucket( + static_cast<int>(EulaScreen::UserAction::kAcceptButtonClicked), + 1), + base::Bucket( + static_cast<int>(EulaScreen::UserAction::kUnselectStatsUsage), 1), + base::Bucket( + static_cast<int>(EulaScreen::UserAction::kSelectStatsUsage), 1))); } // Verify statistic collection denied flow. Clicks on usage stats toggle, // advaces to the next screen and verifies stats collection is disabled. IN_PROC_BROWSER_TEST_F(EulaTest, DisableUsageStats) { + base::HistogramTester histogram_tester; ShowEulaScreen(); // Verify that toggle is enabled by default. @@ -388,10 +410,20 @@ EXPECT_FALSE(g_browser_process->local_state()->GetBoolean( metrics::prefs::kMetricsReportingEnabled)); EXPECT_FALSE(GetGoogleCollectStatsConsent()); + EXPECT_THAT( + histogram_tester.GetAllSamples("OOBE.EulaScreen.UserActions"), + ElementsAre( + base::Bucket( + static_cast<int>(EulaScreen::UserAction::kAcceptButtonClicked), + 1), + base::Bucket( + static_cast<int>(EulaScreen::UserAction::kUnselectStatsUsage), + 1))); } // Tests that clicking on "Learn more" button opens a help dialog. IN_PROC_BROWSER_TEST_F(EulaTest, LearnMore) { + base::HistogramTester histogram_tester; ShowEulaScreen(); // Load HelperApp extension. @@ -405,6 +437,38 @@ // Wait until help dialog is displayed. waiter.Wait(); + EXPECT_THAT( + histogram_tester.GetAllSamples("OOBE.EulaScreen.UserActions"), + ElementsAre(base::Bucket( + static_cast<int>(EulaScreen::UserAction::kShowStatsUsageLearnMore), + 1))); +} + +// Tests that "Additional ToS" dialog could be opened and closed. +IN_PROC_BROWSER_TEST_F(EulaTest, AdditionalToS) { + base::HistogramTester histogram_tester; + ShowEulaScreen(); + + NonPolymerOobeJS().TapOnPath({"oobe-eula-md", "additionalTerms"}); + + test::OobeJS() + .CreateWaiter( + test::GetOobeElementPath({"oobe-eula-md", "additional-tos"}) + + ".open") + ->Wait(); + + NonPolymerOobeJS().TapOnPath({"oobe-eula-md", "close-additional-tos"}); + + test::OobeJS() + .CreateWaiter( + test::GetOobeElementPath({"oobe-eula-md", "additional-tos"}) + + ".open === false") + ->Wait(); + + EXPECT_THAT( + histogram_tester.GetAllSamples("OOBE.EulaScreen.UserActions"), + ElementsAre(base::Bucket( + static_cast<int>(EulaScreen::UserAction::kShowAdditionalTos), 1))); } } // namespace
diff --git a/chrome/browser/chromeos/login/oobe_browsertest.cc b/chrome/browser/chromeos/login/oobe_browsertest.cc index 2d2b6a919..1ce1cbcd 100644 --- a/chrome/browser/chromeos/login/oobe_browsertest.cc +++ b/chrome/browser/chromeos/login/oobe_browsertest.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/ui/webui/signin/signin_utils.h" #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" -#include "chromeos/constants/chromeos_features.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" #include "chromeos/dbus/cryptohome/key.pb.h" @@ -126,141 +125,4 @@ OobeScreenWaiter(EnrollmentScreenView::kScreenId).Wait(); } -class GaiaActionButtonsTest : public OobeBaseTest { - public: - GaiaActionButtonsTest() = default; - ~GaiaActionButtonsTest() override = default; - - void SetUp() override { - scoped_feature_list_.InitAndEnableFeature(features::kGaiaActionButtons); - OobeBaseTest::SetUp(); - } - - void WaitForPageLoad() { - WaitForGaiaPageLoad(); - // Also wait for the javascript page to load - GaiaJSChecker().CreateWaiter("gaia.chromeOSLogin.initialized_")->Wait(); - } - - // A JSChecker for the GAIA Webview - test::JSChecker GaiaJSChecker() { return SigninFrameJS(); } - - // A JSChecker for the Oobe screen - test::JSChecker OobeJSChecker() const { return test::OobeJS(); } - - void ExpectHidden(const std::string& button) const { - OobeJSChecker() - .CreateVisibilityWaiter(false, {module_name, button}) - ->Wait(); - } - - void ExpectVisible(const std::string& button) const { - OobeJSChecker().CreateVisibilityWaiter(true, {module_name, button})->Wait(); - } - - void ExpectEnabled(const std::string& button) const { - OobeJSChecker().CreateEnabledWaiter(true, {module_name, button})->Wait(); - } - - void ExpectDisabled(const std::string& button) const { - OobeJSChecker().CreateEnabledWaiter(false, {module_name, button})->Wait(); - } - - void ExpectLabel(const std::string& button, const std::string& label) const { - ASSERT_EQ(GetLabel(button), label); - } - - std::string GetLabel(const std::string& button) const { - const std::string js_path = - chromeos::test::GetOobeElementPath({module_name, button}); - return test::OobeJS().GetString(js_path + ".innerText"); - } - - void EnablePrimaryButton() { - GaiaJSChecker().Evaluate("sendSetPrimaryActionLabel('label')"); - GaiaJSChecker().Evaluate("sendSetPrimaryActionEnabled(true)"); - } - - private: - FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()}; - base::test::ScopedFeatureList scoped_feature_list_{}; - const char* module_name = "gaia-signin"; - - DISALLOW_COPY_AND_ASSIGN(GaiaActionButtonsTest); -}; - -IN_PROC_BROWSER_TEST_F(GaiaActionButtonsTest, PrimaryActionButtonLabel) { - WaitForPageLoad(); - - // Initially the button is hidden - ExpectHidden("primary-action-button"); - - // It is shown when the label is set - GaiaJSChecker().Evaluate("sendSetPrimaryActionLabel('the-label')"); - ExpectVisible("primary-action-button"); - ExpectLabel("primary-action-button", "the-label"); - - // It is hidden when the label is set to nill - GaiaJSChecker().Evaluate("sendSetPrimaryActionLabel(null)"); - ExpectHidden("primary-action-button"); -} - -IN_PROC_BROWSER_TEST_F(GaiaActionButtonsTest, PrimaryActionButtonEnabled) { - WaitForPageLoad(); - - // Initially the button is enabled - ExpectEnabled("primary-action-button"); - - // It can be disabled - GaiaJSChecker().Evaluate("sendSetPrimaryActionEnabled(false)"); - ExpectDisabled("primary-action-button"); - - // It can be enabled - GaiaJSChecker().Evaluate("sendSetPrimaryActionEnabled(true)"); - ExpectEnabled("primary-action-button"); -} - -IN_PROC_BROWSER_TEST_F(GaiaActionButtonsTest, SecondaryActionButtonLabel) { - WaitForPageLoad(); - - // Initially the button is hidden - ExpectHidden("secondary-action-button"); - - // It is shown when the label is set - GaiaJSChecker().Evaluate("sendSetSecondaryActionLabel('the-label')"); - ExpectVisible("secondary-action-button"); - ExpectLabel("secondary-action-button", "the-label"); - - // It is hidden when the label is set to nill - GaiaJSChecker().Evaluate("sendSetSecondaryActionLabel(null)"); - ExpectHidden("secondary-action-button"); -} - -IN_PROC_BROWSER_TEST_F(GaiaActionButtonsTest, SecondaryActionButtonEnabled) { - WaitForPageLoad(); - - // Initially the button is enabled - ExpectEnabled("secondary-action-button"); - - // It can be disabled - GaiaJSChecker().Evaluate("sendSetSecondaryActionEnabled(false)"); - ExpectDisabled("secondary-action-button"); - - // It can be enabled - GaiaJSChecker().Evaluate("sendSetSecondaryActionEnabled(true)"); - ExpectEnabled("secondary-action-button"); -} - -IN_PROC_BROWSER_TEST_F(GaiaActionButtonsTest, SetAllActionsEnabled) { - WaitForPageLoad(); - - GaiaJSChecker().Evaluate("sendSetAllActionsEnabled(false)"); - ExpectDisabled("primary-action-button"); - ExpectDisabled("secondary-action-button"); - - GaiaJSChecker().Evaluate("sendSetAllActionsEnabled(true)"); - ExpectEnabled("primary-action-button"); - ExpectEnabled("secondary-action-button"); -} - } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/screens/eula_screen.cc b/chrome/browser/chromeos/login/screens/eula_screen.cc index ed4c199..cdf298b 100644 --- a/chrome/browser/chromeos/login/screens/eula_screen.cc +++ b/chrome/browser/chromeos/login/screens/eula_screen.cc
@@ -7,6 +7,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/logging.h" +#include "base/metrics/histogram_functions.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/customization/customization_document.h" #include "chrome/browser/chromeos/login/wizard_controller.h" @@ -20,6 +21,54 @@ constexpr const char kUserActionAcceptButtonClicked[] = "accept-button"; constexpr const char kUserActionBackButtonClicked[] = "back-button"; +constexpr const char kUserActionShowAdditionalTos[] = "show-additional-tos"; +constexpr const char kUserActionShowSecuritySettings[] = + "show-security-settings"; +constexpr const char kUserActionShowStatsUsageLearnMore[] = + "show-stats-usage-learn-more"; +constexpr const char kUserActionUnselectStatsUsage[] = "unselect-stats-usage"; +constexpr const char kUserActionSelectStatsUsage[] = "select-stats-usage"; + +struct EulaUserAction { + const char* name_; + EulaScreen::UserAction uma_name_; +}; + +const EulaUserAction actions[] = { + {kUserActionAcceptButtonClicked, + EulaScreen::UserAction::kAcceptButtonClicked}, + {kUserActionBackButtonClicked, EulaScreen::UserAction::kBackButtonClicked}, + {kUserActionShowAdditionalTos, EulaScreen::UserAction::kShowAdditionalTos}, + {kUserActionShowSecuritySettings, + EulaScreen::UserAction::kShowSecuritySettings}, + {kUserActionShowStatsUsageLearnMore, + EulaScreen::UserAction::kShowStatsUsageLearnMore}, + {kUserActionUnselectStatsUsage, + EulaScreen::UserAction::kUnselectStatsUsage}, + {kUserActionSelectStatsUsage, EulaScreen::UserAction::kSelectStatsUsage}, +}; + +void RecordEulaScreenAction(EulaScreen::UserAction value) { + base::UmaHistogramEnumeration("OOBE.EulaScreen.UserActions", value); +} + +bool IsEulaUserAction(const std::string& action_id) { + for (const auto& el : actions) { + if (action_id == el.name_) + return true; + } + return false; +} + +void RecordUserAction(const std::string& action_id) { + for (const auto& el : actions) { + if (action_id == el.name_) { + RecordEulaScreenAction(el.uma_name_); + return; + } + } + NOTREACHED() << "Unexpected action id: " << action_id; +} // Reflects the value of usage statistics reporting checkbox shown in eula // UI. The value is expected to survive EulaScreen res-hows within a single @@ -93,14 +142,17 @@ } void EulaScreen::OnUserAction(const std::string& action_id) { + if (!IsEulaUserAction(action_id)) { + BaseScreen::OnUserAction(action_id); + return; + } + RecordUserAction(action_id); if (action_id == kUserActionAcceptButtonClicked) { exit_callback_.Run(g_usage_statistics_reporting_enabled ? Result::ACCEPTED_WITH_USAGE_STATS_REPORTING : Result::ACCEPTED_WITHOUT_USAGE_STATS_REPORTING); } else if (action_id == kUserActionBackButtonClicked) { exit_callback_.Run(Result::BACK); - } else { - BaseScreen::OnUserAction(action_id); } }
diff --git a/chrome/browser/chromeos/login/screens/eula_screen.h b/chrome/browser/chromeos/login/screens/eula_screen.h index c518dc3..6af145a5 100644 --- a/chrome/browser/chromeos/login/screens/eula_screen.h +++ b/chrome/browser/chromeos/login/screens/eula_screen.h
@@ -31,6 +31,21 @@ BACK }; + // This enum is tied directly to a UMA enum defined in + // //tools/metrics/histograms/enums.xml, and should always reflect it (do not + // change one without changing the other). Entries should be never modified + // or deleted. Only additions possible. + enum class UserAction { + kAcceptButtonClicked = 0, + kBackButtonClicked = 1, + kShowAdditionalTos = 2, + kShowSecuritySettings = 3, + kShowStatsUsageLearnMore = 4, + kUnselectStatsUsage = 5, + kSelectStatsUsage = 6, + kMaxValue = kSelectStatsUsage + }; + static std::string GetResultString(Result result); using ScreenExitCallback = base::RepeatingCallback<void(Result result)>;
diff --git a/chrome/browser/chromeos/login/screens/recommend_apps_screen.cc b/chrome/browser/chromeos/login/screens/recommend_apps_screen.cc index 11369db..90d69211 100644 --- a/chrome/browser/chromeos/login/screens/recommend_apps_screen.cc +++ b/chrome/browser/chromeos/login/screens/recommend_apps_screen.cc
@@ -19,6 +19,8 @@ return "Selected"; case Result::SKIPPED: return "Skipped"; + case Result::LOAD_ERROR: + return "LoadError"; case Result::NOT_APPLICABLE: return BaseScreen::kNotApplicable; } @@ -45,10 +47,6 @@ exit_callback_.Run(Result::SKIPPED); } -void RecommendAppsScreen::OnRetry() { - recommend_apps_fetcher_->Retry(); -} - void RecommendAppsScreen::OnInstall() { exit_callback_.Run(Result::SELECTED); } @@ -90,8 +88,7 @@ } void RecommendAppsScreen::OnLoadError() { - if (view_) - view_->OnLoadError(); + exit_callback_.Run(Result::LOAD_ERROR); } void RecommendAppsScreen::OnParseResponseError() {
diff --git a/chrome/browser/chromeos/login/screens/recommend_apps_screen.h b/chrome/browser/chromeos/login/screens/recommend_apps_screen.h index 759c37a..b18bf72 100644 --- a/chrome/browser/chromeos/login/screens/recommend_apps_screen.h +++ b/chrome/browser/chromeos/login/screens/recommend_apps_screen.h
@@ -27,7 +27,7 @@ class RecommendAppsScreen : public BaseScreen, public RecommendAppsFetcherDelegate { public: - enum class Result { SELECTED, SKIPPED, NOT_APPLICABLE }; + enum class Result { SELECTED, SKIPPED, NOT_APPLICABLE, LOAD_ERROR }; static std::string GetResultString(Result result);
diff --git a/chrome/browser/chromeos/login/screens/recommend_apps_screen_browsertest.cc b/chrome/browser/chromeos/login/screens/recommend_apps_screen_browsertest.cc index 187ab9b4..3423df0 100644 --- a/chrome/browser/chromeos/login/screens/recommend_apps_screen_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/recommend_apps_screen_browsertest.cc
@@ -271,9 +271,6 @@ "recommend-apps-screen", "recommend-apps-install-button"}; const std::initializer_list<base::StringPiece> skip_button = { "recommend-apps-screen", "recommend-apps-skip-button"}; - const std::initializer_list<base::StringPiece> retry_button = { - "recommend-apps-screen", "recommend-apps-retry-button"}; - test::OobeJS().ExpectDisabledPath(install_button); test::OobeJS() @@ -285,14 +282,12 @@ test::OobeJS().ExpectDisabledPath(install_button); test::OobeJS().ExpectPathDisplayed(true, skip_button); test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); ASSERT_TRUE(ToggleAppsSelection( webview_path, "['test.app.foo.app1', 'test.app.foo.app2']")); test::OobeJS().CreateEnabledWaiter(true, install_button)->Wait(); test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); test::OobeJS().TapOnPath(install_button); @@ -342,8 +337,6 @@ "recommend-apps-screen", "recommend-apps-install-button"}; const std::initializer_list<base::StringPiece> skip_button = { "recommend-apps-screen", "recommend-apps-skip-button"}; - const std::initializer_list<base::StringPiece> retry_button = { - "recommend-apps-screen", "recommend-apps-retry-button"}; test::OobeJS().ExpectDisabledPath(install_button); @@ -356,14 +349,12 @@ test::OobeJS().ExpectDisabledPath(install_button); test::OobeJS().ExpectPathDisplayed(true, skip_button); test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); ASSERT_TRUE(ToggleAppsSelection( webview_path, "['test.app.foo.app1', 'test.app.foo.app2']")); test::OobeJS().CreateEnabledWaiter(true, install_button)->Wait(); test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); ASSERT_TRUE(ToggleAppsSelection(webview_path, "['test.app.foo.app1']")); @@ -414,8 +405,6 @@ "recommend-apps-screen", "recommend-apps-install-button"}; const std::initializer_list<base::StringPiece> skip_button = { "recommend-apps-screen", "recommend-apps-skip-button"}; - const std::initializer_list<base::StringPiece> retry_button = { - "recommend-apps-screen", "recommend-apps-retry-button"}; test::OobeJS().ExpectDisabledPath(install_button); @@ -428,13 +417,11 @@ test::OobeJS().ExpectDisabledPath(install_button); test::OobeJS().ExpectPathDisplayed(true, skip_button); test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); ASSERT_TRUE(ToggleAppsSelection(webview_path, "['test.app.foo.app2']")); test::OobeJS().CreateEnabledWaiter(true, install_button)->Wait(); test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); test::OobeJS().TapOnPath(skip_button); @@ -480,8 +467,6 @@ "recommend-apps-screen", "recommend-apps-install-button"}; const std::initializer_list<base::StringPiece> skip_button = { "recommend-apps-screen", "recommend-apps-skip-button"}; - const std::initializer_list<base::StringPiece> retry_button = { - "recommend-apps-screen", "recommend-apps-retry-button"}; test::OobeJS().ExpectDisabledPath(install_button); @@ -494,19 +479,16 @@ test::OobeJS().ExpectDisabledPath(install_button); test::OobeJS().ExpectPathDisplayed(true, skip_button); test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); ASSERT_TRUE(ToggleAppsSelection(webview_path, "['test.app.foo.app2']")); test::OobeJS().CreateEnabledWaiter(true, install_button)->Wait(); test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); ASSERT_TRUE(ToggleAppsSelection(webview_path, "['test.app.foo.app2']")); test::OobeJS().CreateEnabledWaiter(false, install_button)->Wait(); test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); test::OobeJS().TapOnPath(skip_button); @@ -592,13 +574,10 @@ "recommend-apps-screen", "recommend-apps-install-button"}; const std::initializer_list<base::StringPiece> skip_button = { "recommend-apps-screen", "recommend-apps-skip-button"}; - const std::initializer_list<base::StringPiece> retry_button = { - "recommend-apps-screen", "recommend-apps-retry-button"}; test::OobeJS().CreateDisplayedWaiter(true, skip_button)->Wait(); test::OobeJS().ExpectEnabledPath(skip_button); test::OobeJS().ExpectDisabledPath(install_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); test::OobeJS().TapOnPath(skip_button); @@ -634,125 +613,6 @@ EXPECT_EQ(0, recommend_apps_fetcher_->retries()); } -IN_PROC_BROWSER_TEST_F(RecommendAppsScreenTest, SkipOnLoadError) { - recommend_apps_screen_->Show(); - - OobeScreenWaiter screen_waiter(RecommendAppsScreenView::kScreenId); - screen_waiter.set_assert_next_screen(); - screen_waiter.Wait(); - - // Wait for loading screen. - test::OobeJS() - .CreateVisibilityWaiter(true, {"recommend-apps-loading"}) - ->Wait(); - test::OobeJS().ExpectHidden("recommend-apps-screen"); - - recommend_apps_fetcher_->SimulateLoadError(); - - test::OobeJS() - .CreateVisibilityWaiter(true, {"recommend-apps-screen"}) - ->Wait(); - test::OobeJS().ExpectHidden("recommend-apps-loading"); - - const std::initializer_list<base::StringPiece> install_button = { - "recommend-apps-screen", "recommend-apps-install-button"}; - const std::initializer_list<base::StringPiece> skip_button = { - "recommend-apps-screen", "recommend-apps-skip-button"}; - const std::initializer_list<base::StringPiece> retry_button = { - "recommend-apps-screen", "recommend-apps-retry-button"}; - - test::OobeJS().CreateDisplayedWaiter(true, skip_button)->Wait(); - test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().CreateDisplayedWaiter(true, retry_button)->Wait(); - test::OobeJS().ExpectEnabledPath(retry_button); - test::OobeJS().ExpectPathDisplayed(false, install_button); - - test::OobeJS().TapOnPath(skip_button); - - WaitForScreenExit(); - EXPECT_EQ(RecommendAppsScreen::Result::SKIPPED, screen_result_.value()); - EXPECT_EQ(0, recommend_apps_fetcher_->retries()); - - const base::Value* fast_reinstall_packages = - ProfileManager::GetActiveUserProfile()->GetPrefs()->Get( - arc::prefs::kArcFastAppReinstallPackages); - ASSERT_TRUE(fast_reinstall_packages); - EXPECT_EQ(base::Value(base::Value::Type::LIST), *fast_reinstall_packages); -} - -IN_PROC_BROWSER_TEST_F(RecommendAppsScreenTest, RetryOnLoadError) { - recommend_apps_screen_->Show(); - - OobeScreenWaiter screen_waiter(RecommendAppsScreenView::kScreenId); - screen_waiter.set_assert_next_screen(); - screen_waiter.Wait(); - - // Wait for loading screen. - test::OobeJS() - .CreateVisibilityWaiter(true, {"recommend-apps-loading"}) - ->Wait(); - test::OobeJS().ExpectHidden("recommend-apps-screen"); - - recommend_apps_fetcher_->SimulateLoadError(); - - test::OobeJS() - .CreateVisibilityWaiter(true, {"recommend-apps-screen"}) - ->Wait(); - test::OobeJS().ExpectHidden("recommend-apps-loading"); - - const std::initializer_list<base::StringPiece> install_button = { - "recommend-apps-screen", "recommend-apps-install-button"}; - const std::initializer_list<base::StringPiece> skip_button = { - "recommend-apps-screen", "recommend-apps-skip-button"}; - const std::initializer_list<base::StringPiece> retry_button = { - "recommend-apps-screen", "recommend-apps-retry-button"}; - - test::OobeJS().CreateDisplayedWaiter(true, skip_button)->Wait(); - test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().CreateDisplayedWaiter(true, retry_button)->Wait(); - test::OobeJS().ExpectEnabledPath(retry_button); - test::OobeJS().ExpectPathDisplayed(false, install_button); - - test::OobeJS().TapOnPath(retry_button); - - EXPECT_EQ(1, recommend_apps_fetcher_->retries()); - - test::OobeJS() - .CreateVisibilityWaiter(false, {"recommend-apps-screen"}) - ->Wait(); - test::OobeJS().ExpectVisible("recommend-apps-loading"); - - std::vector<FakeAppInfo> test_apps = { - FakeAppInfo("test.app.foo.app1", "Test app 1")}; - recommend_apps_fetcher_->SimulateSuccess(test_apps); - - test::OobeJS() - .CreateVisibilityWaiter(true, {"recommend-apps-screen"}) - ->Wait(); - test::OobeJS().ExpectHidden("recommend-apps-loading"); - - const std::string webview_path = - test::GetOobeElementPath({"recommend-apps-screen", "app-list-view"}); - test::OobeJS() - .CreateDisplayedWaiter(true, {"recommend-apps-screen", "app-list-view"}) - ->Wait(); - ASSERT_TRUE(WaitForAppListSize(webview_path, test_apps.size())); - - test::OobeJS().ExpectPathDisplayed(true, install_button); - test::OobeJS().ExpectDisabledPath(install_button); - test::OobeJS().ExpectPathDisplayed(true, skip_button); - test::OobeJS().ExpectEnabledPath(skip_button); - test::OobeJS().ExpectPathDisplayed(false, retry_button); - - EXPECT_FALSE(screen_result_.has_value()); - EXPECT_EQ(1, recommend_apps_fetcher_->retries()); - - const base::Value* fast_reinstall_packages = - ProfileManager::GetActiveUserProfile()->GetPrefs()->Get( - arc::prefs::kArcFastAppReinstallPackages); - ASSERT_TRUE(fast_reinstall_packages); - EXPECT_EQ(base::Value(base::Value::Type::LIST), *fast_reinstall_packages); -} IN_PROC_BROWSER_TEST_F(RecommendAppsScreenTest, SkipDueToManagedUser) { GetProfilePolicyConnector()->OverrideIsManagedForTesting(true);
diff --git a/chrome/browser/chromeos/login/webview_login_browsertest.cc b/chrome/browser/chromeos/login/webview_login_browsertest.cc index 89f473c..b605364 100644 --- a/chrome/browser/chromeos/login/webview_login_browsertest.cc +++ b/chrome/browser/chromeos/login/webview_login_browsertest.cc
@@ -45,6 +45,7 @@ #include "chrome/browser/ui/webui/chromeos/login/eula_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" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" #include "chromeos/dbus/session_manager/fake_session_manager_client.h" @@ -89,6 +90,11 @@ constexpr char kTestCookieValue[] = "present"; constexpr char kTestCookieHost[] = "host1.com"; +constexpr std::initializer_list<base::StringPiece> kPrimaryButton = { + "gaia-signin", "primary-action-button"}; +constexpr std::initializer_list<base::StringPiece> kSecondaryButton = { + "gaia-signin", "secondary-action-button"}; + void InjectCookieDoneCallback( base::OnceClosure done_closure, net::CanonicalCookie::CookieInclusionStatus status) { @@ -183,7 +189,9 @@ class WebviewLoginTest : public OobeBaseTest { public: - WebviewLoginTest() = default; + WebviewLoginTest() { + scoped_feature_list_.InitWithFeatures({features::kGaiaActionButtons}, {}); + } ~WebviewLoginTest() override = default; void SetUpCommandLine(base::CommandLine* command_line) override { @@ -247,10 +255,59 @@ FakeGaiaMixin fake_gaia_{&mixin_host_, embedded_test_server()}; private: + base::test::ScopedFeatureList scoped_feature_list_; DISALLOW_COPY_AND_ASSIGN(WebviewLoginTest); }; // Basic signin with username and password. +IN_PROC_BROWSER_TEST_F(WebviewLoginTest, NativeTest) { + WaitForGaiaPageLoadAndPropertyUpdate(); + ExpectIdentifierPage(); + SigninFrameJS().TypeIntoPath(FakeGaiaMixin::kFakeUserEmail, {"identifier"}); + test::OobeJS().ClickOnPath(kPrimaryButton); + WaitForGaiaPageBackButtonUpdate(); + ExpectPasswordPage(); + + test::OobeJS().ExpectVisiblePath(kSecondaryButton); + test::OobeJS().ExpectEnabledPath(kSecondaryButton); + + // Check events propagation. + SigninFrameJS().ExecuteAsync("sendSetAllActionsEnabled(false)"); + test::OobeJS().CreateEnabledWaiter(false, kPrimaryButton)->Wait(); + test::OobeJS().CreateEnabledWaiter(false, kSecondaryButton)->Wait(); + test::OobeJS().ExpectVisiblePath(kPrimaryButton); + test::OobeJS().ExpectVisiblePath(kSecondaryButton); + + SigninFrameJS().ExecuteAsync("sendSetSecondaryActionEnabled(true)"); + test::OobeJS().CreateEnabledWaiter(true, kSecondaryButton)->Wait(); + test::OobeJS().ExpectVisiblePath(kSecondaryButton); + + // Click on the secondary button disables it. + test::OobeJS().ClickOnPath(kSecondaryButton); + test::OobeJS().CreateEnabledWaiter(false, kSecondaryButton)->Wait(); + + SigninFrameJS().ExecuteAsync("sendSetPrimaryActionEnabled(true)"); + test::OobeJS().CreateEnabledWaiter(true, kPrimaryButton)->Wait(); + test::OobeJS().ExpectVisiblePath(kPrimaryButton); + + SigninFrameJS().ExecuteAsync("sendSetPrimaryActionLabel(null)"); + test::OobeJS().CreateVisibilityWaiter(false, kPrimaryButton)->Wait(); + + SigninFrameJS().ExecuteAsync("sendSetSecondaryActionLabel(null)"); + test::OobeJS().CreateVisibilityWaiter(false, kSecondaryButton)->Wait(); + + SigninFrameJS().ExecuteAsync("sendSetPrimaryActionLabel('Submit')"); + test::OobeJS().CreateVisibilityWaiter(true, kPrimaryButton)->Wait(); + test::OobeJS().ExpectElementText("Submit", kPrimaryButton); + + SigninFrameJS().TypeIntoPath("[]", {"services"}); + SigninFrameJS().TypeIntoPath(FakeGaiaMixin::kFakeUserPassword, {"password"}); + test::OobeJS().ClickOnPath(kPrimaryButton); + + test::WaitForPrimaryUserSessionStart(); +} + +// Basic signin with username and password. IN_PROC_BROWSER_TEST_F(WebviewLoginTest, Basic) { base::HistogramTester histogram_tester; WaitForGaiaPageLoadAndPropertyUpdate(); @@ -291,7 +348,7 @@ // Move to password page. SigninFrameJS().TypeIntoPath(FakeGaiaMixin::kFakeUserEmail, {"identifier"}); - SigninFrameJS().TapOn("nextButton"); + test::OobeJS().ClickOnPath(kPrimaryButton); WaitForGaiaPageBackButtonUpdate(); ExpectPasswordPage(); @@ -300,14 +357,14 @@ WaitForGaiaPageBackButtonUpdate(); ExpectIdentifierPage(); // Click next to password page, user id is remembered. - SigninFrameJS().TapOn("nextButton"); + test::OobeJS().ClickOnPath(kPrimaryButton); WaitForGaiaPageBackButtonUpdate(); ExpectPasswordPage(); // Finish sign-up. SigninFrameJS().TypeIntoPath("[]", {"services"}); SigninFrameJS().TypeIntoPath(FakeGaiaMixin::kFakeUserPassword, {"password"}); - SigninFrameJS().TapOn("nextButton"); + test::OobeJS().ClickOnPath(kPrimaryButton); test::WaitForPrimaryUserSessionStart(); }
diff --git a/chrome/browser/chromeos/login/wizard_controller.cc b/chrome/browser/chromeos/login/wizard_controller.cc index c75cc91..dba56768 100644 --- a/chrome/browser/chromeos/login/wizard_controller.cc +++ b/chrome/browser/chromeos/login/wizard_controller.cc
@@ -1176,6 +1176,7 @@ break; case RecommendAppsScreen::Result::SKIPPED: case RecommendAppsScreen::Result::NOT_APPLICABLE: + case RecommendAppsScreen::Result::LOAD_ERROR: ShowAssistantOptInFlowScreen(); break; }
diff --git a/chrome/browser/chromeos/resource_reporter/OWNERS b/chrome/browser/chromeos/resource_reporter/OWNERS deleted file mode 100644 index e3e4f11..0000000 --- a/chrome/browser/chromeos/resource_reporter/OWNERS +++ /dev/null
@@ -1,2 +0,0 @@ -afakhry@chromium.org -nick@chromium.org \ No newline at end of file
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter.cc b/chrome/browser/chromeos/resource_reporter/resource_reporter.cc deleted file mode 100644 index cb5c0f0..0000000 --- a/chrome/browser/chromeos/resource_reporter/resource_reporter.cc +++ /dev/null
@@ -1,433 +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. - -#include "chrome/browser/chromeos/resource_reporter/resource_reporter.h" - -#include <cstdint> -#include <queue> -#include <utility> - -#include "base/bind.h" -#include "base/memory/memory_pressure_monitor.h" -#include "base/metrics/histogram_macros.h" -#include "base/rand_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/system/sys_info.h" -#include "base/threading/thread_task_runner_handle.h" -#include "base/time/time.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/task_manager/task_manager_interface.h" -#include "components/rappor/rappor_service_impl.h" -#include "content/public/browser/browser_thread.h" - -namespace chromeos { - -namespace { - -#define GET_ENUM_VAL(enum_entry) static_cast<int>(enum_entry) - -// At a critical memory pressure event, we only care about a single complete -// refresh from the task manager (with background calculations). So we request -// the minimum refresh rate (once per second). -constexpr int64_t kRefreshIntervalSeconds = 1; - -// Various memory usage sizes in bytes. -constexpr int64_t kMemory1GB = 1024 * 1024 * 1024; -constexpr int64_t kMemory800MB = 800 * 1024 * 1024; -constexpr int64_t kMemory600MB = 600 * 1024 * 1024; -constexpr int64_t kMemory400MB = 400 * 1024 * 1024; -constexpr int64_t kMemory200MB = 200 * 1024 * 1024; - -// The name of the Rappor metric to report the CPU usage. -constexpr char kCpuRapporMetric[] = "ResourceReporter.Cpu"; - -// The name of the Rappor metric to report the memory usage. -constexpr char kMemoryRapporMetric[] = "ResourceReporter.Memory"; - -// The name of the string field of the Rappor metrics in which we'll record the -// task's Rappor sample name. -constexpr char kRapporTaskStringField[] = "task"; - -// The name of the flags field of the Rappor metrics in which we'll store the -// priority of the process on which the task is running. -constexpr char kRapporPriorityFlagsField[] = "priority"; - -// The name of the flags field of the CPU usage Rappor metrics in which we'll -// record the number of cores in the current system. -constexpr char kRapporNumCoresRangeFlagsField[] = "num_cores_range"; - -// The name of the flags field of the Rappor metrics in which we'll store the -// CPU / memory usage ranges. -constexpr char kRapporUsageRangeFlagsField[] = "usage_range"; - -// Key used to store the last time a Rappor report was recorded in local_state. -constexpr char kLastRapporReportTimeKey[] = - "resource_reporter.last_report_time"; - -// To keep privacy guarantees of Rappor, we limit the reports to at most once -// per day. -constexpr base::TimeDelta kMinimumTimeBetweenReports = - base::TimeDelta::FromDays(1); - -constexpr double kTaskCpuThresholdForReporting = 70.0; - -} // namespace - -ResourceReporter::TaskRecord::TaskRecord(task_manager::TaskId task_id) - : id(task_id), cpu_percent(0.0), memory_bytes(0), is_background(false) {} - -ResourceReporter::TaskRecord::TaskRecord(task_manager::TaskId the_id, - const std::string& task_name, - double cpu_percent, - int64_t memory_bytes, - bool background) - : id(the_id), - task_name_for_rappor(task_name), - cpu_percent(cpu_percent), - memory_bytes(memory_bytes), - is_background(background) {} - -ResourceReporter::~ResourceReporter() { -} - -// static -ResourceReporter* ResourceReporter::GetInstance() { - return base::Singleton<ResourceReporter>::get(); -} - -// static -void ResourceReporter::RegisterPrefs(PrefRegistrySimple* registry) { - registry->RegisterDoublePref(kLastRapporReportTimeKey, 0.0); -} - -void ResourceReporter::StartMonitoring( - task_manager::TaskManagerInterface* task_manager_to_observe) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (is_monitoring_) - return; - - task_manager_to_observe_ = task_manager_to_observe; - DCHECK(task_manager_to_observe_); - is_monitoring_ = true; - memory_pressure_listener_.reset(new base::MemoryPressureListener( - base::Bind(&ResourceReporter::OnMemoryPressure, base::Unretained(this)))); -} - -void ResourceReporter::StopMonitoring() { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - if (!is_monitoring_) - return; - - // We might be shutting down right after a critical memory pressure event, and - // before we get an update from the task manager with all background - // calculations refreshed. In this case we must unregister from the task - // manager here. - StopRecordingCurrentState(); - - is_monitoring_ = false; - memory_pressure_listener_.reset(); -} - -void ResourceReporter::OnTasksRefreshedWithBackgroundCalculations( - const task_manager::TaskIdList& task_ids) { - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); - - task_records_.clear(); - task_records_.reserve(task_ids.size()); - - for (const auto& id : task_ids) { - const double cpu_usage = - (observed_task_manager()->GetPlatformIndependentCPUUsage(id) / - base::SysInfo::NumberOfProcessors()); - const int64_t memory_usage = - observed_task_manager()->GetMemoryFootprintUsage(id); - - // Browser and GPU processes are reported later using UMA histograms as they - // don't have any privacy issues. - const auto task_type = observed_task_manager()->GetType(id); - switch (task_type) { - case task_manager::Task::UNKNOWN: - case task_manager::Task::ZYGOTE: - break; - - case task_manager::Task::BROWSER: - last_browser_process_cpu_ = cpu_usage; - last_browser_process_memory_ = memory_usage >= 0 ? memory_usage : 0; - break; - - case task_manager::Task::GPU: - last_gpu_process_cpu_ = cpu_usage; - last_gpu_process_memory_ = memory_usage >= 0 ? memory_usage : 0; - break; - - default: - // Other tasks types will be reported using Rappor. - if (memory_usage < GetTaskMemoryThresholdForReporting() && - cpu_usage < GetTaskCpuThresholdForReporting()) { - // We only care about CPU and memory intensive tasks. - break; - } - - task_records_.emplace_back( - id, observed_task_manager()->GetTaskNameForRappor(id), cpu_usage, - memory_usage, - observed_task_manager()->IsTaskOnBackgroundedProcess(id)); - } - } - - // Now that we got the data, we don't need the task manager anymore. - if (base::MemoryPressureMonitor::Get()->GetCurrentPressureLevel() != - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL || - !task_records_.empty()) { - // The memory pressure events are emitted once per second. In order to avoid - // unsubscribing and then resubscribing to the task manager again on the - // next event, we keep listening to the task manager as long as the memory - // pressure level is critical AND we couldn't find any violators yet. - StopRecordingCurrentState(); - } - - // Schedule reporting the samples. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&ResourceReporter::ReportSamples, base::Unretained(this))); -} - -ResourceReporter::ResourceReporter() - : TaskManagerObserver(base::TimeDelta::FromSeconds(kRefreshIntervalSeconds), - task_manager::REFRESH_TYPE_CPU | - task_manager::REFRESH_TYPE_MEMORY_FOOTPRINT | - task_manager::REFRESH_TYPE_PRIORITY), - task_manager_to_observe_(nullptr), - system_cpu_cores_range_(GetCurrentSystemCpuCoresRange()), - last_browser_process_cpu_(0.0), - last_gpu_process_cpu_(0.0), - last_browser_process_memory_(0), - last_gpu_process_memory_(0), - is_monitoring_(false) {} - -// static -double ResourceReporter::GetTaskCpuThresholdForReporting() { - return kTaskCpuThresholdForReporting; -} - -// static -int64_t ResourceReporter::GetTaskMemoryThresholdForReporting() { - static const int64_t threshold = 0.6 * - base::SysInfo::AmountOfPhysicalMemory() / - base::SysInfo::NumberOfProcessors(); - return threshold; -} - -// static -std::unique_ptr<rappor::Sample> ResourceReporter::CreateRapporSample( - rappor::RapporServiceImpl* rappor_service, - const ResourceReporter::TaskRecord& task_record) { - std::unique_ptr<rappor::Sample> sample( - rappor_service->CreateSample(rappor::UMA_RAPPOR_TYPE)); - sample->SetStringField(kRapporTaskStringField, - task_record.task_name_for_rappor); - sample->SetFlagsField(kRapporPriorityFlagsField, - task_record.is_background ? - GET_ENUM_VAL(TaskProcessPriority::BACKGROUND) : - GET_ENUM_VAL(TaskProcessPriority::FOREGROUND), - GET_ENUM_VAL(TaskProcessPriority::NUM_PRIORITIES)); - return sample; -} - -// static -ResourceReporter::CpuUsageRange -ResourceReporter::GetCpuUsageRange(double cpu) { - if (cpu > 60.0) - return CpuUsageRange::RANGE_ABOVE_60_PERCENT; - if (cpu > 30.0) - return CpuUsageRange::RANGE_30_TO_60_PERCENT; - if (cpu > 10.0) - return CpuUsageRange::RANGE_10_TO_30_PERCENT; - - return CpuUsageRange::RANGE_0_TO_10_PERCENT; -} - -// static -ResourceReporter::MemoryUsageRange -ResourceReporter::GetMemoryUsageRange(int64_t memory_in_bytes) { - if (memory_in_bytes > kMemory1GB) - return MemoryUsageRange::RANGE_ABOVE_1_GB; - if (memory_in_bytes > kMemory800MB) - return MemoryUsageRange::RANGE_800_TO_1_GB; - if (memory_in_bytes > kMemory600MB) - return MemoryUsageRange::RANGE_600_TO_800_MB; - if (memory_in_bytes > kMemory400MB) - return MemoryUsageRange::RANGE_400_TO_600_MB; - if (memory_in_bytes > kMemory200MB) - return MemoryUsageRange::RANGE_200_TO_400_MB; - - return MemoryUsageRange::RANGE_0_TO_200_MB; -} - -// static -ResourceReporter::CpuCoresNumberRange -ResourceReporter::GetCurrentSystemCpuCoresRange() { - const int cpus = base::SysInfo::NumberOfProcessors(); - - if (cpus > 16) - return CpuCoresNumberRange::RANGE_ABOVE_16_CORES; - if (cpus > 8) - return CpuCoresNumberRange::RANGE_9_TO_16_CORES; - if (cpus > 4) - return CpuCoresNumberRange::RANGE_5_TO_8_CORES; - if (cpus > 2) - return CpuCoresNumberRange::RANGE_3_TO_4_CORES; - if (cpus == 2) - return CpuCoresNumberRange::RANGE_2_CORES; - if (cpus == 1) - return CpuCoresNumberRange::RANGE_1_CORE; - - NOTREACHED(); - return CpuCoresNumberRange::RANGE_NA; -} - -const ResourceReporter::TaskRecord* ResourceReporter::SampleTaskByCpu() const { - // Perform a weighted random sampling taking the tasks' CPU usage as their - // weights to randomly select one of them to be reported by Rappor. The higher - // the CPU usage, the higher the chance that the task will be selected. - // See https://en.wikipedia.org/wiki/Reservoir_sampling. - const TaskRecord* sampled_task = nullptr; - double cpu_weights_sum = 0; - for (const auto& task_data : task_records_) { - if ((base::RandDouble() * (cpu_weights_sum + task_data.cpu_percent)) >= - cpu_weights_sum) { - sampled_task = &task_data; - } - cpu_weights_sum += task_data.cpu_percent; - } - - return sampled_task; -} - -const ResourceReporter::TaskRecord* -ResourceReporter::SampleTaskByMemory() const { - // Perform a weighted random sampling taking the tasks' memory usage as their - // weights to randomly select one of them to be reported by Rappor. The higher - // the memory usage, the higher the chance that the task will be selected. - // See https://en.wikipedia.org/wiki/Reservoir_sampling. - const TaskRecord* sampled_task = nullptr; - int64_t memory_weights_sum = 0; - for (const auto& task_data : task_records_) { - if ((base::RandDouble() * (memory_weights_sum + task_data.memory_bytes)) >= - memory_weights_sum) { - sampled_task = &task_data; - } - memory_weights_sum += task_data.memory_bytes; - } - - return sampled_task; -} - -void ResourceReporter::ReportSamples() { - // Report browser and GPU processes usage using UMA histograms. - UMA_HISTOGRAM_ENUMERATION( - "ResourceReporter.BrowserProcess.CpuUsage", - GET_ENUM_VAL(GetCpuUsageRange(last_browser_process_cpu_)), - GET_ENUM_VAL(CpuUsageRange::NUM_RANGES)); - UMA_HISTOGRAM_ENUMERATION( - "ResourceReporter.BrowserProcess.MemoryUsage", - GET_ENUM_VAL(GetMemoryUsageRange(last_browser_process_memory_)), - GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES)); - UMA_HISTOGRAM_ENUMERATION( - "ResourceReporter.GpuProcess.CpuUsage", - GET_ENUM_VAL(GetCpuUsageRange(last_gpu_process_cpu_)), - GET_ENUM_VAL(CpuUsageRange::NUM_RANGES)); - UMA_HISTOGRAM_ENUMERATION( - "ResourceReporter.GpuProcess.MemoryUsage", - GET_ENUM_VAL(GetMemoryUsageRange(last_gpu_process_memory_)), - GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES)); - - // For the rest of tasks, report them using Rappor. - auto* rappor_service = g_browser_process->rappor_service(); - if (!rappor_service || task_records_.empty()) - return; - - // We have samples to report via Rappor. Store 'now' as the time of the last - // report. - if (g_browser_process->local_state()) { - g_browser_process->local_state()->SetDouble( - kLastRapporReportTimeKey, base::Time::NowFromSystemTime().ToDoubleT()); - } - - // Use weighted random sampling to select a task to report in the CPU - // metric. - const TaskRecord* sampled_cpu_task = SampleTaskByCpu(); - if (sampled_cpu_task) { - std::unique_ptr<rappor::Sample> cpu_sample( - CreateRapporSample(rappor_service, *sampled_cpu_task)); - cpu_sample->SetFlagsField(kRapporNumCoresRangeFlagsField, - GET_ENUM_VAL(system_cpu_cores_range_), - GET_ENUM_VAL(CpuCoresNumberRange::NUM_RANGES)); - cpu_sample->SetFlagsField( - kRapporUsageRangeFlagsField, - GET_ENUM_VAL(GetCpuUsageRange(sampled_cpu_task->cpu_percent)), - GET_ENUM_VAL(CpuUsageRange::NUM_RANGES)); - rappor_service->RecordSample(kCpuRapporMetric, std::move(cpu_sample)); - } - - // Use weighted random sampling to select a task to report in the memory - // metric. - const TaskRecord* sampled_memory_task = SampleTaskByMemory(); - if (sampled_memory_task) { - std::unique_ptr<rappor::Sample> memory_sample( - CreateRapporSample(rappor_service, *sampled_memory_task)); - memory_sample->SetFlagsField( - kRapporUsageRangeFlagsField, - GET_ENUM_VAL(GetMemoryUsageRange(sampled_memory_task->memory_bytes)), - GET_ENUM_VAL(MemoryUsageRange::NUM_RANGES)); - rappor_service->RecordSample(kMemoryRapporMetric, std::move(memory_sample)); - } -} - -void ResourceReporter::OnMemoryPressure( - MemoryPressureLevel memory_pressure_level) { - if (memory_pressure_level == - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL) { - StartRecordingCurrentState(); - } else { - StopRecordingCurrentState(); - } -} - -void ResourceReporter::StartRecordingCurrentState() { - // If we are already listening to the task manager, then we're waiting for - // a refresh event. - if (observed_task_manager()) - return; - - // We only record Rappor samples only if it's the first ever critical memory - // pressure event we receive, or it has been more than - // |kMinimumTimeBetweenReportsInMs| since the last time we recorded samples. - if (g_browser_process->local_state()) { - const base::Time now = base::Time::NowFromSystemTime(); - const base::Time last_rappor_report_time = base::Time::FromDoubleT( - g_browser_process->local_state()->GetDouble(kLastRapporReportTimeKey)); - const base::TimeDelta delta_since_last_report = - now >= last_rappor_report_time ? now - last_rappor_report_time - : base::TimeDelta::Max(); - - if (delta_since_last_report < kMinimumTimeBetweenReports) - return; - } - - // Start listening to the task manager and wait for the first refresh event - // with background calculations completion. - task_manager_to_observe_->AddObserver(this); -} - -void ResourceReporter::StopRecordingCurrentState() { - // If we are still listening to the task manager from an earlier critical - // memory pressure level, we need to stop listening to it. - if (observed_task_manager()) - observed_task_manager()->RemoveObserver(this); -} - -} // namespace chromeos
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter.h b/chrome/browser/chromeos/resource_reporter/resource_reporter.h deleted file mode 100644 index ef5bec3..0000000 --- a/chrome/browser/chromeos/resource_reporter/resource_reporter.h +++ /dev/null
@@ -1,198 +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 CHROME_BROWSER_CHROMEOS_RESOURCE_REPORTER_RESOURCE_REPORTER_H_ -#define CHROME_BROWSER_CHROMEOS_RESOURCE_REPORTER_RESOURCE_REPORTER_H_ - -#include <stddef.h> -#include <stdint.h> - -#include <memory> -#include <string> -#include <vector> - -#include "base/gtest_prod_util.h" -#include "base/macros.h" -#include "base/memory/memory_pressure_listener.h" -#include "base/memory/singleton.h" -#include "chrome/browser/task_manager/task_manager_observer.h" -#include "components/metrics/metrics_service.h" -#include "components/prefs/pref_registry_simple.h" -#include "components/rappor/public/sample.h" - -namespace chromeos { - -// A system that tracks the top |kTopConsumersCount| CPU and memory consumer -// Chrome tasks and reports a weighted random sample of them via Rappor whenever -// memory pressure is critical. The reporting is limited to once per -// |kMinimumTimeBetweenReportsInMS|. -class ResourceReporter : public task_manager::TaskManagerObserver { - public: - // A collection of the data of a task manager's task that the ResourceReporter - // is interested in. - struct TaskRecord { - explicit TaskRecord(task_manager::TaskId task_id); - - TaskRecord(task_manager::TaskId task_id, - const std::string& task_name, - double cpu_percent, - int64_t memory_bytes, - bool background); - - // The ID of the task. - task_manager::TaskId id; - - // The canonicalized task name to be used to represent the task in a Rappor - // sample. - std::string task_name_for_rappor; - - // The CPU usage of the task from the most recent task manager refresh in - // percentage [0.0, 100.0]. - double cpu_percent; - - // The memory footprint of the task from the most recent task manager - // refresh in bytes. It doesn't include shared memory. A value of -1 is - // invalid and means that the memory usage measurement for this task is not - // ready yet. See TaskManagerInterface::GetMemoryFootprintUsage(). - int64_t memory_bytes; - - // True if the task is running on a process at background priority. - bool is_background; - }; - - ~ResourceReporter() override; - - // The singleton instance. - static ResourceReporter* GetInstance(); - - static void RegisterPrefs(PrefRegistrySimple* registry); - - // Start / stop observing the task manager and the memory pressure events. - void StartMonitoring( - task_manager::TaskManagerInterface* task_manager_to_observe); - void StopMonitoring(); - - // task_manager::TaskManagerObserver: - void OnTasksRefreshedWithBackgroundCalculations( - const task_manager::TaskIdList& task_ids) override; - - private: - friend struct base::DefaultSingletonTraits<ResourceReporter>; - friend class ResourceReporterTest; - FRIEND_TEST_ALL_PREFIXES(ResourceReporterTest, TestGetCpuRapporMetricName); - FRIEND_TEST_ALL_PREFIXES(ResourceReporterTest, TestGetMemoryRapporMetricName); - FRIEND_TEST_ALL_PREFIXES(ResourceReporterTest, TestAll); - - // WARNING: The below enum MUST never be renamed, modified or reordered, as - // they're written to logs. You can only insert a new element immediately - // before the last, and update the value of the last element. - enum class TaskProcessPriority { - FOREGROUND = 0, - BACKGROUND = 1 << 0, - NUM_PRIORITIES = 2, - }; - - // WARNING: The below enum MUST never be renamed, modified or reordered, as - // they're written to logs. You can only insert a new element immediately - // before the last, and update the value of the last element. - enum class CpuUsageRange { - RANGE_0_TO_10_PERCENT = 0, - RANGE_10_TO_30_PERCENT = 1 << 0, - RANGE_30_TO_60_PERCENT = 1 << 1, - RANGE_ABOVE_60_PERCENT = 1 << 2, - NUM_RANGES = 4, - }; - - // WARNING: The below enum MUST never be renamed, modified or reordered, as - // they're written to logs. You can only insert a new element immediately - // before the last, and update the value of the last element. - enum class MemoryUsageRange { - RANGE_0_TO_200_MB = 0, - RANGE_200_TO_400_MB = 1 << 0, - RANGE_400_TO_600_MB = 1 << 1, - RANGE_600_TO_800_MB = 1 << 2, - RANGE_800_TO_1_GB = 1 << 3, - RANGE_ABOVE_1_GB = 1 << 4, - NUM_RANGES = 6, - }; - - // WARNING: The below enum MUST never be renamed, modified or reordered, as - // they're written to logs. You can only insert a new element immediately - // before the last, and update the value of the last element. - enum class CpuCoresNumberRange { - RANGE_NA = 0, - RANGE_1_CORE = 1 << 0, - RANGE_2_CORES = 1 << 1, - RANGE_3_TO_4_CORES = 1 << 2, - RANGE_5_TO_8_CORES = 1 << 3, - RANGE_9_TO_16_CORES = 1 << 4, - RANGE_ABOVE_16_CORES = 1 << 5, - NUM_RANGES = 7, - }; - - ResourceReporter(); - - // The CPU and memory thresholds beyond which the tasks will be reported. - static double GetTaskCpuThresholdForReporting(); - static int64_t GetTaskMemoryThresholdForReporting(); - - // Creates a Rappor sample for the given |task_record|. - static std::unique_ptr<rappor::Sample> CreateRapporSample( - rappor::RapporServiceImpl* rappor_service, - const TaskRecord& task_record); - - // Gets the CPU/memory usage ranges given the |cpu| / |memory_in_bytes| - // values. - static CpuUsageRange GetCpuUsageRange(double cpu); - static MemoryUsageRange GetMemoryUsageRange(int64_t memory_in_bytes); - - // Gets the bucket in which the current system's number of CPU cores fall. - static CpuCoresNumberRange GetCurrentSystemCpuCoresRange(); - - // Perform a weighted random sampling to select a task by its CPU or memory - // usage weights so that we can record samples for them via Rappor. - // They return nullptr if no TaskRecord has been selected. - const TaskRecord* SampleTaskByCpu() const; - const TaskRecord* SampleTaskByMemory() const; - - // Does the actual recording of Rappor and UMA samples. - void ReportSamples(); - - // The callback function that will be invoked on memory pressure events. - using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; - void OnMemoryPressure(MemoryPressureLevel memory_pressure_level); - - void StartRecordingCurrentState(); - void StopRecordingCurrentState(); - - // Monitor memory pressure events. - std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_; - - // Contains the data about the most CPU and memory intensive tasks collected - // at a critical memory pressure event. - std::vector<TaskRecord> task_records_; - - // Either the real task manager implementation, or a test implementation in - // unit tests. - task_manager::TaskManagerInterface* task_manager_to_observe_; - - // The range that includes the number of CPU cores in the current system. - const CpuCoresNumberRange system_cpu_cores_range_; - - // The most recent reading for the browser and GPU processes to be reported as - // UMA histograms when the system is under critical memory pressure. - double last_browser_process_cpu_; - double last_gpu_process_cpu_; - int64_t last_browser_process_memory_; - int64_t last_gpu_process_memory_; - - // Tracks whether monitoring started or not. - bool is_monitoring_; - - DISALLOW_COPY_AND_ASSIGN(ResourceReporter); -}; - -} // namespace chromeos - -#endif // CHROME_BROWSER_CHROMEOS_RESOURCE_REPORTER_RESOURCE_REPORTER_H_
diff --git a/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc b/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc deleted file mode 100644 index 45b8231..0000000 --- a/chrome/browser/chromeos/resource_reporter/resource_reporter_unittest.cc +++ /dev/null
@@ -1,279 +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. - -#include <stddef.h> -#include <stdint.h> - -#include <limits> -#include <map> -#include <string> -#include <vector> - -#include "base/run_loop.h" -#include "base/stl_util.h" -#include "base/strings/utf_string_conversions.h" -#include "base/system/sys_info.h" -#include "base/timer/mock_timer.h" -#include "base/util/memory_pressure/fake_memory_pressure_monitor.h" -#include "chrome/browser/chromeos/resource_reporter/resource_reporter.h" -#include "chrome/browser/task_manager/test_task_manager.h" -#include "content/public/test/browser_task_environment.h" -#include "testing/gtest/include/gtest/gtest.h" - -using task_manager::TaskId; - -namespace chromeos { - -namespace { - -constexpr int64_t k1KB = 1024; -constexpr int64_t k1MB = 1024 * 1024; -constexpr int64_t k1GB = 1024 * 1024 * 1024; - -constexpr double kBrowserProcessCpu = 21.0; -constexpr int64_t kBrowserProcessMemory = 300 * k1MB; -constexpr double kGpuProcessCpu = 60.0; -constexpr int64_t kGpuProcessMemory = 900 * k1MB; - -// A list of task records that we'll use to fill the task manager. -const ResourceReporter::TaskRecord kTestTasks[] = { - {0, "0", 30.0, 43 * k1KB, false}, - {1, "1", 9.0, 20 * k1MB, false}, - {2, "2", 35.0, 3 * k1GB, false}, - // Browser task. - {3, "3", kBrowserProcessCpu, kBrowserProcessMemory, false}, - {4, "4", 85.0, 400 * k1KB, false}, - {5, "5", 30.1, 500 * k1MB, false}, - // GPU task. - {6, "6", kGpuProcessCpu, kGpuProcessMemory, false}, - {7, "7", 4.0, 1 * k1GB, false}, - {8, "8", 40.0, 64 * k1KB, false}, - {9, "9", 93.0, 64 * k1MB, false}, - {10, "10", 2.23, 2 * k1KB, false}, - {11, "11", 55.0, 40 * k1MB, false}, - {12, "12", 87.0, 30 * k1KB, false}, -}; - -constexpr size_t kTasksSize = base::size(kTestTasks); - -// A test implementation of the task manager that can be used to collect CPU and -// memory usage so that they can be tested with the resource reporter. -class DummyTaskManager : public task_manager::TestTaskManager { - public: - DummyTaskManager() { - set_timer_for_testing(std::make_unique<base::MockRepeatingTimer>()); - } - ~DummyTaskManager() override {} - - // task_manager::TestTaskManager: - double GetPlatformIndependentCPUUsage(TaskId task_id) const override { - // |cpu_percent| expresses the expected value that the metrics reporter - // should give for this Task's group, which is a percentage-of-total, - // so we need to multiply up by the number of cores, to have TaskManager - // return the correct percentage-of-core CPU usage. - return tasks_.at(task_id)->cpu_percent * - base::SysInfo::NumberOfProcessors(); - } - int64_t GetMemoryFootprintUsage(TaskId task_id) const override { - return tasks_.at(task_id)->memory_bytes; - } - const std::string& GetTaskNameForRappor(TaskId task_id) const override { - return tasks_.at(task_id)->task_name_for_rappor; - } - task_manager::Task::Type GetType(TaskId task_id) const override { - switch (task_id) { - case 3: - return task_manager::Task::BROWSER; - - case 6: - return task_manager::Task::GPU; - - default: - return task_manager::Task::RENDERER; - } - } - - void AddTaskFromIndex(size_t index) { - tasks_[kTestTasks[index].id] = &kTestTasks[index]; - } - - void ManualRefresh() { - ids_.clear(); - for (const auto& pair : tasks_) - ids_.push_back(pair.first); - - NotifyObserversOnRefreshWithBackgroundCalculations(ids_); - } - - private: - std::map<TaskId, const ResourceReporter::TaskRecord*> tasks_; - - DISALLOW_COPY_AND_ASSIGN(DummyTaskManager); -}; - -} // namespace - -class ResourceReporterTest : public testing::Test { - public: - ResourceReporterTest() {} - ~ResourceReporterTest() override {} - - void SetUp() override { - resource_reporter()->StartMonitoring(&task_manager_); - } - - void TearDown() override { resource_reporter()->StopMonitoring(); } - - // Adds a number of tasks less than |kTopConsumersCount| to the task manager. - void AddTasks() { - for (size_t i = 0; i < kTasksSize; ++i) - task_manager_.AddTaskFromIndex(i); - } - - // Manually refresh the task manager. - void RefreshTaskManager() { - task_manager_.ManualRefresh(); - } - - ResourceReporter* resource_reporter() const { - return ResourceReporter::GetInstance(); - } - - util::test::FakeMemoryPressureMonitor* monitor() { return &monitor_; } - - private: - content::BrowserTaskEnvironment task_environment_; - - util::test::FakeMemoryPressureMonitor monitor_; - - DummyTaskManager task_manager_; - - DISALLOW_COPY_AND_ASSIGN(ResourceReporterTest); -}; - -// Tests that ResourceReporter::GetCpuRapporMetricName() returns the correct -// metric name that corresponds to the given CPU usage. -TEST_F(ResourceReporterTest, TestGetCpuRapporMetricName) { - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_0_TO_10_PERCENT, - ResourceReporter::GetCpuUsageRange(0.3)); - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_0_TO_10_PERCENT, - ResourceReporter::GetCpuUsageRange(5.7)); - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_0_TO_10_PERCENT, - ResourceReporter::GetCpuUsageRange(9.99)); - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_0_TO_10_PERCENT, - ResourceReporter::GetCpuUsageRange(10.0)); - - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_10_TO_30_PERCENT, - ResourceReporter::GetCpuUsageRange(10.1)); - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_10_TO_30_PERCENT, - ResourceReporter::GetCpuUsageRange(29.99)); - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_10_TO_30_PERCENT, - ResourceReporter::GetCpuUsageRange(30.0)); - - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_30_TO_60_PERCENT, - ResourceReporter::GetCpuUsageRange(30.1)); - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_30_TO_60_PERCENT, - ResourceReporter::GetCpuUsageRange(59.99)); - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_30_TO_60_PERCENT, - ResourceReporter::GetCpuUsageRange(60.0)); - - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_ABOVE_60_PERCENT, - ResourceReporter::GetCpuUsageRange(60.1)); - EXPECT_EQ(ResourceReporter::CpuUsageRange::RANGE_ABOVE_60_PERCENT, - ResourceReporter::GetCpuUsageRange(100.0)); -} - -// Tests that ResourceReporter::GetMemoryRapporMetricName() returns the correct -// metric names for the given memory usage. -TEST_F(ResourceReporterTest, TestGetMemoryRapporMetricName) { - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_0_TO_200_MB, - ResourceReporter::GetMemoryUsageRange(2 * k1KB)); - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_0_TO_200_MB, - ResourceReporter::GetMemoryUsageRange(20 * k1MB)); - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_0_TO_200_MB, - ResourceReporter::GetMemoryUsageRange(200 * k1MB)); - - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_200_TO_400_MB, - ResourceReporter::GetMemoryUsageRange(201 * k1MB)); - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_200_TO_400_MB, - ResourceReporter::GetMemoryUsageRange(400 * k1MB)); - - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_400_TO_600_MB, - ResourceReporter::GetMemoryUsageRange(401 * k1MB)); - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_400_TO_600_MB, - ResourceReporter::GetMemoryUsageRange(600 * k1MB)); - - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_600_TO_800_MB, - ResourceReporter::GetMemoryUsageRange(601 * k1MB)); - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_600_TO_800_MB, - ResourceReporter::GetMemoryUsageRange(800 * k1MB)); - - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_800_TO_1_GB, - ResourceReporter::GetMemoryUsageRange(801 * k1MB)); - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_800_TO_1_GB, - ResourceReporter::GetMemoryUsageRange(1 * k1GB)); - - EXPECT_EQ(ResourceReporter::MemoryUsageRange::RANGE_ABOVE_1_GB, - ResourceReporter::GetMemoryUsageRange(1 * k1GB + 1 * k1KB)); -} - -// Tests all the interactions between the resource reporter and the task -// manager. -TEST_F(ResourceReporterTest, TestAll) { - using MemoryPressureLevel = base::MemoryPressureListener::MemoryPressureLevel; - - // Moderate memory pressure events should not trigger any sampling. - monitor()->SetAndNotifyMemoryPressure( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(resource_reporter()->observed_task_manager()); - - // A critical memory pressure event, but the task manager is not tracking any - // resource intensive tasks yet. - monitor()->SetAndNotifyMemoryPressure( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL); - base::RunLoop().RunUntilIdle(); - // We should keep listening to the task manager, even after a refresh. - RefreshTaskManager(); - EXPECT_TRUE(resource_reporter()->observed_task_manager()); - - // Memory pressure reduces to moderate again, we should stop watching the task - // manager. - monitor()->SetAndNotifyMemoryPressure( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_MODERATE); - base::RunLoop().RunUntilIdle(); - EXPECT_FALSE(resource_reporter()->observed_task_manager()); - - // Memory pressure becomes critical and we have violating tasks. - AddTasks(); - monitor()->SetAndNotifyMemoryPressure( - MemoryPressureLevel::MEMORY_PRESSURE_LEVEL_CRITICAL); - base::RunLoop().RunUntilIdle(); - EXPECT_TRUE(resource_reporter()->observed_task_manager()); - RefreshTaskManager(); - - // Make sure that the ResourceReporter is no longer listening to the task - // manager right after the refresh. - EXPECT_FALSE(resource_reporter()->observed_task_manager()); - - // Make sure the ResourceReporter is not tracking any but the tasks exceeding - // the defined resource use thresholds. - ASSERT_FALSE(resource_reporter()->task_records_.empty()); - for (const auto& task_record : resource_reporter()->task_records_) { - EXPECT_TRUE(task_record.cpu_percent >= - ResourceReporter::GetTaskCpuThresholdForReporting() || - task_record.memory_bytes >= - ResourceReporter::GetTaskMemoryThresholdForReporting()); - } - - // Make sure you have the right info about the Browser and GPU process. - EXPECT_DOUBLE_EQ(resource_reporter()->last_browser_process_cpu_, - kBrowserProcessCpu); - EXPECT_EQ(resource_reporter()->last_browser_process_memory_, - kBrowserProcessMemory); - EXPECT_DOUBLE_EQ(resource_reporter()->last_gpu_process_cpu_, kGpuProcessCpu); - EXPECT_EQ(resource_reporter()->last_gpu_process_memory_, kGpuProcessMemory); -} - -} // namespace chromeos
diff --git a/chrome/browser/enterprise/connectors/connectors_manager.h b/chrome/browser/enterprise/connectors/connectors_manager.h index ee06a40..97ebebb 100644 --- a/chrome/browser/enterprise/connectors/connectors_manager.h +++ b/chrome/browser/enterprise/connectors/connectors_manager.h
@@ -75,8 +75,17 @@ AnalysisConnector connector, AnalysisSettingsCallback callback); + // Public legacy functions. + // These functions are used to interact with legacy policies and should only + // be called while the connectors equivalent isn't available. They should be + // removed once legacy policies are deprecated. + + // Check a url against the corresponding URL patterns policies. + bool MatchURLAgainstLegacyDlpPolicies(const GURL& url, bool upload) const; + bool MatchURLAgainstLegacyMalwarePolicies(const GURL& url, bool upload) const; + private: - // Legacy functions. + // Private legacy functions. // These functions are used to interact with legacy policies and should stay // private. They should be removed once legacy policies are deprecated. @@ -90,8 +99,6 @@ bool LegacyBlockLargeFiles(bool upload) const; bool LegacyBlockUnsupportedFileTypes(bool upload) const; - bool MatchURLAgainstLegacyDlpPolicies(const GURL& url, bool upload) const; - bool MatchURLAgainstLegacyMalwarePolicies(const GURL& url, bool upload) const; std::set<std::string> MatchURLAgainstLegacyPolicies(const GURL& url, bool upload) const; };
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 4ee3fc7..1fc7936 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -114,7 +114,7 @@ }, { "name": "app-management", - "owners": [ "//chrome/browser/resources/app_management/OWNERS" ], + "owners": [ "//chrome/browser/ui/webui/app_management/OWNERS" ], "expiry_milestone": 81 }, {
diff --git a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc index 8761339..0788204 100644 --- a/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc +++ b/chrome/browser/media/webrtc/media_stream_devices_controller_browsertest.cc
@@ -172,7 +172,18 @@ return prompt_factory_.get(); } - private: + void VerifyResultState(blink::mojom::MediaStreamRequestResult result, + bool has_audio, + bool has_video) { + EXPECT_EQ(result, media_stream_result()); + EXPECT_EQ(has_audio, + CheckDevicesListContains( + blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); + EXPECT_EQ(has_video, + CheckDevicesListContains( + blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + } + void SetUpOnMainThread() override { WebRtcTestBase::SetUpOnMainThread(); @@ -702,13 +713,9 @@ // Check the media stream result is expected and the devices returned are // expected; - ASSERT_EQ(test.ExpectedMediaStreamResult(), media_stream_result()); - ASSERT_EQ(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE), - test.ExpectMicAllowed() && test.ExpectCamAllowed()); - ASSERT_EQ(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE), - test.ExpectMicAllowed() && test.ExpectCamAllowed()); + VerifyResultState(test.ExpectedMediaStreamResult(), + test.ExpectMicAllowed() && test.ExpectCamAllowed(), + test.ExpectMicAllowed() && test.ExpectCamAllowed()); } } @@ -721,11 +728,7 @@ ASSERT_EQ(0, prompt_factory()->TotalRequestCount()); - ASSERT_EQ(blink::mojom::MediaStreamRequestResult::OK, media_stream_result()); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - ASSERT_TRUE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, false, true); } IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, @@ -745,12 +748,7 @@ ASSERT_TRUE(prompt_factory()->RequestTypeSeen( permissions::PermissionRequestType::PERMISSION_MEDIASTREAM_MIC)); - // Accept the prompt. - ASSERT_EQ(blink::mojom::MediaStreamRequestResult::OK, media_stream_result()); - ASSERT_TRUE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - ASSERT_TRUE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, true, true); // Check that re-requesting allows without prompting. prompt_factory()->ResetCounts(); @@ -758,11 +756,7 @@ CreateRequest(example_audio_id(), example_video_id())); ASSERT_EQ(0, prompt_factory()->TotalRequestCount()); - ASSERT_EQ(blink::mojom::MediaStreamRequestResult::OK, media_stream_result()); - ASSERT_TRUE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - ASSERT_TRUE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, true, true); } IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, @@ -778,16 +772,12 @@ blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY)); ASSERT_EQ(0, prompt_factory()->TotalRequestCount()); - ASSERT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, - media_stream_result()); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + false, false); } IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, WebContentsDestroyed) { - InitWithUrl(GURL("http://www.example.com")); + InitWithUrl(embedded_test_server()->GetURL("/simple.html")); prompt_factory()->set_response_type( permissions::PermissionRequestManager::ACCEPT_ALL); @@ -801,12 +791,46 @@ RequestPermissions(nullptr, request); ASSERT_EQ(0, prompt_factory()->TotalRequestCount()); - ASSERT_EQ(blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, - media_stream_result()); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState( + blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false, + false); +} + +IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, + WebContentsDestroyedDuringRequest) { + InitWithUrl(embedded_test_server()->GetURL("/simple.html")); + ui_test_utils::NavigateToURLWithDisposition( + browser(), GURL("about:blank"), WindowOpenDisposition::NEW_BACKGROUND_TAB, + ui_test_utils::BROWSER_TEST_WAIT_FOR_TAB); + + prompt_factory()->set_response_type( + permissions::PermissionRequestManager::ACCEPT_ALL); + + content::WebContents* prompt_contents = GetWebContents(); + const int prompt_contents_index = + browser()->tab_strip_model()->GetIndexOfWebContents(prompt_contents); + + // Now request permissions, but before the callback is asynchronously called, + // destroy the tab. + permission_bubble_media_access_handler_->HandleRequest( + prompt_contents, CreateRequest(example_audio_id(), example_video_id()), + base::BindOnce([](const blink::MediaStreamDevices& devices, + blink::mojom::MediaStreamRequestResult result, + std::unique_ptr<content::MediaStreamUI> ui) { + ADD_FAILURE() << " this callback shouldn't be reached"; + }), + nullptr); + // Since the mock prompt factory holds a reference to the + // PermissionRequestManager for the WebContents and uses that reference in its + // destructor, it has to be destroyed before the tab. + prompt_factory_.reset(); + ASSERT_TRUE(browser()->tab_strip_model()->CloseWebContentsAt( + prompt_contents_index, TabStripModel::CloseTypes::CLOSE_USER_GESTURE)); + base::RunLoop().RunUntilIdle(); + + VerifyResultState( + blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS, false, + false); } // Request and block microphone and camera access with kill switch. @@ -832,13 +856,8 @@ CreateRequest(example_audio_id(), example_video_id())); ASSERT_EQ(0, prompt_factory()->TotalRequestCount()); - - ASSERT_EQ(blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON, - media_stream_result()); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState(blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON, + false, false); } IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, @@ -865,12 +884,8 @@ ASSERT_EQ(0, prompt_factory()->TotalRequestCount()); - ASSERT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, - media_stream_result()); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + false, false); EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); } @@ -899,12 +914,8 @@ ASSERT_EQ(0, prompt_factory()->TotalRequestCount()); - ASSERT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, - media_stream_result()); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - ASSERT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState(blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, + false, false); EXPECT_EQ(TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED, GetContentSettings()->GetMicrophoneCameraState()); } @@ -917,12 +928,7 @@ GetWebContents(), CreateRequestWithType(example_audio_id(), std::string(), blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY)); - - EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, media_stream_result()); - EXPECT_TRUE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - EXPECT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, true, false); } IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest, @@ -933,10 +939,5 @@ GetWebContents(), CreateRequestWithType(std::string(), example_video_id(), blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY)); - - EXPECT_EQ(blink::mojom::MediaStreamRequestResult::OK, media_stream_result()); - EXPECT_FALSE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE)); - EXPECT_TRUE(CheckDevicesListContains( - blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE)); + VerifyResultState(blink::mojom::MediaStreamRequestResult::OK, false, true); }
diff --git a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc index d53732e2..03632378 100644 --- a/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc +++ b/chrome/browser/media/webrtc/permission_bubble_media_access_handler.cc
@@ -294,6 +294,11 @@ bool blocked_by_feature_policy, ContentSetting audio_setting, ContentSetting video_setting) { + if (pending_requests_.find(web_contents) == pending_requests_.end()) { + // WebContents has been destroyed. Don't need to do anything. + return; + } + // If the kill switch is, or the request was blocked because of feature // policy we don't update the tab context. if (result != blink::mojom::MediaStreamRequestResult::KILL_SWITCH_ON &&
diff --git a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc index f72bf543..e57fad7d 100644 --- a/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc +++ b/chrome/browser/notifications/platform_notification_service_interactive_uitest.cc
@@ -15,6 +15,8 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/metrics/user_action_tester.h" #include "base/test/scoped_feature_list.h" +#include "base/test/scoped_run_loop_timeout.h" +#include "base/test/test_timeouts.h" #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/engagement/site_engagement_score.h" @@ -462,6 +464,10 @@ ASSERT_EQ(1u, notifications.size()); web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + // We see some timeouts in dbg tests, so increase the wait timeout to the + // test launcher's timeout. + const base::test::ScopedRunLoopTimeout specific_timeout( + FROM_HERE, TestTimeouts::test_launcher_timeout()); ASSERT_TRUE(content::WaitForLoadStop(web_contents)); // No engagement should be granted for clicking on the settings link.
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc index ac6d48a..ed8ff10 100644 --- a/chrome/browser/prefs/browser_prefs.cc +++ b/chrome/browser/prefs/browser_prefs.cc
@@ -314,7 +314,6 @@ #include "chrome/browser/chromeos/printing/enterprise_printers_provider.h" #include "chrome/browser/chromeos/printing/history/print_job_history_service.h" #include "chrome/browser/chromeos/release_notes/release_notes_storage.h" -#include "chrome/browser/chromeos/resource_reporter/resource_reporter.h" #include "chrome/browser/chromeos/settings/device_settings_cache.h" #include "chrome/browser/chromeos/system/automatic_reboot_manager.h" #include "chrome/browser/chromeos/system/input_device_settings.h" @@ -520,6 +519,21 @@ const char kAmbientModeTopicSource[] = "settings.ambient_mode.topic_source"; #endif // defined(OS_CHROMEOS) +// Register local state used only for migration (clearing or moving to a new +// key). +void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) { + registry->RegisterBooleanPref(kGCMChannelStatus, true); + registry->RegisterIntegerPref(kGCMChannelPollIntervalSeconds, 0); + registry->RegisterInt64Pref(kGCMChannelLastCheckTime, 0); + registry->RegisterListPref(kInvalidatorSavedInvalidations); + registry->RegisterStringPref(kInvalidatorInvalidationState, std::string()); + registry->RegisterStringPref(kInvalidatorClientId, std::string()); + +#if defined(OS_WIN) + registry->RegisterBooleanPref(kHasSeenWin10PromoPage, false); +#endif +} + // Register prefs used only for migration (clearing or moving to a new key). void RegisterProfilePrefsForMigration( user_prefs::PrefRegistrySyncable* registry) { @@ -690,7 +704,6 @@ RegisterLocalStatePrefs(registry); chromeos::Preferences::RegisterPrefs(registry); chromeos::ResetScreen::RegisterPrefs(registry); - chromeos::ResourceReporter::RegisterPrefs(registry); chromeos::SchedulerConfigurationManager::RegisterLocalStatePrefs(registry); chromeos::ServicesCustomizationDocument::RegisterPrefs(registry); chromeos::SigninScreenHandler::RegisterPrefs(registry); @@ -749,8 +762,6 @@ ModuleDatabase::RegisterLocalStatePrefs(registry); ThirdPartyConflictsManager::RegisterLocalStatePrefs(registry); #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) - - registry->RegisterBooleanPref(kHasSeenWin10PromoPage, false); // DEPRECATED #endif // defined(OS_WIN) #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) @@ -770,15 +781,7 @@ RegisterBrowserViewLocalPrefs(registry); #endif - // Obsolete. See MigrateObsoleteBrowserPrefs(). - registry->RegisterBooleanPref(kGCMChannelStatus, true); - registry->RegisterIntegerPref(kGCMChannelPollIntervalSeconds, 0); - registry->RegisterInt64Pref(kGCMChannelLastCheckTime, 0); - - // Obsolete. See MigrateObsoleteBrowserPrefs(). - registry->RegisterListPref(kInvalidatorSavedInvalidations); - registry->RegisterStringPref(kInvalidatorInvalidationState, std::string()); - registry->RegisterStringPref(kInvalidatorClientId, std::string()); + RegisterLocalStatePrefsForMigration(registry); } // Register prefs applicable to all profiles. @@ -1067,7 +1070,7 @@ #endif // This method should be periodically pruned of year+ old migrations. -void MigrateObsoleteBrowserPrefs(Profile* profile, PrefService* local_state) { +void MigrateObsoleteLocalStatePrefs(PrefService* local_state) { #if defined(OS_WIN) // Added 6/2019. local_state->ClearPref(kHasSeenWin10PromoPage);
diff --git a/chrome/browser/prefs/browser_prefs.h b/chrome/browser/prefs/browser_prefs.h index 05f6c20..bff02b1 100644 --- a/chrome/browser/prefs/browser_prefs.h +++ b/chrome/browser/prefs/browser_prefs.h
@@ -5,10 +5,9 @@ #ifndef CHROME_BROWSER_PREFS_BROWSER_PREFS_H_ #define CHROME_BROWSER_PREFS_BROWSER_PREFS_H_ -#include <set> +#include <string> #include "build/build_config.h" -#include "components/prefs/pref_value_store.h" class PrefRegistrySimple; class PrefService; @@ -41,8 +40,8 @@ // Migrate/cleanup deprecated prefs in |local_state|. Over time, long deprecated // prefs should be removed as new ones are added, but this call should never go // away (even if it becomes an empty call for some time) as it should remain -// *the* place to drop deprecated browser prefs at. -void MigrateObsoleteBrowserPrefs(Profile* profile, PrefService* local_state); +// *the* place to drop deprecated browser-level (Local State) prefs at. +void MigrateObsoleteLocalStatePrefs(PrefService* local_state); // Migrate/cleanup deprecated prefs in |profile|'s pref store. Over time, long // deprecated prefs should be removed as new ones are added, but this call
diff --git a/chrome/browser/profiles/profile.cc b/chrome/browser/profiles/profile.cc index aaf639ac..ba0a4ad 100644 --- a/chrome/browser/profiles/profile.cc +++ b/chrome/browser/profiles/profile.cc
@@ -423,6 +423,14 @@ observer.OnOffTheRecordProfileCreated(off_the_record); } +Profile* Profile::GetPrimaryOTRProfile() { + return GetOffTheRecordProfile(OTRProfileID::PrimaryID()); +} + +bool Profile::HasPrimaryOTRProfile() { + return HasOffTheRecordProfile(OTRProfileID::PrimaryID()); +} + variations::VariationsClient* Profile::GetVariationsClient() { if (!chrome_variations_client_) chrome_variations_client_ = std::make_unique<ChromeVariationsClient>(this);
diff --git a/chrome/browser/profiles/profile.h b/chrome/browser/profiles/profile.h index 4b47cd5..fd9b2978 100644 --- a/chrome/browser/profiles/profile.h +++ b/chrome/browser/profiles/profile.h
@@ -127,12 +127,16 @@ return profile_id_ < other.profile_id_; } + private: + friend std::ostream& operator<<(std::ostream& out, + const Profile::OTRProfileID& profile_id); + + OTRProfileID() = default; + // Returns this OTRProfileID in a string format that can be used for debug // message. const std::string& ToString() const; - private: - OTRProfileID() = default; const std::string profile_id_; }; @@ -223,6 +227,10 @@ // Returns all OffTheRecord profiles. virtual std::vector<Profile*> GetAllOffTheRecordProfiles() = 0; + // Returns the primary OffTheRecord profile. Creates the profile if it doesn't + // exist. + Profile* GetPrimaryOTRProfile(); + // Destroys the OffTheRecord profile. virtual void DestroyOffTheRecordProfile(Profile* otr_profile) = 0; @@ -239,6 +247,9 @@ // Returns true if the profile has any OffTheRecord profiles. virtual bool HasAnyOffTheRecordProfile() = 0; + // True if the primary OffTheRecord profile exists. + bool HasPrimaryOTRProfile(); + // Return the original "recording" profile. This method returns this if the // profile is not OffTheRecord. virtual Profile* GetOriginalProfile() = 0;
diff --git a/chrome/browser/profiles/profile_impl.cc b/chrome/browser/profiles/profile_impl.cc index 0a75e9d..5125dda 100644 --- a/chrome/browser/profiles/profile_impl.cc +++ b/chrome/browser/profiles/profile_impl.cc
@@ -981,9 +981,8 @@ void ProfileImpl::OnLocaleReady() { TRACE_EVENT0("browser", "ProfileImpl::OnLocaleReady"); + // Migrate obsolete prefs. - if (g_browser_process->local_state()) - MigrateObsoleteBrowserPrefs(this, g_browser_process->local_state()); MigrateObsoleteProfilePrefs(this); #if BUILDFLAG(ENABLE_EXTENSIONS) // Note: Extension preferences can be keyed off the extension ID, so need to
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn index 8aa05da..6377d719 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/BUILD.gn
@@ -400,6 +400,7 @@ "background/logging/log_store_test.js", "background/output_test.js", "background/recovery_strategy_test.js", + "background/smart_sticky_mode_test.js", "braille/braille_table_test.js", "braille/braille_translator_manager_test.js", "braille/liblouis_test.js",
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_state.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_state.js index ac6624ba..608df14 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_state.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/chromevox_state.js
@@ -150,3 +150,13 @@ ChromeVoxState.addObserver = function(observer) { ChromeVoxState.observers.push(observer); }; + +/** + * @param {ChromeVoxStateObserver} observer + */ +ChromeVoxState.removeObserver = function(observer) { + const index = ChromeVoxState.observers.indexOf(observer); + if (index > -1) { + ChromeVoxState.observers.splice(index, 1); + } +};
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode.js index 148075033..0e3c7ead 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode.js +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode.js
@@ -35,16 +35,42 @@ return; } - const isRangeEditable = - newRange.start.node.state[chrome.automation.StateType.EDITABLE]; + // Several cases arise which may lead to a sticky mode toggle: + // The node is either editable itself or a descendant of an editable. + // The node is a relation target of an editable. + const node = newRange.start.node; + let shouldTurnOffStickyMode = false; + if (node.state[chrome.automation.StateType.EDITABLE] || + (node.parent && + node.parent.state[chrome.automation.StateType.EDITABLE])) { + // This covers both editable nodes, and inline text boxes (which are not + // editable themselves, but may have an editable parent). + shouldTurnOffStickyMode = true; + } else { + let focus = node; + while (!shouldTurnOffStickyMode && focus) { + if (focus.activeDescendantFor && focus.activeDescendantFor.length) { + shouldTurnOffStickyMode |= focus.activeDescendantFor.some( + (n) => n.state[chrome.automation.StateType.EDITABLE]); + } - // This toggler should not make any changes when the range isn't editable - // and we haven't previously tracked any sticky mode state from the user. - if (!isRangeEditable && !this.didTurnOffStickyMode_) { + if (focus.controlledBy && focus.controlledBy.length) { + shouldTurnOffStickyMode |= focus.controlledBy.some( + (n) => n.state[chrome.automation.StateType.EDITABLE]); + } + + focus = focus.parent; + } + } + + // This toggler should not make any changes when the range isn't what we're + // lloking for and we haven't previously tracked any sticky mode state from + // the user. + if (!shouldTurnOffStickyMode && !this.didTurnOffStickyMode_) { return; } - if (isRangeEditable) { + if (shouldTurnOffStickyMode) { if (!ChromeVox.isStickyPrefOn) { // Sticky mode was already off; do not track the current sticky state // since we may have set it ourselves.
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode_test.js b/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode_test.js new file mode 100644 index 0000000..281eb5c --- /dev/null +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/background/smart_sticky_mode_test.js
@@ -0,0 +1,63 @@ +// 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 test fixture. +GEN_INCLUDE([ + '../testing/chromevox_next_e2e_test_base.js', '../testing/assert_additions.js' +]); + +/** + * Test fixture for SmartStickyMode. + */ +ChromeVoxSmartStickyModeTest = class extends ChromeVoxNextE2ETest {}; + +TEST_F('ChromeVoxSmartStickyModeTest', 'PossibleRangeTypes', function() { + this.runWithLoadedTree( + ` + <p>start</p> + <input aria-controls="controls-target" type="text"></input> + <textarea aria-activedescendant="active-descendant-target"></textarea> + <div contenteditable><h3>hello</h3></div> + <ul id="controls-target"><li>end</ul> + <ul id="active-descendant-target"><li>end</ul> + `, + function(root) { + const ssm = new SmartStickyMode(); + + // Deregister from actual range changes. + ChromeVoxState.removeObserver(ssm); + assertFalse(ssm.didTurnOffStickyMode_); + const [p, input, textarea, contenteditable, ul1, ul2] = root.children; + + function assertDidTurnOffForNode(node) { + ssm.onCurrentRangeChanged(cursors.Range.fromNode(node)); + assertTrue(ssm.didTurnOffStickyMode_); + } + + function assertDidNotTurnOffForNode(node) { + ssm.onCurrentRangeChanged(cursors.Range.fromNode(node)); + assertFalse(ssm.didTurnOffStickyMode_); + } + + // First, turn on sticky mode and try changing range to various parts of + // the document. + ChromeVoxBackground.setPref( + 'sticky', true /* value */, true /* announce */); + + assertDidTurnOffForNode(input); + assertDidTurnOffForNode(textarea); + assertDidNotTurnOffForNode(p); + + assertDidTurnOffForNode(contenteditable); + assertDidTurnOffForNode(ul1); + assertDidNotTurnOffForNode(p); + assertDidTurnOffForNode(ul2); + assertDidTurnOffForNode(ul1.firstChild); + assertDidNotTurnOffForNode(p); + assertDidTurnOffForNode(ul2.firstChild); + assertDidNotTurnOffForNode(p); + assertDidTurnOffForNode(contenteditable.find({role: 'heading'})); + assertDidTurnOffForNode(contenteditable.find({role: 'inlineTextBox'})); + }); +});
diff --git a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.html b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.html index a385ba0f..61fdaea 100644 --- a/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.html +++ b/chrome/browser/resources/chromeos/accessibility/chromevox/panel/panel.html
@@ -41,7 +41,10 @@ </div> </div> <div id="search-container"> - <input class="i18n" msgid="search_widget_intro" id="search" type="search"> + <input class="i18n" msgid="search_widget_intro" id="search" type="search" + aria-describedby="searchDescription"> + <div class="i18n" id="searchDescription" + msgid="search_widget_description"></div> </div> <div id="annotations-container" hidden> <input class="i18n" msgid="annotations_widget_intro" id="annotations"
diff --git a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp index 90c6cdf..cba15f7 100644 --- a/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp +++ b/chrome/browser/resources/chromeos/accessibility/strings/chromevox_strings.grdp
@@ -1504,6 +1504,9 @@ <message desc="Spoken when the search widget first shows." name="IDS_CHROMEVOX_SEARCH_WIDGET_INTRO"> Find in page </message> + <message desc="Instructions on how to use the ChromeVox find in page text input." name="IDS_CHROMEVOX_SEARCH_WIDGET_DESCRIPTION"> + Type to search the page. Press enter to jump to the result, up or down arrows to browse results, keep typing to change your search, or escape to cancel. + </message> <message desc="Category displayed in the options page under keyboard commands." name="IDS_CHROMEVOX_MODIFIER_KEYS"> Modifier Keys </message>
diff --git a/chrome/browser/resources/chromeos/login/images/1x/download_fail_illustration.svg b/chrome/browser/resources/chromeos/login/images/1x/download_fail_illustration.svg deleted file mode 100644 index 8dfbac96..0000000 --- a/chrome/browser/resources/chromeos/login/images/1x/download_fail_illustration.svg +++ /dev/null
@@ -1,16 +0,0 @@ -<svg version="1.1" viewBox="0 0 264 264" xmlns="http://www.w3.org/2000/svg"> - <g fill="none" fill-rule="evenodd"> - <path d="m171.6 82.336-6.413-6.413c-0.885-0.885-0.885-2.321 0-3.206l6.413-6.413c0.885-0.886 2.321-0.886 3.207 0l6.412 6.413c0.886 0.885 0.886 2.321 0 3.206l-6.412 6.413c-0.886 0.885-2.322 0.885-3.207 0" fill="#EA4335"/> - <path d="m105.87 48.101-6.413-6.413c-0.885-0.885-0.885-2.321 0-3.206l6.413-6.413c0.886-0.885 2.321-0.885 3.207 0l6.413 6.413c0.885 0.885 0.885 2.321 0 3.206l-6.413 6.413c-0.886 0.885-2.321 0.885-3.207 0" fill="#FBBC04"/> - <path d="m96.554 123.42 6.413-6.413c0.885-0.885 2.321-0.885 3.207 0l6.412 6.413c0.886 0.885 0.886 2.321 0 3.207l-6.412 6.412c-0.886 0.886-2.322 0.886-3.207 0l-6.413-6.412c-0.885-0.886-0.885-2.322 0-3.207" fill="#F1F3F4"/> - <path d="m129.01 65.679c-2.214-2.214-2.214-5.802 0-8.016l4.81-4.81c2.213-2.213 5.802-2.213 8.016 0 2.213 2.214 2.213 5.803 0 8.016l-4.81 4.81c-2.214 2.213-5.803 2.213-8.016 0" fill="#4285F4"/> - <path d="m133.77 102.36c-2.214-2.214-2.214-5.802 0-8.016l4.81-4.81c2.213-2.214 5.802-2.214 8.016 0 2.213 2.214 2.213 5.803 0 8.016l-4.81 4.81c-2.214 2.213-5.803 2.213-8.016 0" fill="#F1F3F4"/> - <path d="m146.85 97.289 0.741-0.741c2.214-2.214 2.214-5.802 0-8.016-2.213-2.213-5.803-2.213-8.016 0l-4.809 4.809c-0.745 0.745-1.217 1.651-1.461 2.602 4.621 0.068 9.146 0.527 13.545 1.346" fill="#FBBC04"/> - <path d="m87.07 75.282 11.947 3.201c1.686 0.452 2.25 2.559 1.016 3.793l-8.745 8.746c-1.235 1.234-3.342 0.67-3.794-1.016l-3.201-11.947c-0.452-1.686 1.091-3.229 2.777-2.777" fill="#34A853"/> - <path d="m151.38 118.92 11.947 3.201c1.686 0.452 2.25 2.559 1.016 3.793l-8.745 8.746c-1.235 1.234-3.342 0.67-3.794-1.016l-3.201-11.947c-0.452-1.686 1.091-3.229 2.777-2.777" fill="#F1F3F4"/> - <path d="m159 17c0 3.866-3.134 7-7 7s-7-3.134-7-7 3.134-7 7-7 7 3.134 7 7" fill="#34A853"/> - <path d="m212 175c0 44.183-35.817 80-80 80s-80-35.817-80-80 35.817-80 80-80 80 35.817 80 80z" stroke="#DADCE0" stroke-width="4"/> - <path d="m137 183.81 11.191-11.166 7.063 7.0791-23.394 23.341-23.393-23.341 7.0632-7.079 11.468 11.443v-35.086h10v34.809z" fill="#DADCE0" fill-rule="nonzero"/> - <path d="m101 151 62 62" stroke="#DADCE0" stroke-width="4"/> - </g> -</svg>
diff --git a/chrome/browser/resources/chromeos/login/images/2x/download_fail_illustration.svg b/chrome/browser/resources/chromeos/login/images/2x/download_fail_illustration.svg deleted file mode 100644 index 288fc539..0000000 --- a/chrome/browser/resources/chromeos/login/images/2x/download_fail_illustration.svg +++ /dev/null
@@ -1,16 +0,0 @@ -<svg version="1.1" viewBox="0 0 528 528" xmlns="http://www.w3.org/2000/svg"> - <g fill="none" fill-rule="evenodd"> - <path d="m343.21 164.67-12.826-12.826c-1.77-1.77-1.77-4.642 0-6.412l12.826-12.826c1.77-1.772 4.642-1.772 6.414 0l12.824 12.826c1.772 1.77 1.772 4.642 0 6.412l-12.824 12.826c-1.772 1.77-4.644 1.77-6.414 0" fill="#EA4335"/> - <path d="m211.74 96.202-12.826-12.826c-1.77-1.77-1.77-4.642 0-6.412l12.826-12.826c1.772-1.77 4.642-1.77 6.414 0l12.826 12.826c1.77 1.77 1.77 4.642 0 6.412l-12.826 12.826c-1.772 1.77-4.642 1.77-6.414 0" fill="#FBBC04"/> - <path d="m193.11 246.83 12.826-12.826c1.77-1.77 4.642-1.77 6.414 0l12.824 12.826c1.772 1.77 1.772 4.642 0 6.414l-12.824 12.824c-1.772 1.772-4.644 1.772-6.414 0l-12.826-12.824c-1.77-1.772-1.77-4.644 0-6.414" fill="#F1F3F4"/> - <path d="m258.02 131.36c-4.428-4.428-4.428-11.604 0-16.032l9.62-9.62c4.426-4.426 11.604-4.426 16.032 0 4.426 4.428 4.426 11.606 0 16.032l-9.62 9.62c-4.428 4.426-11.606 4.426-16.032 0" fill="#4285F4"/> - <path d="m267.53 204.72c-4.428-4.428-4.428-11.604 0-16.032l9.62-9.62c4.426-4.428 11.604-4.428 16.032 0 4.426 4.428 4.426 11.606 0 16.032l-9.62 9.62c-4.428 4.426-11.606 4.426-16.032 0" fill="#F1F3F4"/> - <path d="m293.7 194.58 1.482-1.482c4.428-4.428 4.428-11.604 0-16.032-4.426-4.426-11.606-4.426-16.032 0l-9.618 9.618c-1.49 1.49-2.434 3.302-2.922 5.204 9.242 0.136 18.292 1.054 27.09 2.692" fill="#FBBC04"/> - <path d="m174.14 150.56 23.894 6.402c3.372 0.904 4.5 5.118 2.032 7.586l-17.49 17.492c-2.47 2.468-6.684 1.34-7.588-2.032l-6.402-23.894c-0.904-3.372 2.182-6.458 5.554-5.554" fill="#34A853"/> - <path d="m302.77 237.85 23.894 6.402c3.372 0.904 4.5 5.118 2.032 7.586l-17.49 17.492c-2.47 2.468-6.684 1.34-7.588-2.032l-6.402-23.894c-0.904-3.372 2.182-6.458 5.554-5.554" fill="#F1F3F4"/> - <path d="m318 34c0 7.732-6.268 14-14 14s-14-6.268-14-14 6.268-14 14-14 14 6.268 14 14" fill="#34A853"/> - <path d="m424 350c0 88.366-71.634 160-160 160s-160-71.634-160-160 71.634-160 160-160 160 71.634 160 160z" stroke="#DADCE0" stroke-width="8"/> - <path d="m274 367.62 22.383-22.332 14.126 14.158-46.787 46.681-46.785-46.681 14.126-14.158 22.937 22.886v-70.172h20v69.618z" fill="#DADCE0" fill-rule="nonzero"/> - <path d="m202 302 124 124" stroke="#DADCE0" stroke-width="8"/> - </g> -</svg>
diff --git a/chrome/browser/resources/chromeos/login/oobe_eula.html b/chrome/browser/resources/chromeos/login/oobe_eula.html index c91edbb3c..1ff7069 100644 --- a/chrome/browser/resources/chromeos/login/oobe_eula.html +++ b/chrome/browser/resources/chromeos/login/oobe_eula.html
@@ -123,8 +123,8 @@ <webview slot="body" role="document" class="flex oobe-tos-webview" id="additionalChromeToSFrame"> </webview> - <oobe-text-button slot="button-container" inverse - on-click="hideToSDialog_" text-key="oobeModalDialogClose"> + <oobe-text-button id="close-additional-tos" slot="button-container" + on-click="hideToSDialog_" text-key="oobeModalDialogClose" inverse> </oobe-text-button> </cr-dialog> </template>
diff --git a/chrome/browser/resources/chromeos/login/oobe_eula.js b/chrome/browser/resources/chromeos/login/oobe_eula.js index d6b3cb67..3027716 100644 --- a/chrome/browser/resources/chromeos/login/oobe_eula.js +++ b/chrome/browser/resources/chromeos/login/oobe_eula.js
@@ -150,6 +150,11 @@ * @private */ onUsageChanged_() { + if (this.$.usageStats.checked) { + chrome.send('login.EulaScreen.userActed', ['select-stats-usage']); + } else { + chrome.send('login.EulaScreen.userActed', ['unselect-stats-usage']); + } this.screen.onUsageStatsClicked_(this.$.usageStats.checked); }, @@ -157,6 +162,7 @@ * @private */ onAdditionalTermsClicked_() { + chrome.send('login.EulaScreen.userActed', ['show-additional-tos']); this.$['additional-tos'].showModal(); }, @@ -182,6 +188,7 @@ * @private */ onInstallationSettingsClicked_() { + chrome.send('login.EulaScreen.userActed', ['show-security-settings']); chrome.send('eulaOnInstallationSettingsPopupOpened'); this.$.eulaDialog.hidden = true; this.$.installationSettingsDialog.hidden = false; @@ -205,6 +212,7 @@ * @private */ onUsageStatsHelpLinkClicked_(e) { + chrome.send('login.EulaScreen.userActed', ['show-stats-usage-learn-more']); this.$['learn-more'].focus(); chrome.send('eulaOnLearnMore'); e.stopPropagation();
diff --git a/chrome/browser/resources/chromeos/login/recommend_apps.css b/chrome/browser/resources/chromeos/login/recommend_apps.css index ba87a160..df985f4 100644 --- a/chrome/browser/resources/chromeos/login/recommend_apps.css +++ b/chrome/browser/resources/chromeos/login/recommend_apps.css
@@ -15,11 +15,7 @@ .recommend-apps-loading #app-list-error, .recommend-apps-loaded #recommend-apps-retry-button, .recommend-apps-loading #recommend-apps-install-button, -.recommend-apps-loading #recommend-apps-retry-button, -.error #subtitle, -.error #app-list-view-container, -.error .app-list-loading, -.error #recommend-apps-install-button { +.recommend-apps-loading #recommend-apps-retry-button { display: none; }
diff --git a/chrome/browser/resources/chromeos/login/recommend_apps.html b/chrome/browser/resources/chromeos/login/recommend_apps.html index 98ed6fa..4067e976 100644 --- a/chrome/browser/resources/chromeos/login/recommend_apps.html +++ b/chrome/browser/resources/chromeos/login/recommend_apps.html
@@ -18,16 +18,6 @@ <iron-icon src="chrome://oobe/playstore.svg" slot="oobe-icon"> </iron-icon> <div id="subtitle" slot="subtitle"></div> - <div id="app-list-error" slot="subtitle"> - [[i18nDynamic(locale, 'recommendAppsError')]] - </div> - <div slot="footer" class="flex layout vertical center center-justified" - id="download-fail-illustration"> - <img id="illustration" - srcset="images/1x/download_fail_illustration.svg 1x, - images/2x/download_fail_illustration.svg 2x" - class="oobe-illustration"> - </div> <div id="app-list-view-container" slot="footer"> <webview id="app-list-view"></webview> </div> @@ -41,9 +31,6 @@ <oobe-next-button id="recommend-apps-install-button" text-key="recommendAppsInstall" on-tap="onInstall_" inverse> </oobe-next-button> - <oobe-text-button id="recommend-apps-retry-button" - text-key="recommendAppsRetry" on-tap="onRetry_" border inverse> - </oobe-text-button> </div> </oobe-dialog> </template>
diff --git a/chrome/browser/resources/chromeos/login/recommend_apps.js b/chrome/browser/resources/chromeos/login/recommend_apps.js index 68fbea8..3943c0f 100644 --- a/chrome/browser/resources/chromeos/login/recommend_apps.js +++ b/chrome/browser/resources/chromeos/login/recommend_apps.js
@@ -40,11 +40,6 @@ this.screen.onInstall(); }, - /** @private */ - onRetry_() { - this.screen.onRetry(); - }, - /** * Returns element by its id. * @param id String The ID of the element.
diff --git a/chrome/browser/resources/chromeos/login/screen_recommend_apps.js b/chrome/browser/resources/chromeos/login/screen_recommend_apps.js index a73475c..14ebd0b9 100644 --- a/chrome/browser/resources/chromeos/login/screen_recommend_apps.js +++ b/chrome/browser/resources/chromeos/login/screen_recommend_apps.js
@@ -8,8 +8,7 @@ login.createScreen('RecommendAppsScreen', 'recommend-apps', function() { return { - EXTERNAL_API: - ['loadAppList', 'setThrobberVisible', 'setWebview', 'showError'], + EXTERNAL_API: ['loadAppList', 'setThrobberVisible', 'setWebview'], /** Initial UI State for screen */ getOobeUIInitialState() { @@ -83,21 +82,6 @@ window.addEventListener('message', this.onMessage); }, - /** - * Shows error UI when it fails to load the recommended app list. - */ - showError() { - this.ensureInitialized_(); - - // Hide the loading throbber and show the error message. - this.setThrobberVisible(false); - this.removeClass_('recommend-apps-loading'); - this.removeClass_('recommend-apps-loaded'); - this.addClass_('error'); - - this.getElement_('recommend-apps-retry-button').focus(); - }, - setWebview(contents) { const appListView = this.getElement_('app-list-view'); appListView.src = @@ -149,7 +133,6 @@ */ onGenerateContents() { this.removeClass_('recommend-apps-loading'); - this.removeClass_('error'); this.addClass_('recommend-apps-loaded'); this.getElement_('recommend-apps-install-button').focus(); }, @@ -177,18 +160,6 @@ }, /** - * Handles Retry button click. - */ - onRetry() { - this.setThrobberVisible(true); - this.removeClass_('recommend-apps-loaded'); - this.removeClass_('error'); - this.addClass_('recommend-apps-loading'); - - chrome.send('recommendAppsRetry'); - }, - - /** * Handles the message sent from the WebView. */ onMessage(event) {
diff --git a/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.html b/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.html index a440888..95141408 100644 --- a/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.html +++ b/chrome/browser/resources/settings/chromeos/os_search_page/os_search_page.html
@@ -45,7 +45,7 @@ padding-inline-end: 8px; } </style> - <settings-animated-pages id="pages" section="search" + <settings-animated-pages id="pages" section="osSearch" focus-config="[[focusConfig_]]"> <div route-path="default"> <!-- Omnibox and launcher search engine. This shares the same pref with
diff --git a/chrome/browser/resources/settings/privacy_page/security_page.js b/chrome/browser/resources/settings/privacy_page/security_page.js index 01a5a9fc..0e55018 100644 --- a/chrome/browser/resources/settings/privacy_page/security_page.js +++ b/chrome/browser/resources/settings/privacy_page/security_page.js
@@ -56,7 +56,7 @@ /** @private */ selectSafeBrowsingRadio_: { type: String, - computed: 'computeSelectSafeBrowsingRadio_(prefs.safeBrowsing.*)', + computed: 'computeSelectSafeBrowsingRadio_(prefs.safebrowsing.*)', }, /** @private {!settings.SafeBrowsingRadioManagedState} */
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc index aad902f..12637d9 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.cc
@@ -25,6 +25,7 @@ #include "base/time/time.h" #include "build/build_config.h" #include "chrome/browser/browser_process.h" +#include "chrome/browser/enterprise/connectors/connectors_manager.h" #include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h" #include "chrome/browser/file_util_service.h" #include "chrome/browser/profiles/profile.h" @@ -64,14 +65,6 @@ return factory.get(); } -// Determines if the completion callback should be called only after all the -// scan requests have finished and the verdicts known. -bool WaitForVerdict() { - int state = g_browser_process->local_state()->GetInteger( - prefs::kDelayDeliveryUntilVerdict); - return state == DELAY_UPLOADS || state == DELAY_UPLOADS_AND_DOWNLOADS; -} - // A BinaryUploadService::Request implementation that gets the data to scan // from a string. class StringSourceRequest : public BinaryUploadService::Request { @@ -149,26 +142,6 @@ return mime_type; } -bool AllowLargeFile() { - int state = g_browser_process->local_state()->GetInteger( - prefs::kBlockLargeFileTransfer); - return state != BLOCK_LARGE_UPLOADS && - state != BLOCK_LARGE_UPLOADS_AND_DOWNLOADS; -} - -bool AllowEncryptedFiles() { - int state = g_browser_process->local_state()->GetInteger( - prefs::kAllowPasswordProtectedFiles); - return state == ALLOW_UPLOADS || state == ALLOW_UPLOADS_AND_DOWNLOADS; -} - -bool AllowUnsupportedFileTypes() { - int state = g_browser_process->local_state()->GetInteger( - prefs::kBlockUnsupportedFiletypes); - return state != BLOCK_UNSUPPORTED_FILETYPES_UPLOADS && - state != BLOCK_UNSUPPORTED_FILETYPES_UPLOADS_AND_DOWNLOADS; -} - bool* UIEnabledStorage() { static bool enabled = true; return &enabled; @@ -252,8 +225,11 @@ RunCallback(); } +// static bool DeepScanningDialogDelegate::ResultShouldAllowDataUse( - BinaryUploadService::Result result) { + BinaryUploadService::Result result, + const enterprise_connectors::ConnectorsManager::AnalysisSettings& + settings) { // Keep this implemented as a switch instead of a simpler if statement so that // new values added to BinaryUploadService::Result cause a compiler error. switch (result) { @@ -270,13 +246,13 @@ return true; case BinaryUploadService::Result::FILE_TOO_LARGE: - return AllowLargeFile(); + return !settings.block_large_files; case BinaryUploadService::Result::FILE_ENCRYPTED: - return AllowEncryptedFiles(); + return !settings.block_password_protected_files; case BinaryUploadService::Result::UNSUPPORTED_FILE_TYPE: - return AllowUnsupportedFileTypes(); + return !settings.block_unsupported_file_types; } } @@ -300,15 +276,14 @@ (state == CHECK_UPLOADS || state == CHECK_UPLOADS_AND_DOWNLOADS); if (url.is_valid()) - data->url = url.spec(); - if (data->do_dlp_scan && - g_browser_process->local_state()->HasPrefPath( - prefs::kURLsToNotCheckComplianceOfUploadedContent)) { - const base::ListValue* filters = g_browser_process->local_state()->GetList( - prefs::kURLsToNotCheckComplianceOfUploadedContent); - url_matcher::URLMatcher matcher; - policy::url_util::AddAllowFilters(&matcher, filters); - data->do_dlp_scan = matcher.MatchURL(url).empty(); + data->url = url; + if (data->do_dlp_scan) { + // TODO(domfc): Instantiate the manager somewhere that can be accessed by + // both the upload and download paths instead. This is fine for now since + // the manager isn't caching anything. + data->do_dlp_scan = + enterprise_connectors::ConnectorsManager() + .MatchURLAgainstLegacyDlpPolicies(url, /*upload*/ true); } // See if malware checks are needed. @@ -320,17 +295,9 @@ (state == SEND_UPLOADS || state == SEND_UPLOADS_AND_DOWNLOADS); if (data->do_malware_scan) { - if (g_browser_process->local_state()->HasPrefPath( - prefs::kURLsToCheckForMalwareOfUploadedContent)) { - const base::ListValue* filters = - g_browser_process->local_state()->GetList( - prefs::kURLsToCheckForMalwareOfUploadedContent); - url_matcher::URLMatcher matcher; - policy::url_util::AddAllowFilters(&matcher, filters); - data->do_malware_scan = !matcher.MatchURL(url).empty(); - } else { - data->do_malware_scan = false; - } + data->do_malware_scan = + enterprise_connectors::ConnectorsManager() + .MatchURLAgainstLegacyMalwarePolicies(url, /*upload*/ true); } return data->do_dlp_scan || data->do_malware_scan; @@ -342,8 +309,36 @@ Data data, CompletionCallback callback, DeepScanAccessPoint access_point) { + enterprise_connectors::ConnectorsManager().GetAnalysisSettings( + data.url, enterprise_connectors::AnalysisConnector::FILE_ATTACHED, + base::BindOnce(&DeepScanningDialogDelegate::OnGotAnalysisSettings, + web_contents, std::move(data), std::move(callback), + access_point)); +} + +// static +void DeepScanningDialogDelegate::OnGotAnalysisSettings( + content::WebContents* web_contents, + Data data, + CompletionCallback callback, + DeepScanAccessPoint access_point, + base::Optional<enterprise_connectors::ConnectorsManager::AnalysisSettings> + settings) { + // Proceed with a scan after obtaining settings, otherwise complete with a + // positive result. + if (!settings.has_value()) { + Result result; + result.text_results = std::vector<bool>(data.text.size(), true); + result.paths_results = std::vector<bool>(data.paths.size(), true); + std::move(callback).Run(std::move(data), std::move(result)); + return; + } + + data.settings = std::move(settings.value()); + Factory* testing_factory = GetFactoryStorage(); - bool wait_for_verdict = WaitForVerdict(); + bool wait_for_verdict = data.settings.block_until_verdict == + enterprise_connectors::BlockUntilVerdict::BLOCK; // Using new instead of std::make_unique<> to access non public constructor. auto delegate = testing_factory->is_null() @@ -438,7 +433,7 @@ content_size, result, response); text_request_complete_ = true; - bool text_complies = ResultShouldAllowDataUse(result) && + bool text_complies = ResultShouldAllowDataUse(result, data_.settings) && DlpTriggeredRulesOK(response.dlp_scan_verdict()); std::fill(result_.text_results.begin(), result_.text_results.end(), text_complies); @@ -476,7 +471,8 @@ MalwareDeepScanningVerdict::CLEAN; } - bool file_complies = ResultShouldAllowDataUse(result) && dlp_ok && malware_ok; + bool file_complies = + ResultShouldAllowDataUse(result, data_.settings) && dlp_ok && malware_ok; result_.paths_results[index] = file_complies; ++file_result_count_; @@ -610,7 +606,7 @@ if (data_.do_dlp_scan) { DlpDeepScanningClientRequest dlp_request; dlp_request.set_content_source(trigger); - dlp_request.set_url(data_.url); + dlp_request.set_url(data_.url.spec()); request->set_request_dlp_scan(std::move(dlp_request)); }
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h index a2abc73..af57348f 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate.h
@@ -16,6 +16,7 @@ #include "base/memory/weak_ptr.h" #include "base/strings/string16.h" #include "base/time/time.h" +#include "chrome/browser/enterprise/connectors/connectors_manager.h" #include "chrome/browser/enterprise/connectors/enterprise_connectors_policy_handler.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/binary_upload_service.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h" @@ -77,13 +78,16 @@ bool do_malware_scan = false; // URL of the page that is to receive sensitive data. - std::string url; + GURL url; // Text data to scan, such as plain text, URLs, HTML content, etc. std::vector<base::string16> text; // List of files to scan. std::vector<base::FilePath> paths; + + // The settings to use for the analysis of the data in this struct. + enterprise_connectors::ConnectorsManager::AnalysisSettings settings; }; // Result of deep scanning. Each Result contains the verdicts of deep scans @@ -221,7 +225,10 @@ // Determines if a request result should be used to allow a data use or to // block it. - static bool ResultShouldAllowDataUse(BinaryUploadService::Result result); + static bool ResultShouldAllowDataUse( + BinaryUploadService::Result result, + const enterprise_connectors::ConnectorsManager::AnalysisSettings& + settings); protected: DeepScanningDialogDelegate(content::WebContents* web_contents, @@ -242,6 +249,15 @@ } private: + // Callback used to obtain analysis settings from the Connectors manager. + static void OnGotAnalysisSettings( + content::WebContents* web_contents, + Data data, + CompletionCallback callback, + DeepScanAccessPoint access_point, + base::Optional<enterprise_connectors::ConnectorsManager::AnalysisSettings> + settings); + // Uploads data for deep scanning. Returns true if uploading is occurring in // the background and false if there is nothing to do. bool UploadData();
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_browsertest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_browsertest.cc index 5ab3c9c..f1c7e14 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_browsertest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_browsertest.cc
@@ -8,6 +8,7 @@ #include "base/path_service.h" #include "base/stl_util.h" #include "base/test/bind_test_util.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.h" #include "chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_factory.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.h" @@ -19,6 +20,7 @@ #include "chrome/common/chrome_paths.h" #include "components/policy/core/common/cloud/mock_cloud_policy_client.h" #include "components/policy/core/common/cloud/realtime_reporting_job_configuration.h" +#include "components/prefs/scoped_user_pref_update.h" using extensions::SafeBrowsingPrivateEventRouter; using ::testing::_; @@ -162,6 +164,8 @@ constexpr char kDmToken[] = "dm_token"; +constexpr char kTestUrl[] = "https://google.com"; + } // namespace // Tests the behavior of the dialog delegate with minimal overriding of methods. @@ -182,6 +186,12 @@ SetWaitPolicy(DELAY_UPLOADS); SetUnsafeEventsReportingPolicy(true); + // Add the wildcard pattern to this policy since malware responses are + // verified for most of these tests. + ListPrefUpdate(g_browser_process->local_state(), + prefs::kURLsToCheckForMalwareOfUploadedContent) + ->Append("*"); + client_ = std::make_unique<policy::MockCloudPolicyClient>(); extensions::SafeBrowsingPrivateEventRouterFactory::GetForProfile( browser()->profile()) @@ -224,6 +234,8 @@ data.do_malware_scan = true; data.text.emplace_back(base::UTF8ToUTF16("foo")); data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.doc")); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); // Nothing should be reported for unauthorized users. ExpectNoReport(); @@ -255,16 +267,6 @@ IN_PROC_BROWSER_TEST_F(DeepScanningDialogDelegateBrowserTest, Files) { base::ScopedAllowBlockingForTesting allow_blocking; - // Create the files to be opened and scanned. - DeepScanningDialogDelegate::Data data; - data.do_dlp_scan = true; - data.do_malware_scan = true; - CreateFilesForTest({"ok.doc", "bad.exe"}, - {"ok file content", "bad file content"}, &data); - - FakeBinaryUploadServiceStorage()->SetAuthorized(true); - FakeBinaryUploadServiceStorage()->SetShouldAutomaticallyAuthorize(true); - // Set up delegate and upload service. EnableUploadsScanningAndReporting(); @@ -283,6 +285,18 @@ bad_response.mutable_malware_scan_verdict()->set_verdict( MalwareDeepScanningVerdict::MALWARE); + FakeBinaryUploadServiceStorage()->SetAuthorized(true); + FakeBinaryUploadServiceStorage()->SetShouldAutomaticallyAuthorize(true); + + // Create the files to be opened and scanned. + DeepScanningDialogDelegate::Data data; + data.do_dlp_scan = true; + data.do_malware_scan = true; + CreateFilesForTest({"ok.doc", "bad.exe"}, + {"ok file content", "bad file content"}, &data); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); + // The malware verdict means an event should be reported. EventReportValidator validator(client()); validator.ExpectDangerousDeepScanningResult( @@ -379,6 +393,8 @@ data.do_dlp_scan = true; data.do_malware_scan = true; data.paths.emplace_back(test_zip); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); // The file should be reported as unscanned. EventReportValidator validator(client()); @@ -450,15 +466,12 @@ Test) { base::ScopedAllowBlockingForTesting allow_blocking; - // Create the files with unsupported types. - DeepScanningDialogDelegate::Data data; - data.do_dlp_scan = true; - data.do_malware_scan = false; - CreateFilesForTest({"a.sh"}, {"file content"}, &data); - // Set up delegate and upload service. EnableUploadsScanningAndReporting(); SetBlockUnsupportedFileTypesPolicy(block_unsupported_file_types()); + ListPrefUpdate(g_browser_process->local_state(), + prefs::kURLsToCheckForMalwareOfUploadedContent) + ->Clear(); DeepScanningDialogDelegate::SetFactoryForTesting( base::BindRepeating(&MinimalFakeDeepScanningDialogDelegate::Create)); @@ -466,6 +479,14 @@ FakeBinaryUploadServiceStorage()->SetAuthorized(true); FakeBinaryUploadServiceStorage()->SetShouldAutomaticallyAuthorize(true); + // Create the files with unsupported types. + DeepScanningDialogDelegate::Data data; + data.do_dlp_scan = true; + data.do_malware_scan = false; + CreateFilesForTest({"a.sh"}, {"file content"}, &data); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); + // The file should be reported as unscanned. EventReportValidator validator(client()); validator.ExpectUnscannedFileEvent( @@ -541,14 +562,6 @@ Test) { base::ScopedAllowBlockingForTesting allow_blocking; - // Create the large file. - DeepScanningDialogDelegate::Data data; - data.do_dlp_scan = true; - data.do_malware_scan = true; - CreateFilesForTest( - {"large.doc"}, - {std::string(BinaryUploadService::kMaxUploadSizeBytes + 1, 'a')}, &data); - // Set up delegate and upload service. EnableUploadsScanningAndReporting(); SetBlockLargeFileTransferPolicy(block_large_file_transfer()); @@ -559,6 +572,17 @@ FakeBinaryUploadServiceStorage()->SetAuthorized(true); FakeBinaryUploadServiceStorage()->SetShouldAutomaticallyAuthorize(true); + // Create the large file. + DeepScanningDialogDelegate::Data data; + data.do_dlp_scan = true; + data.do_malware_scan = true; + + CreateFilesForTest( + {"large.doc"}, + {std::string(BinaryUploadService::kMaxUploadSizeBytes + 1, 'a')}, &data); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); + // The file should be reported as unscanned. EventReportValidator validator(client()); validator.ExpectUnscannedFileEvent( @@ -675,6 +699,8 @@ data.do_malware_scan = true; data.text.emplace_back(base::UTF8ToUTF16("text1")); data.text.emplace_back(base::UTF8ToUTF16("text2")); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); // Start test. DeepScanningDialogDelegate::ShowForWebContents(
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc index 18983de..0a0fc59 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_delegate_unittest.cc
@@ -1232,9 +1232,11 @@ data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.7z")); data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.bzip")); data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.cab")); + data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.csv")); data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.doc")); data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.docx")); data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.eps")); + data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.tar.gz")); data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.gzip")); data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.odt")); data.paths.emplace_back(FILE_PATH_LITERAL("/tmp/foo.pdf")); @@ -1262,8 +1264,8 @@ base::BindOnce( [](bool* called, const DeepScanningDialogDelegate::Data& data, const DeepScanningDialogDelegate::Result& result) { - EXPECT_EQ(21u, data.paths.size()); - EXPECT_EQ(21u, result.paths_results.size()); + EXPECT_EQ(23u, data.paths.size()); + EXPECT_EQ(23u, result.paths_results.size()); // The supported types should be marked as false. for (const auto& result : result.paths_results) @@ -1466,7 +1468,7 @@ bool expected = DeepScanningDialogDelegate::ResultShouldAllowDataUse( - GetParam()); + GetParam(), data.settings); EXPECT_EQ(expected, result.paths_results[0]); *called = true; }, @@ -1487,7 +1489,25 @@ BinaryUploadService::Result::UNAUTHORIZED, BinaryUploadService::Result::FILE_ENCRYPTED)); -using DeepScanningDialogDelegatePolicyResultsTest = BaseTest; +class DeepScanningDialogDelegatePolicyResultsTest : public BaseTest { + public: + enterprise_connectors::ConnectorsManager::AnalysisSettings settings() { + base::Optional<enterprise_connectors::ConnectorsManager::AnalysisSettings> + settings; + manager_.GetAnalysisSettings( + GURL(kTestUrl), enterprise_connectors::AnalysisConnector::FILE_ATTACHED, + base::BindLambdaForTesting( + [&settings]( + base::Optional< + enterprise_connectors::ConnectorsManager::AnalysisSettings> + tmp_settings) { settings = std::move(tmp_settings); })); + EXPECT_TRUE(settings.has_value()); + return std::move(settings.value()); + } + + private: + enterprise_connectors::ConnectorsManager manager_; +}; TEST_F(DeepScanningDialogDelegatePolicyResultsTest, BlockLargeFile) { // The value returned by ResultShouldAllowDataUse for FILE_TOO_LARGE should @@ -1495,19 +1515,19 @@ SetBlockLargeFilePolicy( BlockLargeFileTransferValues::BLOCK_LARGE_UPLOADS_AND_DOWNLOADS); EXPECT_FALSE(DeepScanningDialogDelegate::ResultShouldAllowDataUse( - BinaryUploadService::Result::FILE_TOO_LARGE)); + BinaryUploadService::Result::FILE_TOO_LARGE, settings())); SetBlockLargeFilePolicy(BlockLargeFileTransferValues::BLOCK_LARGE_DOWNLOADS); EXPECT_TRUE(DeepScanningDialogDelegate::ResultShouldAllowDataUse( - BinaryUploadService::Result::FILE_TOO_LARGE)); + BinaryUploadService::Result::FILE_TOO_LARGE, settings())); SetBlockLargeFilePolicy(BlockLargeFileTransferValues::BLOCK_LARGE_UPLOADS); EXPECT_FALSE(DeepScanningDialogDelegate::ResultShouldAllowDataUse( - BinaryUploadService::Result::FILE_TOO_LARGE)); + BinaryUploadService::Result::FILE_TOO_LARGE, settings())); SetBlockLargeFilePolicy(BlockLargeFileTransferValues::BLOCK_NONE); EXPECT_TRUE(DeepScanningDialogDelegate::ResultShouldAllowDataUse( - BinaryUploadService::Result::FILE_TOO_LARGE)); + BinaryUploadService::Result::FILE_TOO_LARGE, settings())); } TEST_F(DeepScanningDialogDelegatePolicyResultsTest, @@ -1517,19 +1537,19 @@ SetAllowPasswordPolicy( AllowPasswordProtectedFilesValues::ALLOW_UPLOADS_AND_DOWNLOADS); EXPECT_TRUE(DeepScanningDialogDelegate::ResultShouldAllowDataUse( - BinaryUploadService::Result::FILE_ENCRYPTED)); + BinaryUploadService::Result::FILE_ENCRYPTED, settings())); SetAllowPasswordPolicy(AllowPasswordProtectedFilesValues::ALLOW_DOWNLOADS); EXPECT_FALSE(DeepScanningDialogDelegate::ResultShouldAllowDataUse( - BinaryUploadService::Result::FILE_ENCRYPTED)); + BinaryUploadService::Result::FILE_ENCRYPTED, settings())); SetAllowPasswordPolicy(AllowPasswordProtectedFilesValues::ALLOW_UPLOADS); EXPECT_TRUE(DeepScanningDialogDelegate::ResultShouldAllowDataUse( - BinaryUploadService::Result::FILE_ENCRYPTED)); + BinaryUploadService::Result::FILE_ENCRYPTED, settings())); SetAllowPasswordPolicy(AllowPasswordProtectedFilesValues::ALLOW_NONE); EXPECT_FALSE(DeepScanningDialogDelegate::ResultShouldAllowDataUse( - BinaryUploadService::Result::FILE_ENCRYPTED)); + BinaryUploadService::Result::FILE_ENCRYPTED, settings())); } } // namespace safe_browsing
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views_browsertest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views_browsertest.cc index 4a722c9..a95c33dd 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views_browsertest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views_browsertest.cc
@@ -5,12 +5,14 @@ #include "base/test/bind_test_util.h" #include "base/test/metrics/histogram_tester.h" #include "build/build_config.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_browsertest_base.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_dialog_views.h" #include "chrome/browser/safe_browsing/cloud_content_scanning/fake_deep_scanning_dialog_delegate.h" #include "chrome/browser/ui/browser.h" #include "chrome/grit/generated_resources.h" #include "chrome/grit/theme_resources.h" +#include "components/prefs/scoped_user_pref_update.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/views/controls/image_view.h" @@ -427,6 +429,8 @@ DeepScanAccessPoint access_point() const { return std::get<2>(GetParam()); } }; +constexpr char kTestUrl[] = "https://google.com"; + } // namespace IN_PROC_BROWSER_TEST_P(DeepScanningDialogViewsBehaviorBrowserTest, Test) { @@ -448,6 +452,9 @@ if (malware_enabled()) { malware = malware_success(); SetMalwarePolicy(SEND_UPLOADS_AND_DOWNLOADS); + ListPrefUpdate(g_browser_process->local_state(), + prefs::kURLsToCheckForMalwareOfUploadedContent) + ->Append("*"); } SetStatusCallbackResponse( SimpleDeepScanningClientResponseForTesting(dlp, malware)); @@ -467,6 +474,8 @@ data.do_dlp_scan = dlp_enabled(); data.do_malware_scan = malware_enabled(); CreateFilesForTest({"foo.doc"}, {"content"}, &data); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); DeepScanningDialogDelegate::ShowForWebContents( browser()->tab_strip_model()->GetActiveWebContents(), std::move(data), @@ -536,6 +545,8 @@ data.do_malware_scan = false; CreateFilesForTest({"foo.doc", "bar.doc", "baz.doc"}, {"random", "file", "contents"}, &data); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); DeepScanningDialogDelegate::ShowForWebContents( browser()->tab_strip_model()->GetActiveWebContents(), std::move(data), @@ -584,6 +595,8 @@ data.text.emplace_back(base::UTF8ToUTF16("foo")); data.text.emplace_back(base::UTF8ToUTF16("bar")); CreateFilesForTest({"foo.doc", "bar.doc"}, {"file", "content"}, &data); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); DeepScanningDialogDelegate::ShowForWebContents( browser()->tab_strip_model()->GetActiveWebContents(), std::move(data), @@ -642,6 +655,8 @@ CreateFilesForTest({"foo.doc"}, {"content"}, &data); else data.text.emplace_back(base::UTF8ToUTF16("foo")); + ASSERT_TRUE(DeepScanningDialogDelegate::IsEnabled(browser()->profile(), + GURL(kTestUrl), &data)); DeepScanningDialogDelegate::ShowForWebContents( browser()->tab_strip_model()->GetActiveWebContents(), std::move(data),
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc index 981d34e..6efdeaf 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.cc
@@ -230,13 +230,14 @@ 50); } -std::array<const base::FilePath::CharType*, 21> SupportedDlpFileTypes() { +std::array<const base::FilePath::CharType*, 23> SupportedDlpFileTypes() { // Keep sorted for efficient access. - static constexpr const std::array<const base::FilePath::CharType*, 21> + static constexpr const std::array<const base::FilePath::CharType*, 23> kSupportedDLPFileTypes = { FILE_PATH_LITERAL(".7z"), FILE_PATH_LITERAL(".bzip"), - FILE_PATH_LITERAL(".cab"), FILE_PATH_LITERAL(".doc"), - FILE_PATH_LITERAL(".docx"), FILE_PATH_LITERAL(".eps"), + FILE_PATH_LITERAL(".cab"), FILE_PATH_LITERAL(".csv"), + FILE_PATH_LITERAL(".doc"), FILE_PATH_LITERAL(".docx"), + FILE_PATH_LITERAL(".eps"), FILE_PATH_LITERAL(".gz"), FILE_PATH_LITERAL(".gzip"), FILE_PATH_LITERAL(".odt"), FILE_PATH_LITERAL(".pdf"), FILE_PATH_LITERAL(".ppt"), FILE_PATH_LITERAL(".pptx"), FILE_PATH_LITERAL(".ps"),
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h index dafcbd0..776f0c63 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils.h
@@ -77,7 +77,7 @@ bool success); // Returns an array of the file types supported for DLP scanning. -std::array<const base::FilePath::CharType*, 21> SupportedDlpFileTypes(); +std::array<const base::FilePath::CharType*, 23> SupportedDlpFileTypes(); // Returns true if the given file type is supported for DLP scanning. bool FileTypeSupported(bool for_malware_scan,
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils_unittest.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils_unittest.cc index ff87d4d..25b80d6f 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils_unittest.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_utils_unittest.cc
@@ -73,8 +73,32 @@ testing::ValuesIn(kAllBinaryUploadServiceResults))); TEST_P(DeepScanningUtilsUMATest, SuccessfulScanVerdicts) { + // Record metrics for the 5 successful scan possibilities: + // - A default response + // - A DLP response with SUCCESS + // - A malware respopnse with MALWARE, UWS, CLEAN RecordDeepScanMetrics(access_point(), kDuration, kTotalBytes, result(), DeepScanningClientResponse()); + { + DlpDeepScanningVerdict dlp_verdict; + dlp_verdict.set_status(DlpDeepScanningVerdict::SUCCESS); + DeepScanningClientResponse response; + *response.mutable_dlp_scan_verdict() = dlp_verdict; + + RecordDeepScanMetrics(access_point(), kDuration, kTotalBytes, result(), + response); + } + for (const auto verdict : + {MalwareDeepScanningVerdict::MALWARE, MalwareDeepScanningVerdict::UWS, + MalwareDeepScanningVerdict::CLEAN}) { + MalwareDeepScanningVerdict malware_verdict; + malware_verdict.set_verdict(verdict); + DeepScanningClientResponse response; + *response.mutable_malware_scan_verdict() = malware_verdict; + + RecordDeepScanMetrics(access_point(), kDuration, kTotalBytes, result(), + response); + } if (result() == BinaryUploadService::Result::UNAUTHORIZED) { EXPECT_EQ( @@ -83,77 +107,83 @@ } else { // We expect at least 2 histograms (<access-point>.Duration and // <access-point>.<result>.Duration), but only expect a third histogram in - // the success case (bytes/seconds). + // the success case (bytes/seconds). Each of these should have 5 records to + // match each of the RecordDeepScanMetrics calls. uint64_t expected_histograms = success() ? 3u : 2u; - EXPECT_EQ( - expected_histograms, - histograms().GetTotalCountsForPrefix("SafeBrowsing.DeepScan.").size()); + auto recorded = + histograms().GetTotalCountsForPrefix("SafeBrowsing.DeepScan."); + EXPECT_EQ(expected_histograms, recorded.size()); if (success()) { - histograms().ExpectUniqueSample( - "SafeBrowsing.DeepScan." + access_point_string() + ".BytesPerSeconds", - kTotalBytes / kDuration.InSeconds(), 1); + EXPECT_EQ(recorded["SafeBrowsing.DeepScan." + access_point_string() + + ".BytesPerSeconds"], + 5); } - histograms().ExpectTimeBucketCount( - "SafeBrowsing.DeepScan." + access_point_string() + ".Duration", - kDuration, 1); - histograms().ExpectTimeBucketCount("SafeBrowsing.DeepScan." + - access_point_string() + "." + - result_value(true) + ".Duration", - kDuration, 1); + EXPECT_EQ(recorded["SafeBrowsing.DeepScan." + access_point_string() + + ".Duration"], + 5); + EXPECT_EQ(recorded["SafeBrowsing.DeepScan." + access_point_string() + "." + + result_value(true) + ".Duration"], + 5); } } -TEST_P(DeepScanningUtilsUMATest, UnsuccessfulDlpScanVerdict) { - DlpDeepScanningVerdict dlp_verdict; - dlp_verdict.set_status(DlpDeepScanningVerdict::FAILURE); - DeepScanningClientResponse response; - *response.mutable_dlp_scan_verdict() = dlp_verdict; +TEST_P(DeepScanningUtilsUMATest, UnsuccessfulDlpScanVerdicts) { + // Record metrics for the 2 unsuccessful DLP scan possibilities. + for (const auto verdict : {DlpDeepScanningVerdict::FAILURE, + DlpDeepScanningVerdict::STATUS_UNKNOWN}) { + DlpDeepScanningVerdict dlp_verdict; + dlp_verdict.set_status(verdict); + DeepScanningClientResponse response; + *response.mutable_dlp_scan_verdict() = dlp_verdict; - RecordDeepScanMetrics(access_point(), kDuration, kTotalBytes, result(), - response); + RecordDeepScanMetrics(access_point(), kDuration, kTotalBytes, result(), + response); + } if (result() == BinaryUploadService::Result::UNAUTHORIZED) { EXPECT_EQ( 0u, histograms().GetTotalCountsForPrefix("SafeBrowsing.DeepScan.").size()); } else { - EXPECT_EQ( - 2u, - histograms().GetTotalCountsForPrefix("SafeBrowsing.DeepScan.").size()); - histograms().ExpectTimeBucketCount( - "SafeBrowsing.DeepScan." + access_point_string() + ".Duration", - kDuration, 1); - histograms().ExpectTimeBucketCount("SafeBrowsing.DeepScan." + - access_point_string() + "." + - result_value(false) + ".Duration", - kDuration, 1); + auto recorded = + histograms().GetTotalCountsForPrefix("SafeBrowsing.DeepScan."); + EXPECT_EQ(2u, recorded.size()); + EXPECT_EQ(recorded["SafeBrowsing.DeepScan." + access_point_string() + + ".Duration"], + 2); + EXPECT_EQ(recorded["SafeBrowsing.DeepScan." + access_point_string() + "." + + result_value(false) + ".Duration"], + 2); } } TEST_P(DeepScanningUtilsUMATest, UnsuccessfulMalwareScanVerdict) { - MalwareDeepScanningVerdict malware_verdict; - malware_verdict.set_verdict(MalwareDeepScanningVerdict::VERDICT_UNSPECIFIED); - DeepScanningClientResponse response; - *response.mutable_malware_scan_verdict() = malware_verdict; + // Record metrics for the 2 unsuccessful malware scan possibilities. + for (const auto verdict : {MalwareDeepScanningVerdict::VERDICT_UNSPECIFIED, + MalwareDeepScanningVerdict::SCAN_FAILURE}) { + MalwareDeepScanningVerdict malware_verdict; + malware_verdict.set_verdict(verdict); + DeepScanningClientResponse response; + *response.mutable_malware_scan_verdict() = malware_verdict; - RecordDeepScanMetrics(access_point(), kDuration, kTotalBytes, result(), - response); + RecordDeepScanMetrics(access_point(), kDuration, kTotalBytes, result(), + response); + } if (result() == BinaryUploadService::Result::UNAUTHORIZED) { EXPECT_EQ( 0u, histograms().GetTotalCountsForPrefix("SafeBrowsing.DeepScan.").size()); } else { - EXPECT_EQ( - 2u, - histograms().GetTotalCountsForPrefix("SafeBrowsing.DeepScan.").size()); - histograms().ExpectTimeBucketCount( - "SafeBrowsing.DeepScan." + access_point_string() + ".Duration", - kDuration, 1); - histograms().ExpectTimeBucketCount("SafeBrowsing.DeepScan." + - access_point_string() + "." + - result_value(false) + ".Duration", - kDuration, 1); + auto recorded = + histograms().GetTotalCountsForPrefix("SafeBrowsing.DeepScan."); + EXPECT_EQ(2u, recorded.size()); + EXPECT_EQ(recorded["SafeBrowsing.DeepScan." + access_point_string() + + ".Duration"], + 2); + EXPECT_EQ(recorded["SafeBrowsing.DeepScan." + access_point_string() + "." + + result_value(false) + ".Duration"], + 2); } }
diff --git a/chrome/browser/service_process/service_process_control_browsertest.cc b/chrome/browser/service_process/service_process_control_browsertest.cc index b4a80e3..8fb8eff 100644 --- a/chrome/browser/service_process/service_process_control_browsertest.cc +++ b/chrome/browser/service_process/service_process_control_browsertest.cc
@@ -98,10 +98,14 @@ void SetUp() override { InProcessBrowserTest::SetUp(); +#if defined(OS_MACOSX) || defined(OS_LINUX) // This should not be needed because TearDown() ends with a closed // service_process_, but HistogramsTimeout and Histograms fail without this - // on Mac. + // on Mac, and on Linux asan builds (https://crbug.com/1059446). + // Note that closing the process handle means that the exit-code check in + // TearDown will be skipped. service_process_.Close(); +#endif } void TearDown() override {
diff --git a/chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc b/chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc index 77fd7c24..c6e9b80 100644 --- a/chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc +++ b/chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.cc
@@ -12,12 +12,13 @@ #include "base/syslog_logging.h" #include "base/values.h" #include "build/build_config.h" +#include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/common/pref_names.h" #include "components/policy/core/browser/policy_error_map.h" #include "components/policy/policy_constants.h" #include "components/prefs/pref_value_map.h" #include "components/spellcheck/browser/pref_names.h" -#include "components/spellcheck/common/spellcheck_common.h" +#include "components/spellcheck/common/spellcheck_features.h" #include "components/strings/grit/components_strings.h" SpellcheckLanguageBlacklistPolicyHandler:: @@ -113,9 +114,11 @@ // Separate the valid languages from the unknown / unsupported languages and // the languages that also appear in the SpellcheckLanguage policy. for (const base::Value& language : value->GetList()) { + std::string candidate_language = + base::TrimWhitespaceASCII(language.GetString(), base::TRIM_ALL) + .as_string(); std::string current_language = - spellcheck::GetCorrespondingSpellCheckLanguage( - base::TrimWhitespaceASCII(language.GetString(), base::TRIM_ALL)); + SpellcheckService::GetSupportedAcceptLanguageCode(candidate_language); if (current_language.empty()) { unknown->emplace_back(language.GetString());
diff --git a/chrome/browser/spellchecker/spellcheck_language_policy_handler.cc b/chrome/browser/spellchecker/spellcheck_language_policy_handler.cc index b5407f5..7724da7d 100644 --- a/chrome/browser/spellchecker/spellcheck_language_policy_handler.cc +++ b/chrome/browser/spellchecker/spellcheck_language_policy_handler.cc
@@ -11,12 +11,13 @@ #include "base/syslog_logging.h" #include "base/values.h" #include "build/build_config.h" +#include "chrome/browser/spellchecker/spellcheck_service.h" #include "chrome/common/pref_names.h" #include "components/policy/core/browser/policy_error_map.h" #include "components/policy/policy_constants.h" #include "components/prefs/pref_value_map.h" #include "components/spellcheck/browser/pref_names.h" -#include "components/spellcheck/common/spellcheck_common.h" +#include "components/spellcheck/common/spellcheck_features.h" #include "components/strings/grit/components_strings.h" SpellcheckLanguagePolicyHandler::SpellcheckLanguagePolicyHandler() @@ -86,9 +87,11 @@ // Separate the valid languages from the unknown / unsupported languages. for (const base::Value& language : value->GetList()) { + std::string candidate_language = + base::TrimWhitespaceASCII(language.GetString(), base::TRIM_ALL) + .as_string(); std::string current_language = - spellcheck::GetCorrespondingSpellCheckLanguage( - base::TrimWhitespaceASCII(language.GetString(), base::TRIM_ALL)); + SpellcheckService::GetSupportedAcceptLanguageCode(candidate_language); if (current_language.empty()) { unknown->emplace_back(language.GetString());
diff --git a/chrome/browser/spellchecker/spellcheck_language_policy_handlers_unittest.cc b/chrome/browser/spellchecker/spellcheck_language_policy_handlers_unittest.cc new file mode 100644 index 0000000..fd5ff6c2 --- /dev/null +++ b/chrome/browser/spellchecker/spellcheck_language_policy_handlers_unittest.cc
@@ -0,0 +1,207 @@ +// 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. + +// Chromium style is to have one unit test per one header file. However, the +// applied blocked spellcheck language policy depends on the applied forced +// language policy. If a language is both blocked and forced, forced wins. It is +// only practical to test this interaction in a single unit test covering both +// header files. +#include "chrome/browser/spellchecker/spellcheck_language_blacklist_policy_handler.h" +#include "chrome/browser/spellchecker/spellcheck_language_policy_handler.h" + +#include <ostream> +#include <string> +#include <vector> + +#include "base/strings/string_util.h" +#include "base/test/scoped_feature_list.h" +#include "base/values.h" +#include "chrome/common/pref_names.h" +#include "components/policy/core/common/policy_map.h" +#include "components/policy/policy_constants.h" +#include "components/prefs/pref_value_map.h" +#include "components/spellcheck/browser/pref_names.h" +#include "components/spellcheck/common/spellcheck_features.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace policy { + +struct TestCase { + TestCase(const std::vector<std::string>& blocked_languages, + const std::vector<std::string>& forced_languages, + const std::vector<std::string>& expected_blocked_languages, + const std::vector<std::string>& expected_forced_languages, + bool spellcheck_enabled, + bool windows_spellchecker_enabled) + : blocked_languages(blocked_languages), + forced_languages(forced_languages), + expected_blocked_languages(expected_blocked_languages), + expected_forced_languages(expected_forced_languages), + spellcheck_enabled(spellcheck_enabled), + windows_spellchecker_enabled(windows_spellchecker_enabled) {} + + std::vector<std::string> blocked_languages; + std::vector<std::string> forced_languages; + std::vector<std::string> expected_blocked_languages; + std::vector<std::string> expected_forced_languages; + bool spellcheck_enabled; + bool windows_spellchecker_enabled; +}; + +std::ostream& operator<<(std::ostream& out, const TestCase& test_case) { + out << "blocked_languages=[" + << base::JoinString(test_case.blocked_languages, ",") + << "], forced_languages=[" + << base::JoinString(test_case.forced_languages, ",") + << "], expected_blocked_languages=[" + << base::JoinString(test_case.expected_blocked_languages, ",") + << "], expected_forced_languages=[" + << base::JoinString(test_case.expected_forced_languages, ",") + << "], spellcheck_enabled=" << test_case.spellcheck_enabled + << "], windows_spellchecker_enabled=" + << test_case.windows_spellchecker_enabled; + return out; +} + +class SpellcheckLanguagePolicyHandlersTest + : public testing::TestWithParam<TestCase> { + public: + SpellcheckLanguagePolicyHandlersTest() = default; + ~SpellcheckLanguagePolicyHandlersTest() override = default; + + void CheckPrefs(const PrefValueMap& prefs, + const std::string& key, + const std::vector<std::string>& expected) { + // Retrieve the spellcheck enabled pref (if it exists). + const base::Value* spellcheck_enabled_pref = nullptr; + const bool is_spellcheck_enabled_pref_set = prefs.GetValue( + spellcheck::prefs::kSpellCheckEnable, &spellcheck_enabled_pref); + + const base::Value* languages_list = nullptr; + if (GetParam().spellcheck_enabled) { + EXPECT_TRUE(is_spellcheck_enabled_pref_set); + EXPECT_TRUE(spellcheck_enabled_pref->is_bool()); + EXPECT_TRUE(spellcheck_enabled_pref->GetBool()); + + EXPECT_TRUE(prefs.GetValue(key, &languages_list)); + EXPECT_TRUE(languages_list->is_list()); + EXPECT_EQ(expected.size(), languages_list->GetList().size()); + + for (const auto& language : languages_list->GetList()) { + EXPECT_TRUE(language.is_string()); + EXPECT_TRUE(std::find(expected.begin(), expected.end(), + language.GetString()) != expected.end()); + } + } else { + EXPECT_FALSE(is_spellcheck_enabled_pref_set); + // No language list should be added to prefs if spellchecking disabled. + EXPECT_FALSE(prefs.GetValue(key, &languages_list)); + } + } +}; + +TEST_P(SpellcheckLanguagePolicyHandlersTest, ApplyPolicySettings) { +#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER) + base::test::ScopedFeatureList feature_list; + if (GetParam().windows_spellchecker_enabled) { + if (!spellcheck::WindowsVersionSupportsSpellchecker()) + return; + + // Force hybrid spellchecking to be enabled. + feature_list.InitWithFeatures( + /*enabled_features=*/{spellcheck::kWinUseBrowserSpellChecker, + spellcheck::kWinUseHybridSpellChecker}, + /*disabled_features=*/{}); + } else { + // Hunspell-only spellcheck languages will be used. + feature_list.InitAndDisableFeature(spellcheck::kWinUseBrowserSpellChecker); + } +#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER) + + PrefValueMap prefs; + policy::PolicyMap policy; + + base::Value blocked_languages_list(base::Value::Type::LIST); + for (const auto& blocked_language : GetParam().blocked_languages) { + blocked_languages_list.Append(std::move(blocked_language)); + } + + base::Value forced_languages_list(base::Value::Type::LIST); + for (const auto& forced_language : GetParam().forced_languages) { + forced_languages_list.Append(std::move(forced_language)); + } + + policy.Set(policy::key::kSpellcheckLanguageBlacklist, + policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, + policy::POLICY_SOURCE_ENTERPRISE_DEFAULT, + base::Value::ToUniquePtrValue(std::move(blocked_languages_list)), + nullptr); + + policy.Set( + policy::key::kSpellcheckLanguage, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_ENTERPRISE_DEFAULT, + base::Value::ToUniquePtrValue(std::move(forced_languages_list)), nullptr); + + policy.Set( + policy::key::kSpellcheckEnabled, policy::POLICY_LEVEL_MANDATORY, + policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_ENTERPRISE_DEFAULT, + std::make_unique<base::Value>(GetParam().spellcheck_enabled), nullptr); + + // Apply policy to the forced languages handler. + SpellcheckLanguagePolicyHandler forced_languages_handler; + forced_languages_handler.ApplyPolicySettings(policy, &prefs); + + // Apply policy to the blocked languages handler. + SpellcheckLanguageBlacklistPolicyHandler blocked_languages_handler; + blocked_languages_handler.ApplyPolicySettings(policy, &prefs); + + // Check if forced languages preferences are as expected. + CheckPrefs(prefs, spellcheck::prefs::kSpellCheckForcedDictionaries, + GetParam().expected_forced_languages); + + // Check if blocked languages preferences are as expected. + CheckPrefs(prefs, spellcheck::prefs::kSpellCheckBlacklistedDictionaries, + GetParam().expected_blocked_languages); +} + +INSTANTIATE_TEST_SUITE_P( + TestCases, + SpellcheckLanguagePolicyHandlersTest, + testing::Values( +#if BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER) + // Test cases for Windows spellchecker (policy languages not restricted + // to Hunspell). + TestCase({"ar-SA", "es-MX", "fi", "fr", + "not-a-language"} /* blocked languages */, + {"fi", "fr", "not-another-language"} /* forced languages */, + {"ar", "es-MX"} /* expected blocked languages */, + {"fi", "fr"} /* expected forced languages */, + true /* spellcheck enabled */, + true /* windows spellchecker enabled */), + TestCase({"ar-SA", "es-MX", "fi", "fr "} /* blocked languages */, + {"fi", "fr"} /* forced languages */, + {""} /* expected blocked languages */, + {""} /* expected forced languages */, + false /* spellcheck enabled */, + true /* windows spellchecker enabled */), +#endif // BUILDFLAG(USE_WIN_HYBRID_SPELLCHECKER) + // Test cases for Hunspell only spellchecker. ar-SA and fi are + // non-Hunspell languages so are ignored for policy enforcement. If they + // ever obtain Hunspell support, the first test case below will fail. + TestCase({"ar-SA", "es-MX", "fi", "fr", + "not-a-language"} /* blocked languages */, + {"fi", "fr", "not-another-language"} /* forced languages */, + {"es-MX"} /* expected blocked languages */, + {"fr"} /* expected forced languages */, + true /* spellcheck enabled */, + false /* windows spellchecker enabled */), + TestCase({"ar-SA", "es-MX", "fi", "fr", + "not-a-language"} /* blocked languages */, + {"fi", "fr", "not-another-language"} /* forced languages */, + {""} /* expected blocked languages */, + {""} /* expected forced languages */, + false /* spellcheck enabled */, + false /* windows spellchecker enabled */))); + +} // namespace policy
diff --git a/chrome/browser/spellchecker/spellcheck_service.cc b/chrome/browser/spellchecker/spellcheck_service.cc index 7d3ddb7..4aea771d 100644 --- a/chrome/browser/spellchecker/spellcheck_service.cc +++ b/chrome/browser/spellchecker/spellcheck_service.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/spellchecker/spellcheck_service.h" #include <algorithm> +#include <iterator> #include <set> #include <utility> @@ -38,6 +39,7 @@ #include "content/public/browser/render_process_host.h" #include "content/public/browser/storage_partition.h" #include "mojo/public/cpp/bindings/remote.h" +#include "ui/base/l10n/l10n_util.h" #if defined(OS_WIN) && BUILDFLAG(USE_BROWSER_SPELLCHECKER) #include "base/task/post_task.h" @@ -200,6 +202,84 @@ return true; } +// static +std::string SpellcheckService::GetSupportedAcceptLanguageCode( + const std::string& supported_language_full_tag) { + // Default to accept language in hardcoded list of Hunspell dictionaries + // (kSupportedSpellCheckerLanguages). + std::string supported_accept_language = + spellcheck::GetCorrespondingSpellCheckLanguage( + supported_language_full_tag); + +#if defined(OS_WIN) + if (!spellcheck::UseWinHybridSpellChecker()) + return supported_accept_language; + + // Collect the hardcoded list of accept-languages supported by the browser, + // that is, languages that can be added as preferred languages in the + // languages settings page. + std::vector<std::string> accept_languages; + l10n_util::GetAcceptLanguages(&accept_languages); + + // First try exact match. Per BCP47, tags are in ASCII and should be treated + // as case-insensitive (although there are conventions for the capitalization + // of subtags). + auto iter = + std::find_if(accept_languages.begin(), accept_languages.end(), + [supported_language_full_tag](const auto& accept_language) { + return base::EqualsCaseInsensitiveASCII( + supported_language_full_tag, accept_language); + }); + if (iter != accept_languages.end()) + return *iter; + + // Then try matching just the language and (optional) script subtags, but + // not the region subtag. For example, Edge supports sr-Cyrl-RS as an accept + // language, but not sr-Cyrl-CS. Matching language + script subtags assures + // we get the correct script for spellchecking, and not use sr-Latn-RS if + // language packs for both scripts are installed on the system. + if (!base::Contains(supported_language_full_tag, "-")) + return ""; + + iter = + std::find_if(accept_languages.begin(), accept_languages.end(), + [supported_language_full_tag](const auto& accept_language) { + return base::EqualsCaseInsensitiveASCII( + SpellcheckService::GetLanguageAndScriptTag( + supported_language_full_tag, + /* include_script_tag */ true), + SpellcheckService::GetLanguageAndScriptTag( + accept_language, + /* include_script_tag */ true)); + }); + + if (iter != accept_languages.end()) + return *iter; + + // Then try just matching the leading language subtag. E.g. Edge supports + // kok as an accept language, but if the Konkani language pack is + // installed the Windows spellcheck API reports kok-Deva-IN for the + // dictionary name. + iter = + std::find_if(accept_languages.begin(), accept_languages.end(), + [supported_language_full_tag](const auto& accept_language) { + return base::EqualsCaseInsensitiveASCII( + SpellcheckService::GetLanguageAndScriptTag( + supported_language_full_tag, + /* include_script_tag */ false), + SpellcheckService::GetLanguageAndScriptTag( + accept_language, + /* include_script_tag */ false)); + }); + + if (iter != accept_languages.end()) + return *iter; + +#endif // defined(OS_WIN) + + return supported_accept_language; +} + void SpellcheckService::StartRecordingMetrics(bool spellcheck_enabled) { metrics_ = std::make_unique<SpellCheckHostMetrics>(); metrics_->RecordEnabledStats(spellcheck_enabled); @@ -361,6 +441,33 @@ } // static +std::string SpellcheckService::GetLanguageAndScriptTag( + const std::string& full_tag, + bool include_script_tag) { + std::string language_and_script_tag; + + std::vector<std::string> subtags = base::SplitString( + full_tag, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + // Language subtag is required, all others optional. + DCHECK_GE(subtags.size(), 1ULL); + std::vector<std::string> subtag_tokens_to_pass; + subtag_tokens_to_pass.push_back(subtags.front()); + subtags.erase(subtags.begin()); + + // The optional script subtag always follows the language subtag, and is 4 + // characters in length. + if (include_script_tag) { + if (!subtags.empty() && subtags.front().length() == 4) { + subtag_tokens_to_pass.push_back(subtags.front()); + } + } + + language_and_script_tag = base::JoinString(subtag_tokens_to_pass, "-"); + + return language_and_script_tag; +} + +// static void SpellcheckService::AttachStatusEvent(base::WaitableEvent* status_event) { DCHECK_CURRENTLY_ON(BrowserThread::UI);
diff --git a/chrome/browser/spellchecker/spellcheck_service.h b/chrome/browser/spellchecker/spellcheck_service.h index 803c7da..97df1313 100644 --- a/chrome/browser/spellchecker/spellcheck_service.h +++ b/chrome/browser/spellchecker/spellcheck_service.h
@@ -94,6 +94,13 @@ // when we do not set an event to |status_event_|. static bool SignalStatusEvent(EventType type); + // Get the best match of a supported accept language code for the provided + // language tag. Returns an empty string if no match is found. Method cannot + // be defined in spellcheck_common.h as it depends on l10n_util, and code + // under components cannot depend on ui/base. + static std::string GetSupportedAcceptLanguageCode( + const std::string& supported_language_full_tag); + // Instantiates SpellCheckHostMetrics object and makes it ready for recording // metrics. This should be called only if the metrics recording is active. void StartRecordingMetrics(bool spellcheck_enabled); @@ -161,6 +168,11 @@ private: FRIEND_TEST_ALL_PREFIXES(SpellcheckServiceBrowserTest, DeleteCorruptedBDICT); + // Parses a full BCP47 language tag to return just the language subtag, + // optionally with a hyphen and script subtag appended. + static std::string GetLanguageAndScriptTag(const std::string& full_tag, + bool include_script_tag); + // Attaches an event so browser tests can listen the status events. static void AttachStatusEvent(base::WaitableEvent* status_event);
diff --git a/chrome/browser/ssl/tls_deprecation_config.cc b/chrome/browser/ssl/tls_deprecation_config.cc index 05e247b..335c015 100644 --- a/chrome/browser/ssl/tls_deprecation_config.cc +++ b/chrome/browser/ssl/tls_deprecation_config.cc
@@ -33,6 +33,8 @@ return proto_.get(); } + void Reset() { proto_.reset(); } + static TLSDeprecationConfigSingleton& GetInstance() { static base::NoDestructor<TLSDeprecationConfigSingleton> instance; return *instance; @@ -77,3 +79,7 @@ return lower != control_site_hashes.end() && *lower == host_hash; } + +void ResetTLSDeprecationConfigForTesting() { + TLSDeprecationConfigSingleton::GetInstance().Reset(); +}
diff --git a/chrome/browser/ssl/tls_deprecation_config.h b/chrome/browser/ssl/tls_deprecation_config.h index edee244..613a1c7 100644 --- a/chrome/browser/ssl/tls_deprecation_config.h +++ b/chrome/browser/ssl/tls_deprecation_config.h
@@ -13,4 +13,6 @@ bool ShouldSuppressLegacyTLSWarning(const GURL& url); +void ResetTLSDeprecationConfigForTesting(); + #endif // CHROME_BROWSER_SSL_TLS_DEPRECATION_CONFIG_H_
diff --git a/chrome/browser/ssl/tls_deprecation_config_unittest.cc b/chrome/browser/ssl/tls_deprecation_config_unittest.cc index a0ee9030..239ed8b 100644 --- a/chrome/browser/ssl/tls_deprecation_config_unittest.cc +++ b/chrome/browser/ssl/tls_deprecation_config_unittest.cc
@@ -14,14 +14,19 @@ using chrome_browser_ssl::LegacyTLSExperimentConfig; +class TLSDeprecationConfigTest : public testing::Test { + protected: + void TearDown() override { ResetTLSDeprecationConfigForTesting(); } +}; + // Tests the case where no proto has been set by the component installer. -TEST(TLSDeprecationConfigTest, NoProto) { +TEST_F(TLSDeprecationConfigTest, NoProto) { EXPECT_TRUE(ShouldSuppressLegacyTLSWarning(GURL("https://example.test"))); } // This tests that when no sites are in the control set, // IsTLSDeprecationControlSite() returns false. -TEST(TLSDeprecationConfigTest, NoControlSites) { +TEST_F(TLSDeprecationConfigTest, NoControlSites) { GURL control_site("https://control.test"); std::string control_site_hex = "f12b47771bb3c2bcc85a5347d195523013ec5a23b4c761b5d6aacf04bafc5e23"; @@ -38,7 +43,7 @@ // This tests that when only a single control site is in the control set, // IsTLSDeprecationControlSite() works correctly for the site in the control and // for sites not in the control. -TEST(TLSDeprecationConfigTest, SingleControlSite) { +TEST_F(TLSDeprecationConfigTest, SingleControlSite) { GURL control_site("https://control.test"); std::string control_site_hex = "f12b47771bb3c2bcc85a5347d195523013ec5a23b4c761b5d6aacf04bafc5e23"; @@ -65,7 +70,7 @@ // This tests that the binary search in IsTLSDeprecationControlSite() works for // both a site that is in the control set and a site that is not. -TEST(TLSDeprecationConfigTest, ManyControlSites) { +TEST_F(TLSDeprecationConfigTest, ManyControlSites) { const struct { GURL url; std::string hash;
diff --git a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc index bdefbf76..062d5c47 100644 --- a/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc +++ b/chrome/browser/sync/test/integration/single_client_user_events_sync_test.cc
@@ -89,13 +89,7 @@ EXPECT_TRUE(ExpectUserEvents({specifics1, specifics1, specifics2})); } -// Flaky (mostly) on ASan/TSan. http://crbug.com/998130 -#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) -#define MAYBE_RetryParallel DISABLED_RetryParallel -#else -#define MAYBE_RetryParallel RetryParallel -#endif -IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, MAYBE_RetryParallel) { +IN_PROC_BROWSER_TEST_F(SingleClientUserEventsSyncTest, RetryParallel) { ASSERT_TRUE(SetupSync()); const UserEventSpecifics specifics1 = @@ -115,7 +109,7 @@ UserEventSpecifics retry_specifics; GetFakeServer()->OverrideResponseType(base::BindLambdaForTesting( [&](const syncer::LoopbackServerEntity& entity) { - if (first) { + if (first && entity.GetModelType() == syncer::USER_EVENTS) { first = false; SyncEntity sync_entity; entity.SerializeAsProto(&sync_entity);
diff --git a/chrome/browser/task_manager/mock_web_contents_task_manager.cc b/chrome/browser/task_manager/mock_web_contents_task_manager.cc index c11f0d0..5f94aef 100644 --- a/chrome/browser/task_manager/mock_web_contents_task_manager.cc +++ b/chrome/browser/task_manager/mock_web_contents_task_manager.cc
@@ -7,15 +7,11 @@ #include "base/stl_util.h" #include "build/build_config.h" -#if defined(OS_CHROMEOS) -#include "chrome/browser/chromeos/resource_reporter/resource_reporter.h" -#endif // defined(OS_CHROMEOS) - namespace task_manager { -MockWebContentsTaskManager::MockWebContentsTaskManager() {} +MockWebContentsTaskManager::MockWebContentsTaskManager() = default; -MockWebContentsTaskManager::~MockWebContentsTaskManager() {} +MockWebContentsTaskManager::~MockWebContentsTaskManager() = default; void MockWebContentsTaskManager::TaskAdded(Task* task) { DCHECK(task); @@ -30,12 +26,6 @@ } void MockWebContentsTaskManager::StartObserving() { -#if defined(OS_CHROMEOS) - // On ChromeOS, the ResourceReporter needs to be turned off so as not to - // interfere with the tests. - chromeos::ResourceReporter::GetInstance()->StopMonitoring(); -#endif // defined(OS_CHROMEOS) - provider_.SetObserver(this); }
diff --git a/chrome/browser/task_manager/providers/arc/arc_process_task.cc b/chrome/browser/task_manager/providers/arc/arc_process_task.cc index 0d56a32..1db9d91 100644 --- a/chrome/browser/task_manager/providers/arc/arc_process_task.cc +++ b/chrome/browser/task_manager/providers/arc/arc_process_task.cc
@@ -74,7 +74,6 @@ ArcProcessTask::ArcProcessTask(arc::ArcProcess arc_process) : Task(MakeTitle(arc_process), - arc_process.process_name(), nullptr /* icon */, arc_process.pid()), arc_process_(std::move(arc_process)) {
diff --git a/chrome/browser/task_manager/providers/browser_process_task.cc b/chrome/browser/task_manager/providers/browser_process_task.cc index bb3cc21..b4d1229 100644 --- a/chrome/browser/task_manager/providers/browser_process_task.cc +++ b/chrome/browser/task_manager/providers/browser_process_task.cc
@@ -16,7 +16,6 @@ BrowserProcessTask::BrowserProcessTask() : Task(l10n_util::GetStringUTF16(IDS_TASK_MANAGER_WEB_BROWSER_CELL_TEXT), - "Browser Process", FetchIcon(IDR_PRODUCT_LOGO_16, &s_icon_), base::GetCurrentProcessHandle()), used_sqlite_memory_(-1) {}
diff --git a/chrome/browser/task_manager/providers/child_process_task.cc b/chrome/browser/task_manager/providers/child_process_task.cc index 73f9204..4815516d1 100644 --- a/chrome/browser/task_manager/providers/child_process_task.cc +++ b/chrome/browser/task_manager/providers/child_process_task.cc
@@ -162,7 +162,6 @@ ChildProcessTask::ChildProcessTask(const content::ChildProcessData& data) : Task(GetLocalizedTitle(data.name, data.process_type), - base::UTF16ToUTF8(data.name), FetchIcon(IDR_PLUGINS_FAVICON, &s_icon_), data.GetProcess().Handle()), process_resources_sampler_(CreateProcessResourcesSampler(data.id)),
diff --git a/chrome/browser/task_manager/providers/fallback_task_provider_unittest.cc b/chrome/browser/task_manager/providers/fallback_task_provider_unittest.cc index 579bb30..3ff32615 100644 --- a/chrome/browser/task_manager/providers/fallback_task_provider_unittest.cc +++ b/chrome/browser/task_manager/providers/fallback_task_provider_unittest.cc
@@ -21,7 +21,6 @@ public: FakeTask(base::ProcessId process_id, Type type, const std::string& title) : Task(base::ASCIIToUTF16(title), - "FakeTask", nullptr, base::kNullProcessHandle, process_id),
diff --git a/chrome/browser/task_manager/providers/task.cc b/chrome/browser/task_manager/providers/task.cc index 1c96046..bb974882 100644 --- a/chrome/browser/task_manager/providers/task.cc +++ b/chrome/browser/task_manager/providers/task.cc
@@ -34,7 +34,6 @@ } // namespace Task::Task(const base::string16& title, - const std::string& rappor_sample, const gfx::ImageSkia* icon, base::ProcessHandle handle, base::ProcessId process_id) @@ -46,12 +45,11 @@ network_sent_rate_(0), network_read_rate_(0), title_(title), - rappor_sample_name_(rappor_sample), icon_(icon ? *icon : gfx::ImageSkia()), process_handle_(handle), process_id_(DetermineProcessId(handle, process_id)) {} -Task::~Task() {} +Task::~Task() = default; // static base::string16 Task::GetProfileNameFromProfile(Profile* profile) {
diff --git a/chrome/browser/task_manager/providers/task.h b/chrome/browser/task_manager/providers/task.h index 61d32b0..f503e46e 100644 --- a/chrome/browser/task_manager/providers/task.h +++ b/chrome/browser/task_manager/providers/task.h
@@ -60,11 +60,9 @@ }; // Create a task with the given |title| and the given favicon |icon|. This - // task runs on a process whose handle is |handle|. |rappor_sample| is the - // name of the sample to be recorded if this task needs to be reported by - // Rappor. If |process_id| is not supplied, it will be determined by |handle|. + // task runs on a process whose handle is |handle|. + // If |process_id| is not supplied, it will be determined by |handle|. Task(const base::string16& title, - const std::string& rappor_sample, const gfx::ImageSkia* icon, base::ProcessHandle handle, base::ProcessId process_id = base::kNullProcessId); @@ -177,7 +175,6 @@ } const base::string16& title() const { return title_; } - const std::string& rappor_sample_name() const { return rappor_sample_name_; } const gfx::ImageSkia& icon() const { return icon_; } const base::ProcessHandle& process_handle() const { return process_handle_; } const base::ProcessId& process_id() const { return process_id_; } @@ -188,9 +185,6 @@ // Returns |*result_image|. static gfx::ImageSkia* FetchIcon(int id, gfx::ImageSkia** result_image); void set_title(const base::string16& new_title) { title_ = new_title; } - void set_rappor_sample_name(const std::string& sample) { - rappor_sample_name_ = sample; - } void set_icon(const gfx::ImageSkia& new_icon) { icon_ = new_icon; } private: @@ -226,10 +220,6 @@ // The title of the task. base::string16 title_; - // The name of the sample representing this task when a Rappor sample needs to - // be recorded for it. - std::string rappor_sample_name_; - // The favicon. gfx::ImageSkia icon_;
diff --git a/chrome/browser/task_manager/providers/vm/vm_process_task.cc b/chrome/browser/task_manager/providers/vm/vm_process_task.cc index 5740e13d7..5f8da7b 100644 --- a/chrome/browser/task_manager/providers/vm/vm_process_task.cc +++ b/chrome/browser/task_manager/providers/vm/vm_process_task.cc
@@ -33,7 +33,7 @@ base::ProcessId pid, const std::string& owner_id, const std::string& vm_name) - : Task(MakeTitle(ids_vm_prefix, vm_name), vm_name, icon, pid), + : Task(MakeTitle(ids_vm_prefix, vm_name), icon, pid), owner_id_(owner_id), vm_name_(vm_name) {}
diff --git a/chrome/browser/task_manager/providers/web_contents/renderer_task.cc b/chrome/browser/task_manager/providers/web_contents/renderer_task.cc index 37145d60..1fb42a1c 100644 --- a/chrome/browser/task_manager/providers/web_contents/renderer_task.cc +++ b/chrome/browser/task_manager/providers/web_contents/renderer_task.cc
@@ -51,10 +51,6 @@ return (flags & (REFRESH_TYPE_V8_MEMORY | REFRESH_TYPE_WEBCACHE_STATS)) == 0; } -std::string GetRapporSampleName(content::WebContents* web_contents) { - return web_contents->GetVisibleURL().GetOrigin().spec(); -} - } // namespace RendererTask::RendererTask(const base::string16& title, @@ -78,7 +74,6 @@ content::WebContents* web_contents, content::RenderProcessHost* render_process_host) : Task(title, - GetRapporSampleName(web_contents), icon, render_process_host->GetProcess().Handle()), web_contents_(web_contents), @@ -106,10 +101,6 @@ RemoveObserver(this); } -void RendererTask::UpdateRapporSampleName() { - set_rappor_sample_name(GetRapporSampleName(web_contents())); -} - void RendererTask::Activate() { if (!web_contents_->GetDelegate()) return;
diff --git a/chrome/browser/task_manager/providers/web_contents/renderer_task.h b/chrome/browser/task_manager/providers/web_contents/renderer_task.h index a4dd3cc..26d0db8 100644 --- a/chrome/browser/task_manager/providers/web_contents/renderer_task.h +++ b/chrome/browser/task_manager/providers/web_contents/renderer_task.h
@@ -48,11 +48,6 @@ // can update their favicons. virtual void UpdateFavicon() = 0; - // An overridable method that will be called when the event - // WebContentsObserver::DidNavigateMainFrame() occurs, so that we can update - // their Rappor sample name when a navigation takes place. - virtual void UpdateRapporSampleName(); - // task_manager::Task: void Activate() override; void Refresh(const base::TimeDelta& update_interval,
diff --git a/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc b/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc index d0ebc46..0d548b1 100644 --- a/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc +++ b/chrome/browser/task_manager/providers/web_contents/web_contents_task_provider.cc
@@ -240,8 +240,6 @@ if (!main_frame_task) return; - main_frame_task->UpdateRapporSampleName(); - ForEachTask(base::Bind([](RendererTask* task) { // Listening to WebContentsObserver::TitleWasSet() only is not enough in // some cases when the the web page doesn't have a title. That's why we
diff --git a/chrome/browser/task_manager/providers/worker_task.cc b/chrome/browser/task_manager/providers/worker_task.cc index 82f2fde..7c3216a5a 100644 --- a/chrome/browser/task_manager/providers/worker_task.cc +++ b/chrome/browser/task_manager/providers/worker_task.cc
@@ -40,7 +40,6 @@ Task::Type task_type, int render_process_id) : Task(GetTaskTitle(/*script_url=*/GURL(), task_type), - /*rappor_sample=*/std::string(), /*icon=*/nullptr, handle), task_type_(task_type), @@ -58,7 +57,6 @@ void WorkerTask::SetScriptUrl(const GURL& script_url) { set_title(GetTaskTitle(script_url, task_type_)); - set_rappor_sample_name(script_url.spec()); } } // namespace task_manager
diff --git a/chrome/browser/task_manager/sampling/task_group_unittest.cc b/chrome/browser/task_manager/sampling/task_group_unittest.cc index 8169f3b..c74b2245 100644 --- a/chrome/browser/task_manager/sampling/task_group_unittest.cc +++ b/chrome/browser/task_manager/sampling/task_group_unittest.cc
@@ -30,7 +30,6 @@ public: FakeTask(base::ProcessId process_id, Type type, bool is_running_in_vm) : Task(base::string16(), - "FakeTask", nullptr, base::kNullProcessHandle, process_id),
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.cc b/chrome/browser/task_manager/sampling/task_manager_impl.cc index 36a81b3..b722397 100644 --- a/chrome/browser/task_manager/sampling/task_manager_impl.cc +++ b/chrome/browser/task_manager/sampling/task_manager_impl.cc
@@ -234,10 +234,6 @@ return GetTaskByTaskId(task_id)->title(); } -const std::string& TaskManagerImpl::GetTaskNameForRappor(TaskId task_id) const { - return GetTaskByTaskId(task_id)->rappor_sample_name(); -} - base::string16 TaskManagerImpl::GetProfileName(TaskId task_id) const { return GetTaskByTaskId(task_id)->GetProfileName(); }
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl.h b/chrome/browser/task_manager/sampling/task_manager_impl.h index 7a2c7d5..1b314e2 100644 --- a/chrome/browser/task_manager/sampling/task_manager_impl.h +++ b/chrome/browser/task_manager/sampling/task_manager_impl.h
@@ -97,7 +97,6 @@ int GetOpenFdCount(TaskId task_id) const override; bool IsTaskOnBackgroundedProcess(TaskId task_id) const override; const base::string16& GetTitle(TaskId task_id) const override; - const std::string& GetTaskNameForRappor(TaskId task_id) const override; base::string16 GetProfileName(TaskId task_id) const override; const gfx::ImageSkia& GetIcon(TaskId task_id) const override; const base::ProcessHandle& GetProcessHandle(TaskId task_id) const override;
diff --git a/chrome/browser/task_manager/sampling/task_manager_impl_unittest.cc b/chrome/browser/task_manager/sampling/task_manager_impl_unittest.cc index 6d0aaaf..d6d1338 100644 --- a/chrome/browser/task_manager/sampling/task_manager_impl_unittest.cc +++ b/chrome/browser/task_manager/sampling/task_manager_impl_unittest.cc
@@ -27,7 +27,6 @@ const std::string& title, SessionID tab_id) : Task(base::ASCIIToUTF16(title), - "FakeTask", nullptr, base::kNullProcessHandle, process_id),
diff --git a/chrome/browser/task_manager/task_manager_interface.h b/chrome/browser/task_manager/task_manager_interface.h index 89bc94f0..8915b3a 100644 --- a/chrome/browser/task_manager/task_manager_interface.h +++ b/chrome/browser/task_manager/task_manager_interface.h
@@ -119,10 +119,6 @@ // Returns the title of the task with |task_id|. virtual const base::string16& GetTitle(TaskId task_id) const = 0; - // Returns the canonicalized name of the task with |task_id| that can be used - // to represent this task in a Rappor sample via RapporServiceImpl. - virtual const std::string& GetTaskNameForRappor(TaskId task_id) const = 0; - // Returns the name of the profile associated with the browser context of the // render view host that the task with |task_id| represents (if that task // represents a renderer).
diff --git a/chrome/browser/task_manager/test_task_manager.cc b/chrome/browser/task_manager/test_task_manager.cc index 0b45d27..604c6996 100644 --- a/chrome/browser/task_manager/test_task_manager.cc +++ b/chrome/browser/task_manager/test_task_manager.cc
@@ -82,10 +82,6 @@ return title_; } -const std::string& TestTaskManager::GetTaskNameForRappor(TaskId task_id) const { - return rappor_sample_; -} - base::string16 TestTaskManager::GetProfileName(TaskId task_id) const { return base::string16(); }
diff --git a/chrome/browser/task_manager/test_task_manager.h b/chrome/browser/task_manager/test_task_manager.h index 7ad12ae..c27d3a8a 100644 --- a/chrome/browser/task_manager/test_task_manager.h +++ b/chrome/browser/task_manager/test_task_manager.h
@@ -45,7 +45,6 @@ int GetOpenFdCount(TaskId task_id) const override; bool IsTaskOnBackgroundedProcess(TaskId task_id) const override; const base::string16& GetTitle(TaskId task_id) const override; - const std::string& GetTaskNameForRappor(TaskId task_id) const override; base::string16 GetProfileName(TaskId task_id) const override; const gfx::ImageSkia& GetIcon(TaskId task_id) const override; const base::ProcessHandle& GetProcessHandle(TaskId task_id) const override; @@ -86,7 +85,6 @@ base::ProcessHandle handle_; base::ProcessId pid_; base::string16 title_; - std::string rappor_sample_; gfx::ImageSkia icon_; TaskIdList ids_;
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc index d9e34cf..285605d1 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.cc
@@ -205,6 +205,10 @@ withhold_permissions_checkbox_(nullptr) { DCHECK(prompt_->extension()); + extensions::ExtensionRegistry* extension_registry = + extensions::ExtensionRegistry::Get(profile_); + extension_registry_observer_.Add(extension_registry); + int buttons = prompt_->GetDialogButtons(); DCHECK(buttons & ui::DIALOG_BUTTON_CANCEL); @@ -399,6 +403,29 @@ return true; } +void ExtensionInstallDialogView::CloseDialog() { + GetWidget()->Close(); +} + +void ExtensionInstallDialogView::OnExtensionUninstalled( + content::BrowserContext* browser_context, + const extensions::Extension* extension, + extensions::UninstallReason reason) { + // Close the dialog if the extension is uninstalled. + if (extension->id() != prompt_->extension()->id()) + return; + CloseDialog(); +} + +void ExtensionInstallDialogView::OnShutdown( + extensions::ExtensionRegistry* registry) { + extensions::ExtensionRegistry* extension_registry = + extensions::ExtensionRegistry::Get(profile_); + DCHECK_EQ(extension_registry, registry); + extension_registry_observer_.Remove(extension_registry); + CloseDialog(); +} + ax::mojom::Role ExtensionInstallDialogView::GetAccessibleWindowRole() { return ax::mojom::Role::kAlertDialog; } @@ -424,7 +451,7 @@ chrome::ScopedTabbedBrowserDisplayer displayer(profile_); displayer.browser()->OpenURL(params); } - GetWidget()->Close(); + CloseDialog(); } void ExtensionInstallDialogView::CreateContents() {
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h index 4cb47f69..b4e1f500 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view.h +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view.h
@@ -9,9 +9,13 @@ #include "base/macros.h" #include "base/optional.h" +#include "base/scoped_observer.h" #include "base/timer/elapsed_timer.h" #include "base/timer/timer.h" #include "chrome/browser/extensions/extension_install_prompt.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_registry_observer.h" +#include "extensions/browser/uninstall_reason.h" #include "ui/views/bubble/bubble_dialog_delegate_view.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/checkbox.h" @@ -26,7 +30,9 @@ // Modal dialog that shows when the user attempts to install an extension. Also // shown if the extension is already installed but needs additional permissions. // Not a normal "bubble" despite being a subclass of BubbleDialogDelegateView. -class ExtensionInstallDialogView : public views::BubbleDialogDelegateView { +class ExtensionInstallDialogView + : public views::BubbleDialogDelegateView, + public extensions::ExtensionRegistryObserver { public: // The views::View::id of the ratings section in the dialog. static const int kRatingsViewId = 1; @@ -57,6 +63,14 @@ bool IsDialogButtonEnabled(ui::DialogButton button) const override; bool ShouldShowCloseButton() const override; + void CloseDialog(); + + // extensions::ExtensionRegistryObserver: + void OnExtensionUninstalled(content::BrowserContext* browser_context, + const extensions::Extension* extension, + extensions::UninstallReason reason) override; + void OnShutdown(extensions::ExtensionRegistry* registry) override; + // views::WidgetDelegate: ax::mojom::Role GetAccessibleWindowRole() override; base::string16 GetAccessibleWindowTitle() const override; @@ -83,6 +97,9 @@ ExtensionInstallPrompt::DoneCallback done_callback_; std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt_; base::string16 title_; + ScopedObserver<extensions::ExtensionRegistry, + extensions::ExtensionRegistryObserver> + extension_registry_observer_{this}; // The scroll view containing all the details for the dialog (including all // collapsible/expandable sections).
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc index 5d24528..c523300 100644 --- a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc +++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/extensions/extension_icon_manager.h" #include "chrome/browser/extensions/extension_install_prompt.h" #include "chrome/browser/extensions/extension_install_prompt_test_helper.h" +#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/platform_util.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" @@ -31,6 +32,9 @@ #include "components/constrained_window/constrained_window_views.h" #include "content/public/browser/browser_thread.h" #include "content/public/test/test_utils.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_system.h" +#include "extensions/browser/test_extension_registry_observer.h" #include "extensions/common/extension.h" #include "extensions/common/extension_features.h" #include "extensions/common/permissions/permission_message_provider.h" @@ -68,6 +72,9 @@ // Creates and returns an install prompt of |prompt_type|. std::unique_ptr<ExtensionInstallPrompt::Prompt> CreatePrompt( ExtensionInstallPrompt::PromptType prompt_type); + std::unique_ptr<ExtensionInstallPrompt::Prompt> CreatePrompt( + ExtensionInstallPrompt::PromptType prompt_type, + const extensions::Extension* extension); content::WebContents* web_contents() { return web_contents_; } @@ -93,13 +100,20 @@ std::unique_ptr<ExtensionInstallPrompt::Prompt> ExtensionInstallDialogViewTestBase::CreatePrompt( ExtensionInstallPrompt::PromptType prompt_type) { + return CreatePrompt(prompt_type, extension_); +} + +std::unique_ptr<ExtensionInstallPrompt::Prompt> +ExtensionInstallDialogViewTestBase::CreatePrompt( + ExtensionInstallPrompt::PromptType prompt_type, + const extensions::Extension* extension) { std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt( new ExtensionInstallPrompt::Prompt(prompt_type)); - prompt->set_extension(extension_); + prompt->set_extension(extension); std::unique_ptr<ExtensionIconManager> icon_manager( new ExtensionIconManager()); - prompt->set_icon(icon_manager->GetIcon(extension_->id())); + prompt->set_icon(icon_manager->GetIcon(extension->id())); return prompt; } @@ -436,6 +450,82 @@ ShowAndVerifyUi(); } +class ExtensionInstallDialogViewOnUninstallationTest + : public ExtensionInstallDialogViewTest { + public: + ExtensionInstallDialogViewOnUninstallationTest() = default; + ExtensionInstallDialogViewOnUninstallationTest( + const ExtensionInstallDialogViewOnUninstallationTest&) = delete; + ExtensionInstallDialogViewOnUninstallationTest& operator=( + const ExtensionInstallDialogViewOnUninstallationTest&) = delete; + + protected: + void UninstallExtension(const std::string& extension_id); +}; + +void ExtensionInstallDialogViewOnUninstallationTest::UninstallExtension( + const std::string& extension_id) { + extensions::TestExtensionRegistryObserver observer( + extensions::ExtensionRegistry::Get(browser()->profile()), extension_id); + extensions::ExtensionSystem::Get(browser()->profile()) + ->extension_service() + ->UninstallExtension( + extension_id, + extensions::UninstallReason::UNINSTALL_REASON_FOR_TESTING, nullptr); + observer.WaitForExtensionUninstalled(); +} + +IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewOnUninstallationTest, + UninstallingExtensionClosesDialog) { + const extensions::Extension* extension = + LoadExtension(test_data_dir_.AppendASCII( + "install_prompt/dialog_on_uninstall/same_extension")); + ASSERT_TRUE(extension); + std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt = + CreatePrompt(ExtensionInstallPrompt::REPAIR_PROMPT, extension); + ExtensionInstallDialogView* dialog = new ExtensionInstallDialogView( + profile(), web_contents(), base::DoNothing(), std::move(prompt)); + + views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget( + dialog, nullptr, + platform_util::GetViewForWindow(browser()->window()->GetNativeWindow())); + ASSERT_TRUE(modal_dialog); + views::test::WidgetClosingObserver dialog_observer(modal_dialog); + modal_dialog->Show(); + EXPECT_FALSE(modal_dialog->IsClosed()); + UninstallExtension(extension->id()); + dialog_observer.Wait(); + EXPECT_TRUE(dialog_observer.widget_closed()); +} + +IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewOnUninstallationTest, + UninstallingOtherExtensionDoesNotCloseDialog) { + const extensions::Extension* extension = + LoadExtension(test_data_dir_.AppendASCII( + "install_prompt/dialog_on_uninstall/same_extension")); + const extensions::Extension* other_extension = + LoadExtension(test_data_dir_.AppendASCII( + "install_prompt/dialog_on_uninstall/other_extension")); + ASSERT_TRUE(extension); + ASSERT_TRUE(other_extension); + std::unique_ptr<ExtensionInstallPrompt::Prompt> prompt = + CreatePrompt(ExtensionInstallPrompt::REPAIR_PROMPT, extension); + ExtensionInstallDialogView* dialog = new ExtensionInstallDialogView( + profile(), web_contents(), base::DoNothing(), std::move(prompt)); + + views::Widget* modal_dialog = views::DialogDelegate::CreateDialogWidget( + dialog, nullptr, + platform_util::GetViewForWindow(browser()->window()->GetNativeWindow())); + ASSERT_TRUE(modal_dialog); + views::test::WidgetClosingObserver dialog_observer(modal_dialog); + modal_dialog->Show(); + EXPECT_FALSE(modal_dialog->IsClosed()); + UninstallExtension(other_extension->id()); + ASSERT_TRUE(modal_dialog); + modal_dialog->Close(); + dialog_observer.Wait(); +} + class ExtensionInstallDialogRatingsSectionTest : public ExtensionInstallDialogViewTest { public:
diff --git a/chrome/browser/ui/views/feature_promos/global_media_controls_promo_controller.cc b/chrome/browser/ui/views/feature_promos/global_media_controls_promo_controller.cc index 87ec5f8d..acf6fe7 100644 --- a/chrome/browser/ui/views/feature_promos/global_media_controls_promo_controller.cc +++ b/chrome/browser/ui/views/feature_promos/global_media_controls_promo_controller.cc
@@ -31,6 +31,9 @@ DCHECK(profile_); } +GlobalMediaControlsPromoController::~GlobalMediaControlsPromoController() = + default; + void GlobalMediaControlsPromoController::ShowPromo() { // This shouldn't be called more than once. Check that state is fresh. DCHECK(!show_promo_called_); @@ -59,7 +62,7 @@ string_specifier, base::nullopt, base::nullopt, base::nullopt, std::move(feature_promo_bubble_timeout)); promo_bubble_->set_close_on_deactivate(false); - promo_bubble_->GetWidget()->AddObserver(this); + observer_.Add(promo_bubble_->GetWidget()); } void GlobalMediaControlsPromoController::OnMediaDialogOpened() { @@ -79,6 +82,8 @@ DCHECK(promo_bubble_); promo_bubble_ = nullptr; + observer_.Remove(widget); + FinishPromo(); }
diff --git a/chrome/browser/ui/views/feature_promos/global_media_controls_promo_controller.h b/chrome/browser/ui/views/feature_promos/global_media_controls_promo_controller.h index b3c18dd4..ed164eb 100644 --- a/chrome/browser/ui/views/feature_promos/global_media_controls_promo_controller.h +++ b/chrome/browser/ui/views/feature_promos/global_media_controls_promo_controller.h
@@ -5,8 +5,10 @@ #ifndef CHROME_BROWSER_UI_VIEWS_FEATURE_PROMOS_GLOBAL_MEDIA_CONTROLS_PROMO_CONTROLLER_H_ #define CHROME_BROWSER_UI_VIEWS_FEATURE_PROMOS_GLOBAL_MEDIA_CONTROLS_PROMO_CONTROLLER_H_ +#include "base/scoped_observer.h" #include "chrome/browser/ui/global_media_controls/media_toolbar_button_observer.h" #include "chrome/browser/ui/views/feature_promos/feature_promo_bubble_view.h" +#include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" class MediaToolbarButtonView; @@ -21,7 +23,7 @@ public: GlobalMediaControlsPromoController(MediaToolbarButtonView* owner, Profile* profile); - ~GlobalMediaControlsPromoController() override = default; + ~GlobalMediaControlsPromoController() override; // Shows the IPH promo. Should only be called once. void ShowPromo(); @@ -51,6 +53,8 @@ Profile* const profile_; FeaturePromoBubbleView* promo_bubble_ = nullptr; + ScopedObserver<views::Widget, views::WidgetObserver> observer_{this}; + // Whether we are showing the promo. bool is_showing_ = false;
diff --git a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc index ee1f66e..0006756 100644 --- a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc +++ b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.cc
@@ -37,6 +37,8 @@ browser_view_(browser_view) { } +ReopenTabPromoController::~ReopenTabPromoController() = default; + void ReopenTabPromoController::ShowPromo() { // This shouldn't be called more than once. Check that state is fresh. DCHECK(!show_promo_called_); @@ -74,7 +76,7 @@ IDS_REOPEN_TAB_PROMO, base::nullopt, IDS_REOPEN_TAB_PROMO_SCREENREADER, accelerator); promo_bubble_->set_close_on_deactivate(false); - promo_bubble_->GetWidget()->AddObserver(this); + observer_.Add(promo_bubble_->GetWidget()); } void ReopenTabPromoController::OnTabReopened(int command_id) { @@ -104,6 +106,8 @@ // timed out without the user following our IPH. End it. if (promo_step_ == StepAtDismissal::kBubbleShown) PromoEnded(); + + observer_.Remove(widget); } void ReopenTabPromoController::AppMenuShown() {
diff --git a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h index 5c85e7bd..beb2bea 100644 --- a/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h +++ b/chrome/browser/ui/views/feature_promos/reopen_tab_promo_controller.h
@@ -5,7 +5,9 @@ #ifndef CHROME_BROWSER_UI_VIEWS_FEATURE_PROMOS_REOPEN_TAB_PROMO_CONTROLLER_H_ #define CHROME_BROWSER_UI_VIEWS_FEATURE_PROMOS_REOPEN_TAB_PROMO_CONTROLLER_H_ +#include "base/scoped_observer.h" #include "chrome/browser/ui/views/frame/app_menu_button_observer.h" +#include "ui/views/widget/widget.h" #include "ui/views/widget/widget_observer.h" class BrowserView; @@ -19,7 +21,7 @@ public views::WidgetObserver { public: explicit ReopenTabPromoController(BrowserView* browser_view); - ~ReopenTabPromoController() override = default; + ~ReopenTabPromoController() override; // Shows the IPH promo. Should only be called once. void ShowPromo(); @@ -67,6 +69,8 @@ BrowserView* const browser_view_; FeaturePromoBubbleView* promo_bubble_ = nullptr; + ScopedObserver<views::Widget, views::WidgetObserver> observer_{this}; + // The promo stage that has been reached, logged to a histogram when the promo // flow ends. StepAtDismissal promo_step_ = StepAtDismissal::kBubbleShown;
diff --git a/chrome/browser/ui/views/global_error_bubble_view.cc b/chrome/browser/ui/views/global_error_bubble_view.cc index 5279cd2..99f0e2cb 100644 --- a/chrome/browser/ui/views/global_error_bubble_view.cc +++ b/chrome/browser/ui/views/global_error_bubble_view.cc
@@ -34,33 +34,17 @@ #include "ui/views/controls/label.h" #include "ui/views/layout/grid_layout.h" -namespace { - -const int kMaxBubbleViewWidth = 362; - -views::View* GetGlobalErrorBubbleAnchorView(Browser* browser) { - BrowserView* browser_view = BrowserView::GetBrowserViewForBrowser(browser); - return browser_view->toolbar_button_provider()->GetAppMenuButton(); -} - -gfx::Rect GetGlobalErrorBubbleAnchorRect(Browser* browser) { - return gfx::Rect(); -} - -} // namespace - // GlobalErrorBubbleViewBase --------------------------------------------------- // static GlobalErrorBubbleViewBase* GlobalErrorBubbleViewBase::ShowStandardBubbleView( Browser* browser, const base::WeakPtr<GlobalErrorWithStandardBubble>& error) { - views::View* anchor_view = GetGlobalErrorBubbleAnchorView(browser); - gfx::Rect anchor_rect; - if (!anchor_view) - anchor_rect = GetGlobalErrorBubbleAnchorRect(browser); + views::View* anchor_view = BrowserView::GetBrowserViewForBrowser(browser) + ->toolbar_button_provider() + ->GetAppMenuButton(); GlobalErrorBubbleView* bubble_view = new GlobalErrorBubbleView( - anchor_view, anchor_rect, views::BubbleBorder::TOP_RIGHT, browser, error); + anchor_view, views::BubbleBorder::TOP_RIGHT, browser, error); views::BubbleDialogDelegateView::CreateBubble(bubble_view); bubble_view->GetWidget()->Show(); return bubble_view; @@ -70,7 +54,6 @@ GlobalErrorBubbleView::GlobalErrorBubbleView( views::View* anchor_view, - const gfx::Rect& anchor_rect, views::BubbleBorder::Arrow arrow, Browser* browser, const base::WeakPtr<GlobalErrorWithStandardBubble>& error) @@ -104,11 +87,6 @@ this, error_->GetBubbleViewDetailsButtonLabel())); } - if (!anchor_view) { - SetAnchorRect(anchor_rect); - set_parent_window( - platform_util::GetViewForWindow(browser->window()->GetNativeWindow())); - } chrome::RecordDialogCreation(chrome::DialogIdentifier::GLOBAL_ERROR); } @@ -126,6 +104,7 @@ } void GlobalErrorBubbleView::Init() { + const int kMaxBubbleViewWidth = 362; // |error_| is assumed to be valid, and stay valid, at least until Init() // returns.
diff --git a/chrome/browser/ui/views/global_error_bubble_view.h b/chrome/browser/ui/views/global_error_bubble_view.h index 442167a3..5417237f 100644 --- a/chrome/browser/ui/views/global_error_bubble_view.h +++ b/chrome/browser/ui/views/global_error_bubble_view.h
@@ -21,7 +21,6 @@ public: GlobalErrorBubbleView( views::View* anchor_view, - const gfx::Rect& anchor_rect, views::BubbleBorder::Arrow arrow, Browser* browser, const base::WeakPtr<GlobalErrorWithStandardBubble>& error);
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc index 1f0ba0e..a9b83963 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_contents_view.cc
@@ -151,9 +151,10 @@ } OmniboxPopupContentsView::~OmniboxPopupContentsView() { - // We don't need to do anything with |popup_| here. The OS either has already - // closed the window, in which case it's been deleted, or it will soon, in - // which case there's nothing we need to do. + // We don't need to close or delete |popup_| here. The OS either has already + // closed the window, in which case it's been deleted, or it will soon. + if (popup_) + popup_->RemoveObserver(this); } void OmniboxPopupContentsView::OpenMatch(
diff --git a/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.cc index c88297b..27dabbd 100644 --- a/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.cc
@@ -19,7 +19,6 @@ namespace { constexpr const char kUserActionSkip[] = "recommendAppsSkip"; -constexpr const char kUserActionRetry[] = "recommendAppsRetry"; constexpr const char kUserActionInstall[] = "recommendAppsInstall"; constexpr const int kMaxAppCount = 21; @@ -91,15 +90,12 @@ IDS_LOGIN_RECOMMEND_APPS_SCREEN_DESCRIPTION); builder->Add("recommendAppsSkip", IDS_LOGIN_RECOMMEND_APPS_SKIP); builder->Add("recommendAppsInstall", IDS_LOGIN_RECOMMEND_APPS_INSTALL); - builder->Add("recommendAppsRetry", IDS_LOGIN_RECOMMEND_APPS_RETRY); builder->Add("recommendAppsLoading", IDS_LOGIN_RECOMMEND_APPS_SCREEN_LOADING); - builder->Add("recommendAppsError", IDS_LOGIN_RECOMMEND_APPS_SCREEN_ERROR); } void RecommendAppsScreenHandler::RegisterMessages() { BaseScreenHandler::RegisterMessages(); AddCallback(kUserActionSkip, &RecommendAppsScreenHandler::OnUserSkip); - AddCallback(kUserActionRetry, &RecommendAppsScreenHandler::HandleRetry); AddRawCallback(kUserActionInstall, &RecommendAppsScreenHandler::HandleInstall); } @@ -110,6 +106,10 @@ } void RecommendAppsScreenHandler::Show() { + if (!page_is_ready()) { + show_on_init_ = true; + return; + } ShowScreen(kScreenId); Profile* profile = ProfileManager::GetActiveUserProfile(); @@ -118,11 +118,6 @@ void RecommendAppsScreenHandler::Hide() {} -void RecommendAppsScreenHandler::OnLoadError() { - RecordUmaScreenState(RecommendAppsScreenState::ERROR); - CallJS("login.RecommendAppsScreen.showError"); -} - void RecommendAppsScreenHandler::OnLoadSuccess(const base::Value& app_list) { recommended_app_count_ = static_cast<int>(app_list.GetList().size()); LoadAppListInUI(app_list); @@ -133,15 +128,14 @@ HandleSkip(); } -void RecommendAppsScreenHandler::Initialize() {} +void RecommendAppsScreenHandler::Initialize() { + if (show_on_init_) { + Show(); + show_on_init_ = false; + } +} void RecommendAppsScreenHandler::LoadAppListInUI(const base::Value& app_list) { - if (!page_is_ready()) { - RecordUmaScreenState(RecommendAppsScreenState::ERROR); - CallJS("login.RecommendAppsScreen.showError"); - return; - } - RecordUmaScreenState(RecommendAppsScreenState::SHOW); const ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance(); @@ -166,12 +160,6 @@ screen_->OnSkip(); } -void RecommendAppsScreenHandler::HandleRetry() { - RecordUmaScreenAction(RecommendAppsScreenAction::RETRIED); - if (screen_) - screen_->OnRetry(); -} - void RecommendAppsScreenHandler::HandleInstall(const base::ListValue* args) { if (recommended_app_count_ != 0) { int selected_app_count = static_cast<int>(args->GetSize());
diff --git a/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h b/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h index 268ad8c..de0fd1ed 100644 --- a/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h +++ b/chrome/browser/ui/webui/chromeos/login/recommend_apps_screen_handler.h
@@ -31,10 +31,6 @@ // Hides the contents of the screen. virtual void Hide() = 0; - // Called when the download of the recommend app list fails. Show an error - // message to the user. - virtual void OnLoadError() = 0; - // Called when the download of the recommend app list is successful. Shows the // downloaded |app_list| to the user. virtual void OnLoadSuccess(const base::Value& app_list) = 0; @@ -62,7 +58,6 @@ void Bind(RecommendAppsScreen* screen) override; void Show() override; void Hide() override; - void OnLoadError() override; void OnLoadSuccess(const base::Value& app_list) override; void OnParseResponseError() override; @@ -85,6 +80,9 @@ int recommended_app_count_ = 0; + // If true, Initialize() will call Show(). + bool show_on_init_ = false; + DISALLOW_COPY_AND_ASSIGN(RecommendAppsScreenHandler); };
diff --git a/chrome/browser/web_applications/OWNERS b/chrome/browser/web_applications/OWNERS index 7217a06..1d217986 100644 --- a/chrome/browser/web_applications/OWNERS +++ b/chrome/browser/web_applications/OWNERS
@@ -10,4 +10,7 @@ # OS shortcuts tapted@chromium.org -# COMPONENT: UI>Browser>WebAppinstalls +# COMPONENT: UI>Browser>WebAppInstalls + +per-file web_app_file_handler*=davidbienvenu@chromium.org +per-file web_app_file_handler*=jessemckenna@google.com
diff --git a/chrome/browser/web_applications/chrome_pwa_launcher/OWNERS b/chrome/browser/web_applications/chrome_pwa_launcher/OWNERS index b7c2ade4..53fd8cf 100644 --- a/chrome/browser/web_applications/chrome_pwa_launcher/OWNERS +++ b/chrome/browser/web_applications/chrome_pwa_launcher/OWNERS
@@ -1,5 +1,5 @@ davidbienvenu@chromium.org jessemckenna@google.com -# COMPONENT: UI>Browser>WebAppinstalls +# COMPONENT: UI>Browser>WebAppInstalls # OS: Windows
diff --git a/chrome/browser/web_applications/chrome_pwa_launcher/chrome_pwa_launcher_util.cc b/chrome/browser/web_applications/chrome_pwa_launcher/chrome_pwa_launcher_util.cc index cf90617..e40f660 100644 --- a/chrome/browser/web_applications/chrome_pwa_launcher/chrome_pwa_launcher_util.cc +++ b/chrome/browser/web_applications/chrome_pwa_launcher/chrome_pwa_launcher_util.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/web_applications/chrome_pwa_launcher/chrome_pwa_launcher_util.h" +#include "base/files/file_util.h" #include "base/path_service.h" #include "chrome/common/chrome_constants.h" @@ -20,8 +21,12 @@ base::FilePath chrome_dir; if (!base::PathService::Get(base::DIR_EXE, &chrome_dir)) return base::FilePath(); - return chrome_dir.AppendASCII(chrome::kChromeVersion) - .Append(kChromePwaLauncherExecutable); + base::FilePath launcher_path = chrome_dir.AppendASCII(chrome::kChromeVersion) + .Append(kChromePwaLauncherExecutable); + if (base::PathExists(launcher_path)) + return launcher_path; + // In dev builds, the launcher will be in the executable directory. + return chrome_dir.Append(kChromePwaLauncherExecutable); } } // namespace web_app
diff --git a/chrome/browser/web_applications/components/OWNERS b/chrome/browser/web_applications/components/OWNERS new file mode 100644 index 0000000..14435acb --- /dev/null +++ b/chrome/browser/web_applications/components/OWNERS
@@ -0,0 +1,2 @@ +per-file web_app_file_handler_registration*=davidbienvenu@chromium.org +per-file web_app_file_handler_registration*=jessemckenna@google.com
diff --git a/chrome/browser/web_applications/components/web_app_file_handler_registration_win_unittest.cc b/chrome/browser/web_applications/components/web_app_file_handler_registration_win_unittest.cc index 367c0f1e..6eaf2a00 100644 --- a/chrome/browser/web_applications/components/web_app_file_handler_registration_win_unittest.cc +++ b/chrome/browser/web_applications/components/web_app_file_handler_registration_win_unittest.cc
@@ -61,14 +61,6 @@ registry_override_.OverrideRegistry(HKEY_LOCAL_MACHINE)); ASSERT_NO_FATAL_FAILURE( registry_override_.OverrideRegistry(HKEY_CURRENT_USER)); - - // Create a mock chrome_pwa_launcher.exe in a mock Chrome version directory, - // where the file-registration code expects it to be. - const base::FilePath pwa_launcher_path = GetChromePwaLauncherPath(); - ASSERT_TRUE(temp_version_dir_.Set(pwa_launcher_path.DirName())); - ASSERT_TRUE( - base::File(pwa_launcher_path, base::File::FLAG_CREATE).IsValid()); - testing_profile_manager_ = std::make_unique<TestingProfileManager>( TestingBrowserProcess::GetGlobal()); ASSERT_TRUE(testing_profile_manager_->SetUp());
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index b0f3565..312a8c8 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -4475,6 +4475,7 @@ sources += [ "../browser/spellchecker/spell_check_host_chrome_impl_mac_unittest.cc", "../browser/spellchecker/spellcheck_custom_dictionary_unittest.cc", + "../browser/spellchecker/spellcheck_language_policy_handlers_unittest.cc", "../browser/spellchecker/spellcheck_service_unittest.cc", "../tools/convert_dict/convert_dict_unittest.cc", ]
diff --git a/chrome/test/chromedriver/docs/chrome_connection.md b/chrome/test/chromedriver/docs/chrome_connection.md new file mode 100644 index 0000000..07a5b22 --- /dev/null +++ b/chrome/test/chromedriver/docs/chrome_connection.md
@@ -0,0 +1,96 @@ +# Chrome Connection + +## Overview + +ChromeDriver uses several classes to connect to Chrome and control it. +* `Chrome` class represents the Chrome browser controlled by ChromeDriver. +* `DevToolsClient` class represents a connection to Chrome. +* `WebView` class wraps around a `DevToolsClient` to provide some higher level + methods. + +## `Chrome` class + +ChromeDriver uses abstract class `Chrome` to represent the Chrome browser that +it controls. Other classes derived from it provide the actual implementations. +Here is its inheritance hierarchy: + +* [`Chrome`](../chrome/chrome.h): Abstract base class, defining the API. + * [`ChromeImpl`](../chrome/chrome_impl.h): Still an abstract class, + it contains implementation code that is shared by concrete classes. + * [`ChromeDesktopImpl`](../chrome/chrome_desktop_impl.h): + Represents a local desktop Chrome browser. + * [`ChromeAndroidImpl`](../chrome/chrome_android_impl.h): + Represents an adb connection to a Chrome running on an Android device. + * [`ChromeRemoteImpl`](../chrome/chrome_remote_impl.h): + Represents a Chrome browser that is started + independently from ChromeDriver, and is connected through a TCP port. + The browser can be running locally or remotely. + * [`StubChrome`](../chrome/stub_chrome.h): An implementation with all methods + stubbed out, used for unit tests only. + * Various test classes. + +There is a separate instance of `ChromeImpl` for each ChromeDriver session. +It has several fields related to the connection between +ChromeDriver and the browser: + +* `ChromeImpl::devtools_http_client_` is a `DevToolsHttpClient` object. + It contains the URL necessary to connect to browser DevTools (e.g., + http://localhost:12345), but doesn't contain any actual connections. + +* `ChromeImpl::devtools_websocket_client_` is a `DevToolsClient` object. + It encapsulates a browser-wide DevTools connection, used for sending commands + that apply to the whole browser. + This instance of `DevToolsClient` is sometimes referred to as the + "browser-wide `DevToolsClient`". + +* `ChromeImpl::web_views_` is a list of `WebView` objects, + one for each tab active in the browser. + These objects are used for sending commands that apply to a specific tab. + `Chrome::GetWebViewById` allows retrieving a `WebView` by its ID. + (There are additional `WebView` instances that represent frames, + but `ChromeImpl` is not aware of them.) + +## `DevToolsClient` and `WebView` + +Abstract class [`DevToolsClient`](../chrome/devtools_client.h) and its +implementation class [`DevToolsClientImpl`](../chrome/devtools_client_impl.h) +handle communication between ChromeDriver and DevTools. +`DevToolsClient` contains methods to connect to Chrome, +send commands to Chrome, and receive responses and events from Chrome. +Changes are rarely needed at this level to implement new features. + +The abstract class [`WebView`](../chrome/web_view.h) and its implementation +class [`WebViewImpl`](../chrome/web_view_impl.h) contain higher-level +methods on top of `DevToolsClient`. In addition to wrappers to methods +provided by `DevToolsClient`, it also has higher level methods for +synthetic event dispatching, cookie handling, etc. +The rest of ChromeDriver usually interacts with Chrome through `WebView` class. + +There are several types of `DevToolsClient` and `WebView` instances: + +* Browser-wide `DevToolsClient`, with no matching `WebView`. + It has id `"browser"`. + +* `DevToolsClient` and `WebView` representing a tab or window. + Both should have the same id, a 32-digit uppercase hexadecimal number. + +* `DevToolsClient` and `WebView` representing an OOPIF (out-of-process iframe, + i.e., a frame connected to a different renderer process than its parent + frame). They are created in response to + [`Target.attachedToTarget` event](https://chromedevtools.github.io/devtools-protocol/tot/Target#event-attachedToTarget) from DevTools. + Each OOPIF has a `targetId` and a `sessionId` (not to be confused + with ChromeDriver's session ID), both 32-bit hexadecimal numbers. + The `DevToolsClient` uses the `sessionId` as its ID, and has a parent + `DevToolsClient`. The `WebView` uses the `targetId` (same as `frameId`) + as its ID, and has a parent `WebView`. + No real connections are made. All communications are forwarded by the parent + `DevToolsClient` and `WebView`. + +Note that in most case, each instance of `DevToolsClient` is wrapped by a +`WebView`. The browser-wide `DevToolsClient` is the only instance not wrapped. + +From the point of view of the client application, each browser tab or window is +represented by a window handle, a string formed by concatenation `"CDwindow-"` +with the ID of the `DevToolsClient` and `WebView` representing the tab/window. +Each session has a tab that is currently active. The `WebView` connected to that +tab can be retrieved with `Session::GetTargetWindow`.
diff --git a/chrome/test/data/extensions/install_prompt/dialog_on_uninstall/other_extension/manifest.json b/chrome/test/data/extensions/install_prompt/dialog_on_uninstall/other_extension/manifest.json new file mode 100644 index 0000000..ab7d4433 --- /dev/null +++ b/chrome/test/data/extensions/install_prompt/dialog_on_uninstall/other_extension/manifest.json
@@ -0,0 +1,6 @@ +{ + "name": "chrome_extension_name__other", + "description": "chrome_extension_desc__other", + "version": "1", + "manifest_version": 2 +}
diff --git a/chrome/test/data/extensions/install_prompt/dialog_on_uninstall/same_extension/manifest.json b/chrome/test/data/extensions/install_prompt/dialog_on_uninstall/same_extension/manifest.json new file mode 100644 index 0000000..56084fe --- /dev/null +++ b/chrome/test/data/extensions/install_prompt/dialog_on_uninstall/same_extension/manifest.json
@@ -0,0 +1,6 @@ +{ + "name": "chrome_extension_name__", + "description": "chrome_extension_desc__", + "version": "1", + "manifest_version": 2 +}
diff --git a/chrome/test/data/webui/settings/security_page_test.js b/chrome/test/data/webui/settings/security_page_test.js index f1a934f..a0b9acf 100644 --- a/chrome/test/data/webui/settings/security_page_test.js +++ b/chrome/test/data/webui/settings/security_page_test.js
@@ -176,6 +176,37 @@ page.prefs.profile.password_manager_leak_detection.value == previous); }); + test('SafeBrowsingRadio_PreferenceUpdate', function() { + const enhancedRadio = page.$$('#safeBrowsingEnhanced'); + const standardRadio = page.$$('#safeBrowsingStandard'); + const disabledRadio = page.$$('#safeBrowsingDisabled'); + + // Set an enhanced protection preference state and ensure the radio buttons + // correctly reflect this. + page.set('prefs.safebrowsing.enabled.value', true); + page.set('prefs.safebrowsing.enhanced.value', true); + Polymer.dom.flush(); + assertTrue(enhancedRadio.checked); + assertFalse(standardRadio.checked); + assertFalse(disabledRadio.checked); + + // As above but for an enabled protection state. + page.set('prefs.safebrowsing.enabled.value', true); + page.set('prefs.safebrowsing.enhanced.value', false); + Polymer.dom.flush(); + assertFalse(enhancedRadio.checked); + assertTrue(standardRadio.checked); + assertFalse(disabledRadio.checked); + + // As above but for a safebrowsing disabled state. + page.set('prefs.safebrowsing.enabled.value', false); + page.set('prefs.safebrowsing.enhanced.value', false); + Polymer.dom.flush(); + assertFalse(enhancedRadio.checked); + assertFalse(standardRadio.checked); + assertTrue(disabledRadio.checked); + }); + test('SafeBrowsingRadio_ManagedState', async function() { const enhancedRadio = page.$$('#safeBrowsingEnhanced'); const standardRadio = page.$$('#safeBrowsingStandard');
diff --git a/components/download/internal/common/download_stats.cc b/components/download/internal/common/download_stats.cc index ca82992..fee6727 100644 --- a/components/download/internal/common/download_stats.cc +++ b/components/download/internal/common/download_stats.cc
@@ -734,32 +734,6 @@ DownloadContent::MAX); } -void RecordDownloadContentTypeSecurity( - const GURL& download_url, - const std::vector<GURL>& url_chain, - const std::string& mime_type, - const base::RepeatingCallback<bool(const GURL&)>& - is_origin_secure_callback) { - bool is_final_download_secure = is_origin_secure_callback.Run(download_url); - bool is_redirect_chain_secure = true; - for (const auto& url : url_chain) { - if (!is_origin_secure_callback.Run(url)) { - is_redirect_chain_secure = false; - break; - } - } - - DownloadContent download_content = - download::DownloadContentFromMimeType(mime_type, false); - if (is_final_download_secure && is_redirect_chain_secure) { - UMA_HISTOGRAM_ENUMERATION("Download.Start.ContentType.SecureChain", - download_content, DownloadContent::MAX); - } else { - UMA_HISTOGRAM_ENUMERATION("Download.Start.ContentType.InsecureChain", - download_content, DownloadContent::MAX); - } -} - void RecordDownloadSourcePageTransitionType( const base::Optional<ui::PageTransition>& page_transition) { if (!page_transition)
diff --git a/components/download/internal/common/in_progress_download_manager.cc b/components/download/internal/common/in_progress_download_manager.cc index 6e84587..5d3a187 100644 --- a/components/download/internal/common/in_progress_download_manager.cc +++ b/components/download/internal/common/in_progress_download_manager.cc
@@ -487,11 +487,6 @@ std::vector<GURL> url_chain = info->url_chain; std::string mime_type = info->mime_type; - if (info->is_new_download) { - RecordDownloadContentTypeSecurity(info->url(), info->url_chain, - info->mime_type, is_origin_secure_cb_); - } - // If the download cannot be found locally, ask |delegate_| to provide the // DownloadItem. if (delegate_ && !GetDownloadByGuid(info->guid)) {
diff --git a/components/download/public/common/download_stats.h b/components/download/public/common/download_stats.h index afd011d..ed5a4c7b 100644 --- a/components/download/public/common/download_stats.h +++ b/components/download/public/common/download_stats.h
@@ -420,13 +420,6 @@ const GURL& download_url, const std::vector<GURL>& url_chain); -COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadContentTypeSecurity( - const GURL& download_url, - const std::vector<GURL>& url_chain, - const std::string& mime_type, - const base::RepeatingCallback<bool(const GURL&)>& - is_origin_secure_callback); - COMPONENTS_DOWNLOAD_EXPORT void RecordDownloadSourcePageTransitionType( const base::Optional<ui::PageTransition>& transition);
diff --git a/components/exo/shell_surface_base.cc b/components/exo/shell_surface_base.cc index 17449b5..32b654a3 100644 --- a/components/exo/shell_surface_base.cc +++ b/components/exo/shell_surface_base.cc
@@ -694,6 +694,8 @@ void ShellSurfaceBase::WindowClosing() { SetEnabled(false); + if (widget_) + widget_->RemoveObserver(this); widget_ = nullptr; }
diff --git a/components/open_from_clipboard/BUILD.gn b/components/open_from_clipboard/BUILD.gn index a7099b0..411035c 100644 --- a/components/open_from_clipboard/BUILD.gn +++ b/components/open_from_clipboard/BUILD.gn
@@ -93,7 +93,11 @@ if (!is_ios) { sources += [ "clipboard_recent_content_generic_unittest.cc" ] - deps += [ "//ui/base/clipboard:clipboard_test_support" ] + deps += [ + ":feature_flags", + "//base/test:test_support", + "//ui/base/clipboard:clipboard_test_support", + ] } else { sources += [ "clipboard_recent_content_ios_unittest.mm" ] configs += [ "//build/config/compiler:enable_arc" ]
diff --git a/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc b/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc index 4edc278..bc9cffaa0 100644 --- a/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc +++ b/components/open_from_clipboard/clipboard_recent_content_generic_unittest.cc
@@ -11,7 +11,9 @@ #include "base/stl_util.h" #include "base/strings/string16.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "base/time/time.h" +#include "components/open_from_clipboard/clipboard_recent_content_features.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/clipboard/test/test_clipboard.h" #include "url/gurl.h" @@ -75,14 +77,18 @@ } TEST_F(ClipboardRecentContentGenericTest, OlderURLsNotSuggested) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeatureWithParameters( + kClipboardMaximumAge, {{kClipboardMaximumAgeParam, "600"}}); ClipboardRecentContentGeneric recent_content; base::Time now = base::Time::Now(); std::string text = "http://example.com/"; test_clipboard_->WriteText(text.data(), text.length()); - test_clipboard_->SetLastModifiedTime(now - base::TimeDelta::FromSeconds(10)); + test_clipboard_->SetLastModifiedTime(now - base::TimeDelta::FromMinutes(9)); EXPECT_TRUE(recent_content.GetRecentURLFromClipboard().has_value()); - // If the last modified time is days ago, the URL shouldn't be suggested. - test_clipboard_->SetLastModifiedTime(now - base::TimeDelta::FromDays(2)); + // If the last modified time is 10 minutes ago, the URL shouldn't be + // suggested. + test_clipboard_->SetLastModifiedTime(now - base::TimeDelta::FromMinutes(11)); EXPECT_FALSE(recent_content.GetRecentURLFromClipboard().has_value()); }
diff --git a/components/page_info/page_info.h b/components/page_info/page_info.h index 4ad9524..daa699a 100644 --- a/components/page_info/page_info.h +++ b/components/page_info/page_info.h
@@ -129,6 +129,8 @@ PAGE_INFO_CONNECTION_HELP_OPENED = 8, PAGE_INFO_SITE_SETTINGS_OPENED = 9, PAGE_INFO_SECURITY_DETAILS_OPENED = 10, + PAGE_INFO_COOKIE_ALLOWED_FOR_SITE = 11, + PAGE_INFO_COOKIE_BLOCKED_FOR_SITE = 12, PAGE_INFO_COUNT };
diff --git a/components/password_manager/core/browser/fake_form_fetcher.cc b/components/password_manager/core/browser/fake_form_fetcher.cc index 3c8789f..d8e8f40 100644 --- a/components/password_manager/core/browser/fake_form_fetcher.cc +++ b/components/password_manager/core/browser/fake_form_fetcher.cc
@@ -26,6 +26,10 @@ consumers_.RemoveObserver(consumer); } +void FakeFormFetcher::Fetch() { + state_ = State::WAITING; +} + FormFetcher::State FakeFormFetcher::GetState() const { return state_; } @@ -80,10 +84,6 @@ consumer.OnFetchCompleted(); } -void FakeFormFetcher::Fetch() { - state_ = State::WAITING; -} - std::unique_ptr<FormFetcher> FakeFormFetcher::Clone() { return std::make_unique<FakeFormFetcher>(); }
diff --git a/components/password_manager/core/browser/fake_form_fetcher.h b/components/password_manager/core/browser/fake_form_fetcher.h index bae0e3ea..805f30e 100644 --- a/components/password_manager/core/browser/fake_form_fetcher.h +++ b/components/password_manager/core/browser/fake_form_fetcher.h
@@ -37,6 +37,9 @@ void RemoveConsumer(Consumer* consumer) override; + // Only sets the internal state to WAITING, no call to PasswordStore. + void Fetch() override; + // Returns State::WAITING if Fetch() was called after any Set* calls, and // State::NOT_WAITING otherwise. State GetState() const override; @@ -80,9 +83,6 @@ void NotifyFetchCompleted(); - // Only sets the internal state to WAITING, no call to PasswordStore. - void Fetch() override; - // Returns a new FakeFormFetcher. std::unique_ptr<FormFetcher> Clone() override;
diff --git a/components/password_manager/core/browser/form_fetcher.h b/components/password_manager/core/browser/form_fetcher.h index 682ab53..4d0949d 100644 --- a/components/password_manager/core/browser/form_fetcher.h +++ b/components/password_manager/core/browser/form_fetcher.h
@@ -25,8 +25,6 @@ // indirection allows caching of identical requests from PFM on the same origin, // as well as easier testing (no need to mock the whole PasswordStore when // testing a PFM). -// TODO(crbug.com/621355): Actually modify the API to support fetching in the -// FormFetcher instance. class FormFetcher { public: // State of waiting for a response from a PasswordStore. There might be @@ -54,6 +52,12 @@ // Call this to stop |consumer| from receiving updates from |this|. virtual void RemoveConsumer(Consumer* consumer) = 0; + // Fetches stored matching logins. In addition the statistics is fetched on + // platforms with the password bubble. This is called automatically during + // construction and can be called manually later as well to cause an update + // of the cached credentials. + virtual void Fetch() = 0; + // Returns the current state of the FormFetcher virtual State GetState() const = 0; @@ -87,12 +91,6 @@ // Pointer to a preferred entry in the vector returned by GetBestMatches(). virtual const autofill::PasswordForm* GetPreferredMatch() const = 0; - // Fetches stored matching logins. In addition the statistics is fetched on - // platforms with the password bubble. This is called automatically during - // construction and can be called manually later as well to cause an update - // of the cached credentials. - virtual void Fetch() = 0; - // Creates a copy of |*this| with contains the same credentials without the // need for calling Fetch(). virtual std::unique_ptr<FormFetcher> Clone() = 0;
diff --git a/components/password_manager/core/browser/form_fetcher_impl.cc b/components/password_manager/core/browser/form_fetcher_impl.cc index 43aa314..4d804853 100644 --- a/components/password_manager/core/browser/form_fetcher_impl.cc +++ b/components/password_manager/core/browser/form_fetcher_impl.cc
@@ -89,6 +89,41 @@ consumers_.RemoveObserver(consumer); } +void FormFetcherImpl::Fetch() { + std::unique_ptr<BrowserSavePasswordProgressLogger> logger; + if (password_manager_util::IsLoggingActive(client_)) { + logger.reset( + new BrowserSavePasswordProgressLogger(client_->GetLogManager())); + logger->LogMessage(Logger::STRING_FETCH_METHOD); + logger->LogNumber(Logger::STRING_FORM_FETCHER_STATE, + static_cast<int>(state_)); + } + + if (state_ == State::WAITING) { + // There is currently a password store query in progress, need to re-fetch + // store results later. + need_to_refetch_ = true; + return; + } + + PasswordStore* password_store = client_->GetProfilePasswordStore(); + if (!password_store) { + if (logger) + logger->LogMessage(Logger::STRING_NO_STORE); + NOTREACHED(); + return; + } + state_ = State::WAITING; + password_store->GetLogins(form_digest_, this); + +// The statistics isn't needed on mobile, only on desktop. Let's save some +// processor cycles. +#if !defined(OS_IOS) && !defined(OS_ANDROID) + // The statistics is needed for the "Save password?" bubble. + password_store->GetSiteStats(form_digest_.origin.GetOrigin(), this); +#endif +} + FormFetcherImpl::State FormFetcherImpl::GetState() const { return state_; } @@ -167,41 +202,6 @@ ProcessPasswordStoreResults(std::move(forms)); } -void FormFetcherImpl::Fetch() { - std::unique_ptr<BrowserSavePasswordProgressLogger> logger; - if (password_manager_util::IsLoggingActive(client_)) { - logger.reset( - new BrowserSavePasswordProgressLogger(client_->GetLogManager())); - logger->LogMessage(Logger::STRING_FETCH_METHOD); - logger->LogNumber(Logger::STRING_FORM_FETCHER_STATE, - static_cast<int>(state_)); - } - - if (state_ == State::WAITING) { - // There is currently a password store query in progress, need to re-fetch - // store results later. - need_to_refetch_ = true; - return; - } - - PasswordStore* password_store = client_->GetProfilePasswordStore(); - if (!password_store) { - if (logger) - logger->LogMessage(Logger::STRING_NO_STORE); - NOTREACHED(); - return; - } - state_ = State::WAITING; - password_store->GetLogins(form_digest_, this); - -// The statistics isn't needed on mobile, only on desktop. Let's save some -// processor cycles. -#if !defined(OS_IOS) && !defined(OS_ANDROID) - // The statistics is needed for the "Save password?" bubble. - password_store->GetSiteStats(form_digest_.origin.GetOrigin(), this); -#endif -} - std::unique_ptr<FormFetcher> FormFetcherImpl::Clone() { // Create the copy without the "HTTPS migration" activated. If it was needed, // then it was done by |this| already.
diff --git a/components/password_manager/core/browser/form_fetcher_impl.h b/components/password_manager/core/browser/form_fetcher_impl.h index 42a5ab30e..4a8a00b 100644 --- a/components/password_manager/core/browser/form_fetcher_impl.h +++ b/components/password_manager/core/browser/form_fetcher_impl.h
@@ -45,25 +45,19 @@ // FormFetcher: void AddConsumer(FormFetcher::Consumer* consumer) override; void RemoveConsumer(FormFetcher::Consumer* consumer) override; + void Fetch() override; State GetState() const override; const std::vector<InteractionsStats>& GetInteractionsStats() const override; - std::vector<const autofill::PasswordForm*> GetNonFederatedMatches() const override; std::vector<const autofill::PasswordForm*> GetFederatedMatches() const override; - bool IsBlacklisted() const override; - const std::vector<const autofill::PasswordForm*>& GetAllRelevantMatches() const override; - const std::vector<const autofill::PasswordForm*>& GetBestMatches() const override; - const autofill::PasswordForm* GetPreferredMatch() const override; - - void Fetch() override; std::unique_ptr<FormFetcher> Clone() override; // PasswordStoreConsumer:
diff --git a/components/password_manager/core/browser/multi_store_form_fetcher.cc b/components/password_manager/core/browser/multi_store_form_fetcher.cc index 8ec7a426..823b8c0b 100644 --- a/components/password_manager/core/browser/multi_store_form_fetcher.cc +++ b/components/password_manager/core/browser/multi_store_form_fetcher.cc
@@ -25,14 +25,6 @@ MultiStoreFormFetcher::~MultiStoreFormFetcher() = default; -bool MultiStoreFormFetcher::IsBlacklisted() const { - if (client_->GetPasswordFeatureManager()->GetDefaultPasswordStore() == - PasswordForm::Store::kAccountStore) { - return is_blacklisted_in_account_store_; - } - return is_blacklisted_in_profile_store_; -} - void MultiStoreFormFetcher::Fetch() { if (password_manager_util::IsLoggingActive(client_)) { BrowserSavePasswordProgressLogger logger(client_->GetLogManager()); @@ -63,6 +55,14 @@ } } +bool MultiStoreFormFetcher::IsBlacklisted() const { + if (client_->GetPasswordFeatureManager()->GetDefaultPasswordStore() == + PasswordForm::Store::kAccountStore) { + return is_blacklisted_in_account_store_; + } + return is_blacklisted_in_profile_store_; +} + void MultiStoreFormFetcher::OnGetPasswordStoreResults( std::vector<std::unique_ptr<PasswordForm>> results) { DCHECK_EQ(State::WAITING, state_);
diff --git a/components/password_manager/core/browser/multi_store_form_fetcher.h b/components/password_manager/core/browser/multi_store_form_fetcher.h index fb25367a..3954b10 100644 --- a/components/password_manager/core/browser/multi_store_form_fetcher.h +++ b/components/password_manager/core/browser/multi_store_form_fetcher.h
@@ -21,9 +21,10 @@ bool should_migrate_http_passwords); ~MultiStoreFormFetcher() override; + // FormFetcher overrides. + void Fetch() override; bool IsBlacklisted() const override; - void Fetch() override; void OnGetPasswordStoreResults( std::vector<std::unique_ptr<autofill::PasswordForm>> results) override;
diff --git a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc index 565bbb77..7e5d29e6 100644 --- a/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc +++ b/components/password_manager/core/browser/sync/password_sync_bridge_unittest.cc
@@ -902,9 +902,6 @@ ON_CALL(*mock_password_store_sync(), IsAccountStore()) .WillByDefault(Return(true)); - const int kPrimaryKeyUnsyncedCredential = 1000; - const int kPrimaryKeySyncedCredential = 1001; - const int kPrimaryKeyUnsyncedDeletion = 1002; const std::string kPrimaryKeyUnsyncedCredentialStr = "1000"; const std::string kPrimaryKeySyncedCredentialStr = "1001"; const std::string kPrimaryKeyUnsyncedDeletionStr = "1002"; @@ -934,15 +931,16 @@ return batch; }); + // No form is added to the database for the unsynced deletion primary key, + // because the deletion is supposed to have already removed such form. + const int kPrimaryKeyUnsyncedCredential = 1000; + const int kPrimaryKeySyncedCredential = 1001; autofill::PasswordForm unsynced_credential = MakePasswordForm(kSignonRealm1); autofill::PasswordForm synced_credential = MakePasswordForm(kSignonRealm2); - autofill::PasswordForm unsynced_deletion = MakePasswordForm(kSignonRealm3); fake_db()->AddLoginForPrimaryKey(kPrimaryKeyUnsyncedCredential, unsynced_credential); fake_db()->AddLoginForPrimaryKey(kPrimaryKeySyncedCredential, synced_credential); - fake_db()->AddLoginForPrimaryKey(kPrimaryKeyUnsyncedDeletion, - unsynced_deletion); // The notification should only contain new credentials that are unsynced, // ignoring both synced ones and deletion entries.
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/Address.java b/components/payments/content/android/java/src/org/chromium/components/payments/Address.java index 6a87e1c..0d106e4 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/Address.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/Address.java
@@ -4,6 +4,10 @@ package org.chromium.components.payments; +import android.os.Bundle; + +import androidx.annotation.Nullable; + /** * An immutable class that mirrors org.chromium.payments.mojom.PaymentAddress. * https://w3c.github.io/payment-request/#paymentaddress-interface @@ -63,4 +67,39 @@ this.recipient = recipient; this.phone = phone; } + + // Keys in shipping address bundle. + public static final String EXTRA_ADDRESS_COUNTRY = "country"; + public static final String EXTRA_ADDRESS_LINES = "addressLines"; + public static final String EXTRA_ADDRESS_REGION = "region"; + public static final String EXTRA_ADDRESS_CITY = "city"; + public static final String EXTRA_ADDRESS_DEPENDENT_LOCALITY = "dependentLocality"; + public static final String EXTRA_ADDRESS_POSTAL_CODE = "postalCode"; + public static final String EXTRA_ADDRESS_SORTING_CODE = "sortingCode"; + public static final String EXTRA_ADDRESS_ORGANIZATION = "organization"; + public static final String EXTRA_ADDRESS_RECIPIENT = "recipient"; + public static final String EXTRA_ADDRESS_PHONE = "phone"; + + /** + * @param address Bundle to be parsed. + * @return converted Address or null. + */ + @Nullable + public static Address createFromBundle(@Nullable Bundle address) { + if (address == null) return null; + return new Address(getStringOrEmpty(address, EXTRA_ADDRESS_COUNTRY), + address.getStringArray(EXTRA_ADDRESS_LINES), + getStringOrEmpty(address, EXTRA_ADDRESS_REGION), + getStringOrEmpty(address, EXTRA_ADDRESS_CITY), + getStringOrEmpty(address, EXTRA_ADDRESS_DEPENDENT_LOCALITY), + getStringOrEmpty(address, EXTRA_ADDRESS_POSTAL_CODE), + getStringOrEmpty(address, EXTRA_ADDRESS_SORTING_CODE), + getStringOrEmpty(address, EXTRA_ADDRESS_ORGANIZATION), + getStringOrEmpty(address, EXTRA_ADDRESS_RECIPIENT), + getStringOrEmpty(address, EXTRA_ADDRESS_PHONE)); + } + + private static String getStringOrEmpty(Bundle bundle, String key) { + return bundle.getString(key, /*defaultValue =*/""); + } }
diff --git a/components/payments/content/android/java/src/org/chromium/components/payments/intent/WebPaymentIntentHelper.java b/components/payments/content/android/java/src/org/chromium/components/payments/intent/WebPaymentIntentHelper.java index 57ef7fc9..b13bd01 100644 --- a/components/payments/content/android/java/src/org/chromium/components/payments/intent/WebPaymentIntentHelper.java +++ b/components/payments/content/android/java/src/org/chromium/components/payments/intent/WebPaymentIntentHelper.java
@@ -75,18 +75,8 @@ public static final String EXTRA_RESPONSE_PAYER_EMAIL = "payerEmail"; public static final String EXTRA_RESPONSE_PAYER_PHONE = "payerPhone"; - // Shipping address parsable and its fields, used in payment response and shippingAddressChange. + // Shipping address bundle used in payment response and shippingAddressChange. public static final String EXTRA_SHIPPING_ADDRESS = "shippingAddress"; - public static final String EXTRA_ADDRESS_COUNTRY = "country"; - public static final String EXTRA_ADDRESS_LINES = "addressLines"; - public static final String EXTRA_ADDRESS_REGION = "region"; - public static final String EXTRA_ADDRESS_CITY = "city"; - public static final String EXTRA_ADDRESS_DEPENDENT_LOCALITY = "dependentLocality"; - public static final String EXTRA_ADDRESS_POSTAL_CODE = "postalCode"; - public static final String EXTRA_ADDRESS_SORTING_CODE = "sortingCode"; - public static final String EXTRA_ADDRESS_ORGANIZATION = "organization"; - public static final String EXTRA_ADDRESS_RECIPIENT = "recipient"; - public static final String EXTRA_ADDRESS_PHONE = "phone"; private static final String EMPTY_JSON_DATA = "{}"; @@ -165,16 +155,7 @@ errorCallback.onPaymentError(ErrorStrings.SHIPPING_ADDRESS_INVALID); return; } - shippingAddress = new Address(getStringOrEmpty(addressBundle, EXTRA_ADDRESS_COUNTRY), - addressBundle.getStringArray(EXTRA_ADDRESS_LINES), - getStringOrEmpty(addressBundle, EXTRA_ADDRESS_REGION), - getStringOrEmpty(addressBundle, EXTRA_ADDRESS_CITY), - getStringOrEmpty(addressBundle, EXTRA_ADDRESS_DEPENDENT_LOCALITY), - getStringOrEmpty(addressBundle, EXTRA_ADDRESS_POSTAL_CODE), - getStringOrEmpty(addressBundle, EXTRA_ADDRESS_SORTING_CODE), - getStringOrEmpty(addressBundle, EXTRA_ADDRESS_ORGANIZATION), - getStringOrEmpty(addressBundle, EXTRA_ADDRESS_RECIPIENT), - getStringOrEmpty(addressBundle, EXTRA_ADDRESS_PHONE)); + shippingAddress = Address.createFromBundle(addressBundle); } else { // !requestedPaymentOptions.requestShipping shippingAddress = new Address(); } @@ -585,10 +566,6 @@ } private static String getStringOrEmpty(Intent data, String key) { - return getStringOrEmpty(data.getExtras(), key); - } - - private static String getStringOrEmpty(Bundle bundle, String key) { - return bundle.getString(key, /*defaultValue =*/""); + return data.getExtras().getString(key, /*defaultValue =*/""); } }
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor.cc b/components/sync/model_impl/client_tag_based_model_type_processor.cc index 2b199d52..aa935f0 100644 --- a/components/sync/model_impl/client_tag_based_model_type_processor.cc +++ b/components/sync/model_impl/client_tag_based_model_type_processor.cc
@@ -42,9 +42,6 @@ dump_stack_(dump_stack), commit_only_(commit_only) { ResetState(CLEAR_METADATA); - // TODO(crbug.com/947044): create entity tracker after initial merge. It will - // be changed in a follow-up patch. - DCHECK(entity_tracker_); } ClientTagBasedModelTypeProcessor::~ClientTagBasedModelTypeProcessor() { @@ -80,7 +77,7 @@ void ClientTagBasedModelTypeProcessor::ModelReadyToSync( std::unique_ptr<MetadataBatch> batch) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(!entity_tracker_->size()); + DCHECK(!entity_tracker_); DCHECK(!model_ready_to_sync_); model_ready_to_sync_ = true; @@ -92,7 +89,7 @@ if (batch->GetModelTypeState().initial_sync_done()) { EntityMetadataMap metadata_map(batch->TakeAllMetadata()); entity_tracker_ = std::make_unique<ProcessorEntityTracker>( - std::move(metadata_map), batch->GetModelTypeState()); + batch->GetModelTypeState(), std::move(metadata_map)); } else { // In older versions of the binary, commit-only types did not persist // initial_sync_done(). So this branch can be exercised for commit-only @@ -101,7 +98,6 @@ // persisted Sync metadata is in an inconsistent state. DCHECK(commit_only_ || batch->TakeAllMetadata().empty()) << ModelTypeToString(type_); - entity_tracker_->InitializeMetadata(type_); } ConnectIfReady(); @@ -126,61 +122,34 @@ return; } - sync_pb::ModelTypeState model_type_state = - entity_tracker_->model_type_state(); - - if (!model_type_state.has_cache_guid()) { - // Initialize the cache_guid for old clients that didn't persist it. - model_type_state.set_cache_guid(activation_request_.cache_guid); - } - // Check for invalid persisted metadata. - if (model_type_state.cache_guid() != activation_request_.cache_guid || - model_type_state.progress_marker().data_type_id() != - GetSpecificsFieldNumberFromModelType(type_)) { - // There is a mismatch between the cache guid or the data type id stored in - // |model_type_state_| and the one received from sync. This indicates that - // the stored metadata are invalid (e.g. has been manipulated) and don't - // belong to the current syncing client. - if (model_type_state.progress_marker().data_type_id() != - GetSpecificsFieldNumberFromModelType(type_)) { - UMA_HISTOGRAM_ENUMERATION("Sync.PersistedModelTypeIdMismatch", - ModelTypeHistogramValue(type_)); - } - ClearMetadataAndResetState(); - model_type_state = entity_tracker_->model_type_state(); - model_type_state.set_cache_guid(activation_request_.cache_guid); - - // The model is still ready to sync (with the same |bridge_|) - replay - // the initialization. - model_ready_to_sync_ = true; - // Notify the bridge sync is starting to simulate an enable event. - bridge_->OnSyncStarting(activation_request_); - - DCHECK(!model_type_state.initial_sync_done()); - } - - // Cache GUID verification earlier above guarantees the user is the same. - model_type_state.set_authenticated_account_id( - activation_request_.authenticated_account_id.ToString()); - - entity_tracker_->set_model_type_state(model_type_state); - - // For commit-only types, no updates are expected and hence we can consider - // initial_sync_done(), reflecting that sync is enabled. - if (commit_only_ && - !entity_tracker_->model_type_state().initial_sync_done()) { - sync_pb::ModelTypeState model_type_state_sync_done = - entity_tracker_->model_type_state(); - model_type_state_sync_done.set_initial_sync_done(true); - OnFullUpdateReceived(model_type_state_sync_done, UpdateResponseDataList()); - DCHECK(IsTrackingMetadata()); - } - - DCHECK_EQ(entity_tracker_->model_type_state().cache_guid(), - activation_request_.cache_guid); + CheckForInvalidPersistedMetadata(); auto activation_response = std::make_unique<DataTypeActivationResponse>(); - activation_response->model_type_state = entity_tracker_->model_type_state(); + if (!entity_tracker_) { + sync_pb::ModelTypeState model_type_state; + model_type_state.mutable_progress_marker()->set_data_type_id( + GetSpecificsFieldNumberFromModelType(type_)); + model_type_state.set_cache_guid(activation_request_.cache_guid); + model_type_state.set_authenticated_account_id( + activation_request_.authenticated_account_id.ToString()); + if (commit_only_) { + // For commit-only types, no updates are expected and hence we can + // consider initial_sync_done(), reflecting that sync is enabled. + model_type_state.set_initial_sync_done(true); + OnFullUpdateReceived(model_type_state, UpdateResponseDataList()); + DCHECK(entity_tracker_); + } else { + activation_response->model_type_state = model_type_state; + } + } + + if (entity_tracker_) { + activation_response->model_type_state = entity_tracker_->model_type_state(); + } + + DCHECK_EQ(activation_response->model_type_state.cache_guid(), + activation_request_.cache_guid); + activation_response->type_processor = std::make_unique<ModelTypeProcessorProxy>( weak_ptr_factory_for_worker_.GetWeakPtr(), @@ -235,8 +204,12 @@ void ClientTagBasedModelTypeProcessor::ClearMetadataAndResetState() { std::unique_ptr<MetadataChangeList> change_list; + // All changes before the initial sync is done are ignored and in fact they + // were never persisted by the bridge (prior to MergeSyncData), so no + // entities should be tracking. + // // Clear metadata if MergeSyncData() was called before. - if (entity_tracker_->model_type_state().initial_sync_done()) { + if (entity_tracker_) { change_list = bridge_->CreateMetadataChangeList(); std::vector<const ProcessorEntity*> entities = entity_tracker_->GetAllEntitiesIncludingTombstones(); @@ -244,11 +217,6 @@ change_list->ClearMetadata(entity->storage_key()); } change_list->ClearModelTypeState(); - } else { - // All changes before the initial sync is done are ignored and in fact they - // were never persisted by the bridge (prior to MergeSyncData), so we should - // be tracking no entities. - DCHECK(!entity_tracker_->size()); } bridge_->ApplyStopSyncChanges(std::move(change_list)); @@ -258,7 +226,7 @@ } bool ClientTagBasedModelTypeProcessor::IsTrackingMetadata() { - return entity_tracker_->model_type_state().initial_sync_done(); + return entity_tracker_ != nullptr; } std::string ClientTagBasedModelTypeProcessor::TrackedAccountId() { @@ -340,7 +308,9 @@ weak_ptr_factory_for_worker_.InvalidateWeakPtrs(); worker_.reset(); - entity_tracker_->ClearTransientSyncState(); + if (entity_tracker_) { + entity_tracker_->ClearTransientSyncState(); + } } void ClientTagBasedModelTypeProcessor::Put( @@ -356,7 +326,7 @@ DCHECK(!storage_key.empty()); DCHECK_EQ(type_, GetModelTypeFromSpecifics(data->specifics)); - if (!entity_tracker_->model_type_state().initial_sync_done()) { + if (!entity_tracker_) { // Ignore changes before the initial sync is done. return; } @@ -416,7 +386,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(IsAllowingChanges()); - if (!entity_tracker_->model_type_state().initial_sync_done()) { + if (!entity_tracker_) { // Ignore changes before the initial sync is done. return; } @@ -444,7 +414,7 @@ DCHECK(!client_tag_hash.value().empty()); DCHECK(!storage_key.empty()); DCHECK(!bridge_->SupportsGetStorageKey()); - DCHECK(entity_tracker_->model_type_state().initial_sync_done()); + DCHECK(entity_tracker_); ProcessorEntity* entity = entity_tracker_->GetEntityForTagHash(client_tag_hash); @@ -458,17 +428,29 @@ void ClientTagBasedModelTypeProcessor::UntrackEntityForStorageKey( const std::string& storage_key) { + if (!entity_tracker_) { + // Ignore changes before the initial sync is done. + return; + } entity_tracker_->RemoveEntityForStorageKey(storage_key); } void ClientTagBasedModelTypeProcessor::UntrackEntityForClientTagHash( const ClientTagHash& client_tag_hash) { DCHECK(!client_tag_hash.value().empty()); + if (!entity_tracker_) { + // Ignore changes before the initial sync is done. + return; + } entity_tracker_->RemoveEntityForClientTagHash(client_tag_hash); } bool ClientTagBasedModelTypeProcessor::IsEntityUnsynced( const std::string& storage_key) { + if (!entity_tracker_) { + return false; + } + const ProcessorEntity* entity = entity_tracker_->GetEntityForStorageKey(storage_key); if (entity == nullptr) { @@ -480,6 +462,10 @@ base::Time ClientTagBasedModelTypeProcessor::GetEntityCreationTime( const std::string& storage_key) const { + if (!entity_tracker_) { + return base::Time(); + } + const ProcessorEntity* entity = entity_tracker_->GetEntityForStorageKey(storage_key); if (entity == nullptr) { @@ -490,6 +476,10 @@ base::Time ClientTagBasedModelTypeProcessor::GetEntityModificationTime( const std::string& storage_key) const { + if (!entity_tracker_) { + return base::Time(); + } + const ProcessorEntity* entity = entity_tracker_->GetEntityForStorageKey(storage_key); if (entity == nullptr) { @@ -504,7 +494,7 @@ return; // Don't send anything if the type is not ready to handle commits. - if (!entity_tracker_->model_type_state().initial_sync_done()) + if (!entity_tracker_) return; // Nudge worker if there are any entities with local changes.0 @@ -517,10 +507,13 @@ GetLocalChangesCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_GT(max_entries, 0U); + // If there is a model error, it must have been reported already but hasn't // reached the sync engine yet. In this case return directly to avoid // interactions with the bridge. - if (model_error_) { + // In some cases local changes may be requested before entity tracker is + // loaded. Just invoke the callback with empty list. + if (model_error_ || !entity_tracker_) { std::move(callback).Run(CommitRequestDataList()); return; } @@ -556,6 +549,10 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!model_error_); + DCHECK(entity_tracker_) + << "Received commit response when entity tracker is null. Type: " + << ModelTypeToString(type_); + // |error_response_list| is ignored, because all errors are treated as // transientand the processor with eventually retry. @@ -654,8 +651,7 @@ // always clear all data. We do this to allow the server to replace all data // on the client, without having to know exactly which entities the client // has. - const bool is_initial_sync = - !entity_tracker_->model_type_state().initial_sync_done(); + const bool is_initial_sync = !IsTrackingMetadata(); if (is_initial_sync || HasClearAllDirective(model_type_state)) { error = OnFullUpdateReceived(model_type_state, std::move(updates)); } else { @@ -683,6 +679,7 @@ /*buckets=*/50); } + DCHECK(entity_tracker_); // If there were entities with empty storage keys, they should have been // updated by bridge as part of ApplySyncChanges. DCHECK(entity_tracker_->AllStorageKeysPopulated()); @@ -693,7 +690,7 @@ bool ClientTagBasedModelTypeProcessor::ValidateUpdate( const sync_pb::ModelTypeState& model_type_state, const UpdateResponseDataList& updates) { - if (!entity_tracker_->model_type_state().initial_sync_done()) { + if (!entity_tracker_) { // Due to uss_migrator, initial sync (when migrating from non-USS) does not // contain any gc directives. Thus, we cannot expect the conditions below to // be satisfied. It is okay to skip the check as for an initial sync, the gc @@ -733,30 +730,33 @@ bridge_->CreateMetadataChangeList(); DCHECK(model_ready_to_sync_); - // Check that the worker correctly marked initial sync as done - // for this update. + // Check that the worker correctly marked initial sync as done for this + // update. DCHECK(model_type_state.initial_sync_done()); - if (HasClearAllDirective(model_type_state)) { + // Ensure that this is the initial sync, and it was not already marked done. + DCHECK(HasClearAllDirective(model_type_state) || !entity_tracker_); + + if (entity_tracker_ && HasClearAllDirective(model_type_state)) { ExpireAllEntries(metadata_changes.get()); - } else { - // Ensure that this is the initial sync, and it was not already marked done. - DCHECK(!entity_tracker_->model_type_state().initial_sync_done()); + entity_tracker_->set_model_type_state(model_type_state); + } + + if (!entity_tracker_) { + entity_tracker_ = std::make_unique<ProcessorEntityTracker>( + model_type_state, EntityMetadataMap()); } // TODO(crbug.com/1041888): the comment below may be wrong in case where a - // datatype supports non-incremental updates and local updates are acceptable. - + // datatype supports non-incremental updates and local updates are + // acceptable. // Given that we either just removed all existing sync entities (in the full - // update case), or we just started sync for the first time, we should not - // have any entities here. + // update case). DCHECK(!entity_tracker_->size()); - EntityChangeList entity_data; - - entity_tracker_->set_model_type_state(model_type_state); metadata_changes->UpdateModelTypeState(entity_tracker_->model_type_state()); + EntityChangeList entity_data; for (syncer::UpdateResponseData& update : updates) { const ClientTagHash& client_tag_hash = update.entity.client_tag_hash; if (client_tag_hash.value().empty()) { @@ -812,6 +812,7 @@ UpdateResponseDataList updates) { DCHECK(model_ready_to_sync_); DCHECK(model_type_state.initial_sync_done()); + DCHECK(entity_tracker_); ClientTagBasedRemoteUpdateHandler updates_handler(type_, bridge_, entity_tracker_.get()); @@ -832,6 +833,8 @@ ConsumeDataBatch(std::move(storage_keys_to_load), std::move(data_batch)); + // TODO(rushans): looks like some old logic, remove ConnectIfReady() in a + // separate patch. ConnectIfReady(); CommitLocalChanges(max_entries, std::move(callback)); } @@ -839,6 +842,7 @@ void ClientTagBasedModelTypeProcessor::ConsumeDataBatch( std::unordered_set<std::string> storage_keys_to_load, std::unique_ptr<DataBatch> data_batch) { + DCHECK(entity_tracker_); while (data_batch->HasNext()) { KeyAndData data = data_batch->Next(); const std::string& storage_key = data.first; @@ -896,6 +900,7 @@ size_t max_entries, GetLocalChangesCallback callback) { DCHECK(!model_error_); + DCHECK(entity_tracker_); // Prepares entities commit request data for entities which are // out of sync with the sync thread. CommitRequestDataList commit_requests; @@ -918,6 +923,7 @@ ClientTagHash ClientTagBasedModelTypeProcessor::GetClientTagHash( const std::string& storage_key, const EntityData& data) const { + DCHECK(entity_tracker_); const base::Optional<ClientTagHash> client_tag_hash = entity_tracker_->GetClientTagHash(storage_key); DCHECK(bridge_->SupportsGetClientTag()); @@ -930,6 +936,7 @@ const std::string& storage_key, const EntityData& data) { DCHECK(!bridge_->SupportsGetStorageKey() || !storage_key.empty()); + DCHECK(entity_tracker_); ProcessorEntity* entity_ptr = entity_tracker_->Add(storage_key, data); return entity_ptr; } @@ -955,7 +962,9 @@ size_t ClientTagBasedModelTypeProcessor::EstimateMemoryUsage() const { using base::trace_event::EstimateMemoryUsage; size_t memory_usage = 0; - memory_usage += entity_tracker_->EstimateMemoryUsage(); + if (entity_tracker_) { + memory_usage += entity_tracker_->EstimateMemoryUsage(); + } if (bridge_) { memory_usage += bridge_->EstimateSyncOverheadMemoryUsage(); } @@ -963,12 +972,13 @@ } bool ClientTagBasedModelTypeProcessor::HasLocalChangesForTest() const { - return entity_tracker_->HasLocalChanges(); + return entity_tracker_ && entity_tracker_->HasLocalChanges(); } bool ClientTagBasedModelTypeProcessor::IsTrackingEntityForTest( const std::string& storage_key) const { - return entity_tracker_->GetEntityForStorageKey(storage_key) != nullptr; + return entity_tracker_ && + entity_tracker_->GetEntityForStorageKey(storage_key) != nullptr; } bool ClientTagBasedModelTypeProcessor::IsModelReadyToSyncForTest() const { @@ -978,6 +988,7 @@ void ClientTagBasedModelTypeProcessor::ExpireAllEntries( MetadataChangeList* metadata_changes) { DCHECK(metadata_changes); + DCHECK(entity_tracker_); std::vector<std::string> storage_key_to_be_deleted; for (const ProcessorEntity* entity : @@ -996,6 +1007,7 @@ const std::string& storage_key, MetadataChangeList* metadata_change_list) { DCHECK(!storage_key.empty()); + DCHECK(entity_tracker_); DCHECK(entity_tracker_->GetEntityForStorageKey(storage_key)); metadata_change_list->ClearMetadata(storage_key); entity_tracker_->RemoveEntityForStorageKey(storage_key); @@ -1011,7 +1023,7 @@ break; case CLEAR_METADATA: model_ready_to_sync_ = false; - entity_tracker_ = std::make_unique<ProcessorEntityTracker>(type_); + entity_tracker_.reset(); break; } @@ -1083,18 +1095,77 @@ std::move(callback).Run(type_, std::move(all_nodes)); } +void ClientTagBasedModelTypeProcessor::InitializeCacheGuidForOldClients() { + DCHECK(entity_tracker_); + + // TODO(rushans): remove this logic because cache GUID must have been + // initialized for most of clients. Clients that have not initialized yet will + // behave as in cache GUID mismatch situation. + if (!entity_tracker_->model_type_state().has_cache_guid()) { + sync_pb::ModelTypeState model_type_state = + entity_tracker_->model_type_state(); + model_type_state.set_cache_guid(activation_request_.cache_guid); + entity_tracker_->set_model_type_state(model_type_state); + } +} + +void ClientTagBasedModelTypeProcessor::CheckForInvalidPersistedMetadata() { + if (!entity_tracker_) { + return; + } + + InitializeCacheGuidForOldClients(); + + const sync_pb::ModelTypeState& model_type_state = + entity_tracker_->model_type_state(); + const bool invalid_cache_guid = + model_type_state.cache_guid() != activation_request_.cache_guid; + const bool invalid_data_type_id = + model_type_state.progress_marker().data_type_id() != + GetSpecificsFieldNumberFromModelType(type_); + const bool invalid_authenticated_account_id = + model_type_state.authenticated_account_id() != + activation_request_.authenticated_account_id.ToString(); + // Check for invalid persisted metadata. + // TODO(rushans): add UMA for each case of inconsistent data. + if (!invalid_cache_guid && !invalid_data_type_id && + !invalid_authenticated_account_id) { + return; + } + // There is a mismatch between the cache guid or the data type id stored + // in |model_type_state_| and the one received from sync. This indicates + // that the stored metadata are invalid (e.g. has been manipulated) and + // don't belong to the current syncing client. + if (model_type_state.progress_marker().data_type_id() != + GetSpecificsFieldNumberFromModelType(type_)) { + UMA_HISTOGRAM_ENUMERATION("Sync.PersistedModelTypeIdMismatch", + ModelTypeHistogramValue(type_)); + } + ClearMetadataAndResetState(); + // The model is still ready to sync (with the same |bridge_|) - replay + // the initialization. + model_ready_to_sync_ = true; + // Notify the bridge sync is starting to simulate an enable event. + bridge_->OnSyncStarting(activation_request_); + DCHECK(!entity_tracker_); +} + void ClientTagBasedModelTypeProcessor::GetStatusCountersForDebugging( StatusCountersCallback callback) { StatusCounters counters; - counters.num_entries_and_tombstones = entity_tracker_->size(); - counters.num_entries = entity_tracker_->CountNonTombstoneEntries(); + if (entity_tracker_) { + counters.num_entries_and_tombstones = entity_tracker_->size(); + counters.num_entries = entity_tracker_->CountNonTombstoneEntries(); + } std::move(callback).Run(type_, counters); } void ClientTagBasedModelTypeProcessor::RecordMemoryUsageAndCountsHistograms() { SyncRecordModelTypeMemoryHistogram(type_, EstimateMemoryUsage()); - SyncRecordModelTypeCountHistogram( - type_, entity_tracker_->CountNonTombstoneEntries()); + const size_t non_tombstone_entries_count = + entity_tracker_ == nullptr ? 0 + : entity_tracker_->CountNonTombstoneEntries(); + SyncRecordModelTypeCountHistogram(type_, non_tombstone_entries_count); } } // namespace syncer
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor.h b/components/sync/model_impl/client_tag_based_model_type_processor.h index 99a423a..7b9d788a 100644 --- a/components/sync/model_impl/client_tag_based_model_type_processor.h +++ b/components/sync/model_impl/client_tag_based_model_type_processor.h
@@ -210,6 +210,13 @@ void MergeDataWithMetadataForDebugging(AllNodesCallback callback, std::unique_ptr<DataBatch> batch); + // Initialize the cache_guid for old clients that didn't persist it. + void InitializeCacheGuidForOldClients(); + + // Checks for valid cache GUID and data type id. Resets state if metadata is + // invalid. + void CheckForInvalidPersistedMetadata(); + ///////////////////// // Processor state // /////////////////////
diff --git a/components/sync/model_impl/client_tag_based_model_type_processor_unittest.cc b/components/sync/model_impl/client_tag_based_model_type_processor_unittest.cc index b5cb240..a1c7404 100644 --- a/components/sync/model_impl/client_tag_based_model_type_processor_unittest.cc +++ b/components/sync/model_impl/client_tag_based_model_type_processor_unittest.cc
@@ -38,6 +38,8 @@ namespace { +const char kDefaultAuthenticatedAccountId[] = "DefaultAccountId"; + const char kKey1[] = "key1"; const char kKey2[] = "key2"; const char kKey3[] = "key3"; @@ -133,6 +135,8 @@ model_type_state.set_initial_sync_done(is_done); model_type_state.mutable_progress_marker()->set_data_type_id( GetSpecificsFieldNumberFromModelType(model_type_)); + model_type_state.set_authenticated_account_id( + kDefaultAuthenticatedAccountId); db_->set_model_type_state(model_type_state); } @@ -272,10 +276,10 @@ void OnCommitDataLoaded() { bridge()->OnCommitDataLoaded(); } - void OnSyncStarting( - const std::string& authenticated_account_id = "SomeAccountId", - const std::string& cache_guid = "TestCacheGuid", - SyncMode sync_mode = SyncMode::kFull) { + void OnSyncStarting(const std::string& authenticated_account_id = + kDefaultAuthenticatedAccountId, + const std::string& cache_guid = "TestCacheGuid", + SyncMode sync_mode = SyncMode::kFull) { DataTypeActivationRequest request; request.error_handler = base::BindRepeating( &ClientTagBasedModelTypeProcessorTest::ErrorReceived, @@ -374,7 +378,9 @@ // Return the number of entities the processor has metadata for. size_t ProcessorEntityCount() const { - return type_processor()->entity_tracker_->size(); + if (type_processor()->entity_tracker_) + return type_processor()->entity_tracker_->size(); + return 0; } // Expect to receive an error from the processor. @@ -454,9 +460,10 @@ ShouldExposeNewlyTrackedAccountId) { ModelReadyToSync(); ASSERT_EQ("", type_processor()->TrackedAccountId()); - OnSyncStarting("SomeAccountId"); + OnSyncStarting(); worker()->UpdateFromServer(); - EXPECT_EQ("SomeAccountId", type_processor()->TrackedAccountId()); + EXPECT_EQ(kDefaultAuthenticatedAccountId, + type_processor()->TrackedAccountId()); } TEST_F(ClientTagBasedModelTypeProcessorTest, @@ -482,7 +489,7 @@ ShouldExposeNewlyTrackedCacheGuid) { ModelReadyToSync(); ASSERT_EQ("", type_processor()->TrackedCacheGuid()); - OnSyncStarting("SomeAccountId", "TestCacheGuid"); + OnSyncStarting(kDefaultAuthenticatedAccountId, "TestCacheGuid"); worker()->UpdateFromServer(); EXPECT_EQ("TestCacheGuid", type_processor()->TrackedCacheGuid()); } @@ -493,6 +500,7 @@ sync_pb::ModelTypeState model_type_state(metadata_batch->GetModelTypeState()); model_type_state.set_initial_sync_done(true); model_type_state.set_cache_guid("PersistedCacheGuid"); + model_type_state.set_authenticated_account_id(kDefaultAuthenticatedAccountId); model_type_state.mutable_progress_marker()->set_data_type_id( GetSpecificsFieldNumberFromModelType(GetModelType())); metadata_batch->SetModelTypeState(model_type_state); @@ -502,7 +510,7 @@ EXPECT_EQ("PersistedCacheGuid", type_processor()->TrackedCacheGuid()); // If sync gets started, the cache guid should still be set. - OnSyncStarting("SomeAccountId", "PersistedCacheGuid"); + OnSyncStarting(kDefaultAuthenticatedAccountId, "PersistedCacheGuid"); EXPECT_EQ("PersistedCacheGuid", type_processor()->TrackedCacheGuid()); } @@ -1873,7 +1881,8 @@ TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldReportEphemeralConfigurationTime) { InitializeToMetadataLoaded(/*initial_sync_done=*/false); - OnSyncStarting("SomeAccountId", "TestCacheGuid", SyncMode::kTransportOnly); + OnSyncStarting(kDefaultAuthenticatedAccountId, "TestCacheGuid", + SyncMode::kTransportOnly); base::HistogramTester histogram_tester; @@ -1897,7 +1906,8 @@ TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldReportPersistentConfigurationTime) { InitializeToMetadataLoaded(/*initial_sync_done=*/false); - OnSyncStarting("SomeAccountId", "TestCacheGuid", SyncMode::kFull); + OnSyncStarting(kDefaultAuthenticatedAccountId, "TestCacheGuid", + SyncMode::kFull); base::HistogramTester histogram_tester; @@ -1966,7 +1976,8 @@ TEST_F(FullUpdateClientTagBasedModelTypeProcessorTest, ShouldReportEphemeralConfigurationTimeOnlyForFirstFullUpdate) { InitializeToMetadataLoaded(/*initial_sync_done=*/false); - OnSyncStarting("SomeAccountId", "TestCacheGuid", SyncMode::kTransportOnly); + OnSyncStarting(kDefaultAuthenticatedAccountId, "TestCacheGuid", + SyncMode::kTransportOnly); UpdateResponseDataList updates1; updates1.push_back(worker()->GenerateUpdateData( @@ -2534,6 +2545,7 @@ TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldPropagateFailedCommitItemsToBridgeWhenCommitCompleted) { + InitializeToReadyState(); FailedCommitResponseData response_data; response_data.client_tag_hash = GetHash("dummy tag"); response_data.response_type = sync_pb::CommitResponse::TRANSIENT_ERROR; @@ -2576,6 +2588,7 @@ TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldNotPropagateFailedCommitAttemptToBridgeWhenNoFailedItems) { + InitializeToReadyState(); auto on_commit_attempt_errors_callback = base::BindOnce( [](const FailedCommitResponseDataList& error_response_list) { ADD_FAILURE() @@ -2609,8 +2622,9 @@ ShouldExposeNewlyTrackedAccountId) { ModelReadyToSync(); ASSERT_EQ("", type_processor()->TrackedAccountId()); - OnSyncStarting("SomeAccountId"); - EXPECT_EQ("SomeAccountId", type_processor()->TrackedAccountId()); + OnSyncStarting(); + EXPECT_EQ(kDefaultAuthenticatedAccountId, + type_processor()->TrackedAccountId()); } TEST_F(CommitOnlyClientTagBasedModelTypeProcessorTest, @@ -2705,4 +2719,50 @@ EXPECT_EQ(0U, db()->metadata_count()); } +TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldResetOnInvalidCacheGuid) { + ResetStateWriteItem(kKey1, kValue1); + InitializeToMetadataLoaded(); + OnSyncStarting(); + OnCommitDataLoaded(); + ASSERT_EQ(1U, ProcessorEntityCount()); + + ResetStateWriteItem(kKey1, kValue1); + sync_pb::ModelTypeState model_type_state = db()->model_type_state(); + model_type_state.set_cache_guid("OtherCacheGuid"); + db()->set_model_type_state(model_type_state); + + ModelReadyToSync(); + OnSyncStarting(); + EXPECT_EQ(0U, ProcessorEntityCount()); +} + +TEST_F(ClientTagBasedModelTypeProcessorTest, ShouldResetOnInvalidDataTypeId) { + ResetStateWriteItem(kKey1, kValue1); + ASSERT_EQ(0U, ProcessorEntityCount()); + + // Initialize change processor, expect to load data from the bridge. + InitializeToMetadataLoaded(); + OnSyncStarting(); + OnCommitDataLoaded(); + ASSERT_EQ(1U, ProcessorEntityCount()); + + ResetStateWriteItem(kKey1, kValue1); + + base::HistogramTester histogram_tester; + OnSyncStarting(); + // Set different data type id. + sync_pb::ModelTypeState model_type_state = db()->model_type_state(); + + ASSERT_NE(model_type_state.progress_marker().data_type_id(), + GetSpecificsFieldNumberFromModelType(AUTOFILL)); + model_type_state.mutable_progress_marker()->set_data_type_id( + GetSpecificsFieldNumberFromModelType(AUTOFILL)); + db()->set_model_type_state(model_type_state); + + ModelReadyToSync(); + EXPECT_EQ(0U, ProcessorEntityCount()); + histogram_tester.ExpectUniqueSample("Sync.PersistedModelTypeIdMismatch", + ModelTypeForHistograms::kPreferences, 1); +} + } // namespace syncer
diff --git a/components/sync/model_impl/processor_entity_tracker.cc b/components/sync/model_impl/processor_entity_tracker.cc index ba70792b..adab2d3 100644 --- a/components/sync/model_impl/processor_entity_tracker.cc +++ b/components/sync/model_impl/processor_entity_tracker.cc
@@ -12,14 +12,10 @@ namespace syncer { -ProcessorEntityTracker::ProcessorEntityTracker(ModelType type) { - InitializeMetadata(type); -} - ProcessorEntityTracker::ProcessorEntityTracker( + const sync_pb::ModelTypeState& model_type_state, std::map<std::string, std::unique_ptr<sync_pb::EntityMetadata>> - metadata_map, - const sync_pb::ModelTypeState& model_type_state) + metadata_map) : model_type_state_(model_type_state) { DCHECK(model_type_state.initial_sync_done()); for (auto& kv : metadata_map) { @@ -196,11 +192,6 @@ return entities_.size(); } -void ProcessorEntityTracker::InitializeMetadata(ModelType type) { - model_type_state_.mutable_progress_marker()->set_data_type_id( - GetSpecificsFieldNumberFromModelType(type)); -} - std::vector<const ProcessorEntity*> ProcessorEntityTracker::IncrementSequenceNumberForAllExcept( const std::unordered_set<std::string>& already_updated_storage_keys) {
diff --git a/components/sync/model_impl/processor_entity_tracker.h b/components/sync/model_impl/processor_entity_tracker.h index 7c513727..01acc3a 100644 --- a/components/sync/model_impl/processor_entity_tracker.h +++ b/components/sync/model_impl/processor_entity_tracker.h
@@ -23,15 +23,13 @@ // This component tracks entities for ClientTagBasedModelTypeProcessor. class ProcessorEntityTracker { public: - explicit ProcessorEntityTracker(ModelType type); - // Creates tracker and fills entities data from batch metadata map. This // constructor must be used only if initial_sync_done returns true in // |model_type_state|. ProcessorEntityTracker( + const sync_pb::ModelTypeState& model_type_state, std::map<std::string, std::unique_ptr<sync_pb::EntityMetadata>> - metadata_map, - const sync_pb::ModelTypeState& model_type_state); + metadata_map); ~ProcessorEntityTracker(); @@ -91,9 +89,6 @@ model_type_state_ = model_type_state; } - // Sets data type id to model type state. Used for first time syncing. - void InitializeMetadata(ModelType type); - // Returns number of entities, including tombstones. size_t size() const;
diff --git a/components/sync_sessions/session_sync_bridge_unittest.cc b/components/sync_sessions/session_sync_bridge_unittest.cc index c14d8998..0493c00 100644 --- a/components/sync_sessions/session_sync_bridge_unittest.cc +++ b/components/sync_sessions/session_sync_bridge_unittest.cc
@@ -228,6 +228,7 @@ state.set_initial_sync_done(true); state.mutable_progress_marker()->set_data_type_id( GetSpecificsFieldNumberFromModelType(syncer::SESSIONS)); + state.set_authenticated_account_id("SomeAccountId"); syncer::UpdateResponseDataList initial_updates; for (const SessionSpecifics& specifics : remote_data) { initial_updates.push_back(SpecificsToUpdateResponse(specifics));
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc index dfe9cce4b..ddaea4c 100644 --- a/components/viz/common/resources/resource_format_utils.cc +++ b/components/viz/common/resources/resource_format_utils.cc
@@ -200,6 +200,8 @@ return GL_RG8_EXT; else if (format == ETC1) return GL_ETC1_RGB8_OES; + else if (format == RGBA_1010102 || format == BGRA_1010102) + return GL_RGB10_A2_EXT; return GLDataFormat(format); } @@ -337,6 +339,8 @@ case R16_EXT: case RGBA_4444: case RGBA_8888: + case RGBA_1010102: + case BGRA_1010102: case RGBA_F16: return true; // These formats have no BufferFormat equivalent or are only used @@ -350,8 +354,6 @@ case RG_88: case RGBX_8888: case BGRX_8888: - case RGBA_1010102: - case BGRA_1010102: case YVU_420: case YUV_420_BIPLANAR: case P010: @@ -431,7 +433,6 @@ switch (format) { case BGR_565: case BGRX_8888: - case BGRA_1010102: case YVU_420: case YUV_420_BIPLANAR: case P010:
diff --git a/components/viz/service/display/ca_layer_overlay.cc b/components/viz/service/display/ca_layer_overlay.cc index 4638b06..393a085 100644 --- a/components/viz/service/display/ca_layer_overlay.cc +++ b/components/viz/service/display/ca_layer_overlay.cc
@@ -196,7 +196,8 @@ return CA_LAYER_FAILED_QUAD_BLEND_MODE; // Early-out for invisible quads. - if (quad->shared_quad_state->opacity == 0.f) { + if (quad->shared_quad_state->opacity == 0.f || + quad->visible_rect.IsEmpty()) { *skip = true; return CA_LAYER_SUCCESS; } @@ -307,8 +308,15 @@ CALayerOverlayList* ca_layer_overlays) const { CALayerResult result = CA_LAYER_SUCCESS; - if (quad_list.size() < kTooManyQuads) - ca_layer_overlays->reserve(quad_list.size()); + size_t num_visible_quads = quad_list.size(); + for (const auto* quad : quad_list) { + if (quad->shared_quad_state->opacity == 0.f || + quad->visible_rect.IsEmpty()) { + num_visible_quads--; + } + } + if (num_visible_quads < kTooManyQuads) + ca_layer_overlays->reserve(num_visible_quads); else result = CA_LAYER_FAILED_TOO_MANY_QUADS;
diff --git a/components/viz/service/display/overlay_ca_unittest.cc b/components/viz/service/display/overlay_ca_unittest.cc index f4adf98..4be3865 100644 --- a/components/viz/service/display/overlay_ca_unittest.cc +++ b/components/viz/service/display/overlay_ca_unittest.cc
@@ -382,6 +382,28 @@ EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); } +TEST_F(CALayerOverlayTest, SkipNonVisible) { + std::unique_ptr<RenderPass> pass = CreateRenderPass(); + CreateFullscreenCandidateQuad( + resource_provider_.get(), child_resource_provider_.get(), + child_provider_.get(), pass->shared_quad_state_list.back(), pass.get()); + pass->quad_list.back()->visible_rect.set_size(gfx::Size()); + + gfx::Rect damage_rect; + CALayerOverlayList ca_layer_list; + OverlayProcessorInterface::FilterOperationsMap render_pass_filters; + OverlayProcessorInterface::FilterOperationsMap render_pass_backdrop_filters; + RenderPassList pass_list; + pass_list.push_back(std::move(pass)); + overlay_processor_->ProcessForOverlays( + resource_provider_.get(), &pass_list, GetIdentityColorMatrix(), + render_pass_filters, render_pass_backdrop_filters, nullptr, + &ca_layer_list, &damage_rect_, &content_bounds_); + EXPECT_EQ(gfx::Rect(), damage_rect); + EXPECT_EQ(0U, ca_layer_list.size()); + EXPECT_EQ(0U, output_surface_->bind_framebuffer_count()); +} + class CALayerOverlayRPDQTest : public CALayerOverlayTest { protected: void SetUp() override { @@ -501,8 +523,10 @@ TEST_F(CALayerOverlayRPDQTest, TooManyRenderPassDrawQuads) { filters_.Append(cc::FilterOperation::CreateBlurFilter(0.8f)); int count = 35; - - for (int i = 0; i < count; ++i) { + quad_->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect, + kOverlayRect, render_pass_id_, 2, gfx::RectF(), gfx::Size(), + gfx::Vector2dF(1, 1), gfx::PointF(), gfx::RectF(), false, 1.0f); + for (int i = 1; i < count; ++i) { auto* quad = pass_->CreateAndAppendDrawQuad<RenderPassDrawQuad>(); quad->SetNew(pass_->shared_quad_state_list.back(), kOverlayRect, kOverlayRect, render_pass_id_, 2, gfx::RectF(), gfx::Size(),
diff --git a/content/browser/appcache/appcache.cc b/content/browser/appcache/appcache.cc index 52f9bcd1..f823298 100644 --- a/content/browser/appcache/appcache.cc +++ b/content/browser/appcache/appcache.cc
@@ -341,7 +341,6 @@ info.response_size = pair.second.response_size(); info.padding_size = pair.second.padding_size(); info.response_id = pair.second.response_id(); - info.token_expires = pair.second.token_expires(); } }
diff --git a/content/browser/appcache/appcache_internals_ui.cc b/content/browser/appcache/appcache_internals_ui.cc index 7e9f65c..aae37ef 100644 --- a/content/browser/appcache/appcache_internals_ui.cc +++ b/content/browser/appcache/appcache_internals_ui.cc
@@ -146,7 +146,6 @@ dict->SetBoolean("isFallback", resource_info.is_fallback); dict->SetBoolean("isIntercept", resource_info.is_intercept); dict->SetBoolean("isForeign", resource_info.is_foreign); - dict->SetDouble("tokenExpires", resource_info.token_expires.ToJsTime()); return dict; }
diff --git a/content/browser/browser_interface_binders.cc b/content/browser/browser_interface_binders.cc index 2cc94e3..113086e 100644 --- a/content/browser/browser_interface_binders.cc +++ b/content/browser/browser_interface_binders.cc
@@ -615,6 +615,10 @@ base::BindRepeating(&RenderFrameHostImpl::BindRestrictedCookieManager, base::Unretained(host))); + map->Add<network::mojom::HasTrustTokensAnswerer>( + base::BindRepeating(&RenderFrameHostImpl::BindHasTrustTokensAnswerer, + base::Unretained(host))); + map->Add<shape_detection::mojom::BarcodeDetectionProvider>( base::BindRepeating(&BindBarcodeDetectionProvider));
diff --git a/content/browser/display_cutout/display_cutout_host_impl.cc b/content/browser/display_cutout/display_cutout_host_impl.cc index 7a266559..e8d64f7 100644 --- a/content/browser/display_cutout/display_cutout_host_impl.cc +++ b/content/browser/display_cutout/display_cutout_host_impl.cc
@@ -71,9 +71,7 @@ // If we finish a main frame navigation and the |WebDisplayMode| is // fullscreen then we should make the main frame the current // |RenderFrameHost|. - RenderWidgetHostImpl* rwh = - web_contents_impl_->GetRenderViewHost()->GetWidget(); - blink::mojom::DisplayMode mode = web_contents_impl_->GetDisplayMode(rwh); + blink::mojom::DisplayMode mode = web_contents_impl_->GetDisplayMode(); if (mode == blink::mojom::DisplayMode::kFullscreen) SetCurrentRenderFrameHost(web_contents_impl_->GetMainFrame()); }
diff --git a/content/browser/frame_host/back_forward_cache_impl.cc b/content/browser/frame_host/back_forward_cache_impl.cc index 9ce2816..ff7a2122 100644 --- a/content/browser/frame_host/back_forward_cache_impl.cc +++ b/content/browser/frame_host/back_forward_cache_impl.cc
@@ -149,8 +149,7 @@ FeatureToBit(WebSchedulerTrackedFeature::kWakeLock) | FeatureToBit(WebSchedulerTrackedFeature::kWebShare) | FeatureToBit(WebSchedulerTrackedFeature::kWebFileSystem) | - FeatureToBit(WebSchedulerTrackedFeature::kAppBanner) | - FeatureToBit(WebSchedulerTrackedFeature::kPrinting); + FeatureToBit(WebSchedulerTrackedFeature::kAppBanner); uint64_t result = kAlwaysDisallowedFeatures;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 8e11789f..ed32810 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -188,6 +188,7 @@ #include "services/device/public/mojom/wake_lock.mojom.h" #include "services/device/public/mojom/wake_lock_context.mojom.h" #include "services/network/public/cpp/features.h" +#include "services/network/public/cpp/is_potentially_trustworthy.h" #include "services/network/public/cpp/wrapper_shared_url_loader_factory.h" #include "services/network/public/mojom/network_service.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -6978,6 +6979,44 @@ std::move(receiver)); } +void RenderFrameHostImpl::BindHasTrustTokensAnswerer( + mojo::PendingReceiver<network::mojom::HasTrustTokensAnswerer> receiver) { + auto top_frame_origin = ComputeTopFrameOrigin(GetLastCommittedOrigin()); + + // A check at the callsite in the renderer ensures a correctly functioning + // renderer will only request this Mojo handle if the top-frame origin is + // potentially trustworthy and has scheme HTTP or HTTPS. + if ((top_frame_origin.scheme() != url::kHttpScheme && + top_frame_origin.scheme() != url::kHttpsScheme) || + !network::IsOriginPotentiallyTrustworthy(top_frame_origin)) { + mojo::ReportBadMessage( + "Attempted to get a HasTrustTokensAnswerer for a non-trustworthy or " + "non-HTTP/HTTPS top-frame origin."); + return; + } + + // This is enforced in benign renderers by the [SecureContext] IDL + // attribute on Document::hasTrustToken. + if (!network::IsOriginPotentiallyTrustworthy(GetLastCommittedOrigin())) { + mojo::ReportBadMessage( + "Attempted to get a HasTrustTokensAnswerer from an insecure context."); + return; + } + + // This is enforced in benign renderers by the RuntimeEnabled=TrustTokens IDL + // attribute (the base::Feature's value is tied to the + // RuntimeEnabledFeature's). + if (!base::FeatureList::IsEnabled(network::features::kTrustTokens)) { + mojo::ReportBadMessage( + "Attempted to get a HasTrustTokensAnswerer with Trust Tokens " + "disabled."); + return; + } + + GetProcess()->GetStoragePartition()->CreateHasTrustTokensAnswerer( + std::move(receiver), ComputeTopFrameOrigin(GetLastCommittedOrigin())); +} + void RenderFrameHostImpl::GetInterface( const std::string& interface_name, mojo::ScopedMessagePipeHandle interface_pipe) {
diff --git a/content/browser/frame_host/render_frame_host_impl.h b/content/browser/frame_host/render_frame_host_impl.h index 78614f4..b222465 100644 --- a/content/browser/frame_host/render_frame_host_impl.h +++ b/content/browser/frame_host/render_frame_host_impl.h
@@ -83,6 +83,7 @@ #include "services/network/public/cpp/content_security_policy/csp_context.h" #include "services/network/public/cpp/cross_origin_embedder_policy.h" #include "services/network/public/mojom/network_context.mojom.h" +#include "services/network/public/mojom/trust_tokens.mojom.h" #include "services/service_manager/public/cpp/binder_registry.h" #include "services/service_manager/public/mojom/interface_provider.mojom.h" #include "services/viz/public/mojom/hit_test/input_target_client.mojom.h" @@ -1238,6 +1239,18 @@ void BindRestrictedCookieManager( mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver); + // Requires the following preconditions, reporting a bad message otherwise. + // + // 1. This frame's top-frame origin must be potentially trustworthy and + // have scheme HTTP or HTTPS. (See network::SuitableTrustTokenOrigin's class + // comment for the rationale.) + // + // 2. Trust Tokens must be enabled (network::features::kTrustTokens). + // + // 3. This frame's origin must be potentially trustworthy. + void BindHasTrustTokensAnswerer( + mojo::PendingReceiver<network::mojom::HasTrustTokensAnswerer> receiver); + // Creates connections to WebUSB interfaces bound to this frame. void CreateWebUsbService( mojo::PendingReceiver<blink::mojom::WebUsbService> receiver);
diff --git a/content/browser/renderer_host/render_widget_host_delegate.cc b/content/browser/renderer_host/render_widget_host_delegate.cc index 7c12613..3f91d5f 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.cc +++ b/content/browser/renderer_host/render_widget_host_delegate.cc
@@ -87,8 +87,7 @@ return false; } -blink::mojom::DisplayMode RenderWidgetHostDelegate::GetDisplayMode( - RenderWidgetHostImpl* render_widget_host) const { +blink::mojom::DisplayMode RenderWidgetHostDelegate::GetDisplayMode() const { return blink::mojom::DisplayMode::kBrowser; }
diff --git a/content/browser/renderer_host/render_widget_host_delegate.h b/content/browser/renderer_host/render_widget_host_delegate.h index ec91ee51..3874e6f 100644 --- a/content/browser/renderer_host/render_widget_host_delegate.h +++ b/content/browser/renderer_host/render_widget_host_delegate.h
@@ -218,9 +218,9 @@ // solid color is displayed instead. virtual bool ShouldShowStaleContentOnEviction(); - // Returns the display mode for the view. - virtual blink::mojom::DisplayMode GetDisplayMode( - RenderWidgetHostImpl* render_widget_host) const; + // Returns the display mode for all widgets in the frame tree. Only applies + // to frame-based widgets. Other widgets are always kBrowser. + virtual blink::mojom::DisplayMode GetDisplayMode() const; // Notification that the widget has lost capture. virtual void LostCapture(RenderWidgetHostImpl* render_widget_host) {}
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index 5ad66a6a..55e1970 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -781,13 +781,23 @@ // which are to be sent to the renderer process. DCHECK(view_); + // Differentiate between widgets for frames vs widgets for popups/pepper. + // Historically this was done by finding the RenderViewHost for the widget, + // but a child local root would not convert to a RenderViewHost but is for a + // frame. + const bool is_frame_widget = owner_delegate_ || owned_by_render_frame_host_; + VisualProperties visual_properties; GetScreenInfo(&visual_properties.screen_info); visual_properties.is_fullscreen_granted = delegate_->IsFullscreenForCurrentTab(); - visual_properties.display_mode = delegate_->GetDisplayMode(this); + + if (is_frame_widget) + visual_properties.display_mode = delegate_->GetDisplayMode(); + else + visual_properties.display_mode = blink::mojom::DisplayMode::kBrowser; visual_properties.zoom_level = delegate_->GetPendingPageZoomLevel(); RenderViewHostDelegateView* rvh_delegate_view = delegate_->GetDelegateView();
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc index 8ba0170..dcd2a41 100644 --- a/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc +++ b/content/browser/renderer_host/render_widget_host_view_child_frame_browsertest.cc
@@ -291,7 +291,7 @@ EXPECT_EQ(initial_size, child_visible_viewport_size); } - // Same check as abvoe but for a nested WebContents. + // Same check as above but for a nested WebContents. { base::RunLoop loop; @@ -496,4 +496,101 @@ .size() != 1); } +// Auto-resize is only implemented for Ash and GuestViews. So we need to inject +// an implementation that actually resizes the top level widget. +class DisplayModeControllingWebContentsDelegate : public WebContentsDelegate { + public: + blink::mojom::DisplayMode GetDisplayMode( + const WebContents* web_contents) override { + return mode_; + } + + void set_display_mode(blink::mojom::DisplayMode mode) { mode_ = mode; } + + private: + // The is the default value throughout the browser and renderer. + blink::mojom::DisplayMode mode_ = blink::mojom::DisplayMode::kBrowser; +}; + +// TODO(crbug.com/1060336): Unlike most VisualProperties, the DisplayMode does +// not propagate down the tree of RenderWidgets, but is sent independently to +// each RenderWidget. +IN_PROC_BROWSER_TEST_F(RenderWidgetHostViewChildFrameBrowserTest, + VisualPropertiesPropagation_DisplayMode) { + GURL main_url(embedded_test_server()->GetURL( + "a.com", "/cross_site_iframe_factory.html?a(a,b)")); + EXPECT_TRUE(NavigateToURL(shell(), main_url)); + + auto* web_contents = static_cast<WebContentsImpl*>(shell()->web_contents()); + + DisplayModeControllingWebContentsDelegate display_mode_delegate; + shell()->web_contents()->SetDelegate(&display_mode_delegate); + + // Main frame. + FrameTreeNode* root = web_contents->GetFrameTree()->root(); + RenderWidgetHostImpl* root_widget = + root->current_frame_host()->GetRenderWidgetHost(); + // In-process frame. + FrameTreeNode* ipchild = root->child_at(0); + RenderWidgetHostImpl* ipchild_widget = + ipchild->current_frame_host()->GetRenderWidgetHost(); + // Out-of-process frame. + FrameTreeNode* oopchild = root->child_at(1); + RenderWidgetHostImpl* oopchild_widget = + oopchild->current_frame_host()->GetRenderWidgetHost(); + + // Check all frames for the initial value. + EXPECT_EQ( + true, + EvalJs(root, "window.matchMedia('(display-mode: browser)').matches")); + EXPECT_EQ( + true, + EvalJs(ipchild, "window.matchMedia('(display-mode: browser)').matches")); + EXPECT_EQ( + true, + EvalJs(oopchild, "window.matchMedia('(display-mode: browser)').matches")); + + // The display mode changes. + display_mode_delegate.set_display_mode( + blink::mojom::DisplayMode::kStandalone); + // Each RenderWidgetHost would need to hear about that by having + // SynchronizeVisualProperties() called. It's not clear what triggers that but + // the place that changes the DisplayMode would be responsible. + root_widget->SynchronizeVisualProperties(); + ipchild_widget->SynchronizeVisualProperties(); + oopchild_widget->SynchronizeVisualProperties(); + + // Check all frames for the changed value. + EXPECT_EQ( + true, + EvalJsAfterLifecycleUpdate( + root, "", "window.matchMedia('(display-mode: standalone)').matches")); + EXPECT_EQ(true, + EvalJsAfterLifecycleUpdate( + ipchild, "", + "window.matchMedia('(display-mode: standalone)').matches")); + EXPECT_EQ(true, + EvalJsAfterLifecycleUpdate( + oopchild, "", + "window.matchMedia('(display-mode: standalone)').matches")); + + // Navigate a frame to b.com, which we already have a process for. + GURL same_site_url(embedded_test_server()->GetURL("b.com", "/title2.html")); + NavigateFrameToURL(root->child_at(0), same_site_url); + + // The navigated frame sees the correct (non-default) value. + EXPECT_EQ(true, + EvalJs(root->child_at(0), + "window.matchMedia('(display-mode: standalone)').matches")); + + // Navigate the frame to c.com, which we don't have a process for. + GURL cross_site_url(embedded_test_server()->GetURL("c.com", "/title2.html")); + NavigateFrameToURL(root->child_at(0), cross_site_url); + + // The navigated frame sees the correct (non-default) value. + EXPECT_EQ(true, + EvalJs(root->child_at(0), + "window.matchMedia('(display-mode: standalone)').matches")); +} + } // namespace content
diff --git a/content/browser/resources/appcache/appcache_internals.css b/content/browser/resources/appcache/appcache_internals.css index eb3908a..2daa6f5 100644 --- a/content/browser/resources/appcache/appcache_internals.css +++ b/content/browser/resources/appcache/appcache_internals.css
@@ -86,7 +86,3 @@ .appcache-details td { width: 80px; } - -.appcache-details td.token-expires { - width: 500px; -}
diff --git a/content/browser/resources/appcache/appcache_internals.html b/content/browser/resources/appcache/appcache_internals.html index 951164f..f8ab596 100644 --- a/content/browser/resources/appcache/appcache_internals.html +++ b/content/browser/resources/appcache/appcache_internals.html
@@ -104,7 +104,6 @@ <th>Response</th> <th>Padding</th> <th>Properties</th> - <th>Token Expires</th> </tr> </thead> <tbody class="appcache-details" @@ -119,9 +118,6 @@ <td jscontent="responseSize"></td> <td jscontent="paddingSize"></td> <td jscontent="properties"></td> - <td class="token-expires" jscontent= - "tokenExpires ? new Date(tokenExpires) : '(unset)'"> - </td> </tr> </tbody> </table>
diff --git a/content/browser/resources/appcache/appcache_internals.js b/content/browser/resources/appcache/appcache_internals.js index 12eccae9..0003fe0 100644 --- a/content/browser/resources/appcache/appcache_internals.js +++ b/content/browser/resources/appcache/appcache_internals.js
@@ -174,7 +174,6 @@ properties: properties, fileUrl: details.url, responseId: details.responseId, - tokenExpires: details.tokenExpires, }); } return simpleVector;
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc index c8224c0..19fe65c1 100644 --- a/content/browser/storage_partition_impl.cc +++ b/content/browser/storage_partition_impl.cc
@@ -97,6 +97,7 @@ #include "services/network/public/cpp/features.h" #include "services/network/public/mojom/cookie_manager.mojom.h" #include "services/network/public/mojom/network_context.mojom.h" +#include "services/network/public/mojom/trust_tokens.mojom.h" #include "storage/browser/blob/blob_registry_impl.h" #include "storage/browser/blob/blob_storage_context.h" #include "storage/browser/database/database_tracker.h" @@ -1669,6 +1670,14 @@ } } +void StoragePartitionImpl::CreateHasTrustTokensAnswerer( + mojo::PendingReceiver<network::mojom::HasTrustTokensAnswerer> receiver, + const url::Origin& top_frame_origin) { + DCHECK(initialized_); + GetNetworkContext()->GetHasTrustTokensAnswerer(std::move(receiver), + top_frame_origin); +} + storage::QuotaManager* StoragePartitionImpl::GetQuotaManager() { DCHECK(initialized_); return quota_manager_.get();
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h index eedad24..5bc9275 100644 --- a/content/browser/storage_partition_impl.h +++ b/content/browser/storage_partition_impl.h
@@ -131,6 +131,9 @@ int routing_id, mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) override; + void CreateHasTrustTokensAnswerer( + mojo::PendingReceiver<network::mojom::HasTrustTokensAnswerer> receiver, + const url::Origin& top_frame_origin) override; storage::QuotaManager* GetQuotaManager() override; ChromeAppCacheService* GetAppCacheService() override; BackgroundSyncContextImpl* GetBackgroundSyncContext() override;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 9f596277..f59b9b6 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -2687,11 +2687,7 @@ return IsFullscreenForCurrentTab(); } -blink::mojom::DisplayMode WebContentsImpl::GetDisplayMode( - RenderWidgetHostImpl* render_widget_host) const { - if (!RenderViewHostImpl::From(render_widget_host)) - return blink::mojom::DisplayMode::kBrowser; - +blink::mojom::DisplayMode WebContentsImpl::GetDisplayMode() const { return delegate_ ? delegate_->GetDisplayMode(this) : blink::mojom::DisplayMode::kBrowser; }
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index 05254ab..49ed5dc 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -888,8 +888,7 @@ RenderWidgetHostImpl* GetKeyboardLockWidget() override; // The following function is already listed under WebContents overrides: // bool IsFullscreenForCurrentTab() const override; - blink::mojom::DisplayMode GetDisplayMode( - RenderWidgetHostImpl* render_widget_host) const override; + blink::mojom::DisplayMode GetDisplayMode() const override; void LostCapture(RenderWidgetHostImpl* render_widget_host) override; void LostMouseLock(RenderWidgetHostImpl* render_widget_host) override; bool HasMouseLock(RenderWidgetHostImpl* render_widget_host) override;
diff --git a/content/public/browser/storage_partition.h b/content/public/browser/storage_partition.h index 022b6373..91d1b77 100644 --- a/content/public/browser/storage_partition.h +++ b/content/public/browser/storage_partition.h
@@ -18,6 +18,7 @@ #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/cookie_manager.mojom-forward.h" #include "services/network/public/mojom/restricted_cookie_manager.mojom-forward.h" +#include "services/network/public/mojom/trust_tokens.mojom-forward.h" class GURL; @@ -120,6 +121,10 @@ mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) = 0; + virtual void CreateHasTrustTokensAnswerer( + mojo::PendingReceiver<network::mojom::HasTrustTokensAnswerer> receiver, + const url::Origin& top_frame_origin) = 0; + virtual storage::QuotaManager* GetQuotaManager() = 0; virtual AppCacheService* GetAppCacheService() = 0; virtual BackgroundSyncContext* GetBackgroundSyncContext() = 0;
diff --git a/content/public/test/test_storage_partition.cc b/content/public/test/test_storage_partition.cc index 42cc3309..f08684d 100644 --- a/content/public/test/test_storage_partition.cc +++ b/content/public/test/test_storage_partition.cc
@@ -53,6 +53,12 @@ NOTREACHED(); } +void TestStoragePartition::CreateHasTrustTokensAnswerer( + mojo::PendingReceiver<network::mojom::HasTrustTokensAnswerer> receiver, + const url::Origin& top_frame_origin) { + NOTREACHED() << "Not implemented."; +} + storage::QuotaManager* TestStoragePartition::GetQuotaManager() { return quota_manager_; }
diff --git a/content/public/test/test_storage_partition.h b/content/public/test/test_storage_partition.h index 85c0b9a..3a04824 100644 --- a/content/public/test/test_storage_partition.h +++ b/content/public/test/test_storage_partition.h
@@ -75,6 +75,10 @@ mojo::PendingReceiver<network::mojom::RestrictedCookieManager> receiver) override; + void CreateHasTrustTokensAnswerer( + mojo::PendingReceiver<network::mojom::HasTrustTokensAnswerer> receiver, + const url::Origin& top_frame_origin) override; + void set_quota_manager(storage::QuotaManager* manager) { quota_manager_ = manager; }
diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index f18664d..91444f942 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc
@@ -1399,7 +1399,6 @@ std::unique_ptr<RenderWidget> render_widget = RenderWidget::CreateForFrame( params->main_frame_widget_routing_id, compositor_deps, - params->visual_properties.display_mode, render_view->widgets_never_composited()); render_widget->set_delegate(render_view); @@ -1563,7 +1562,6 @@ std::unique_ptr<RenderWidget> render_widget = RenderWidget::CreateForFrame( widget_params->routing_id, compositor_deps, - widget_params->visual_properties.display_mode, render_view->widgets_never_composited()); render_widget->set_delegate(render_view); @@ -1613,7 +1611,6 @@ // space/context. std::unique_ptr<RenderWidget> render_widget = RenderWidget::CreateForFrame( widget_params->routing_id, compositor_deps, - widget_params->visual_properties.display_mode, render_view->widgets_never_composited()); // Non-owning pointer that is self-referencing and destroyed by calling
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc index f0cb483..c0f5ce15 100644 --- a/content/renderer/render_view_impl.cc +++ b/content/renderer/render_view_impl.cc
@@ -454,10 +454,6 @@ bool local_main_frame = params->main_frame_routing_id != MSG_ROUTING_NONE; - // TODO(danakj): Put this in with making the RenderFrame? Does order matter? - if (local_main_frame) - GetWebView()->SetDisplayMode(params->visual_properties.display_mode); - ApplyWebPreferences(webkit_preferences_, GetWebView()); ApplyCommandLineToSettings(GetWebView()->GetSettings()); @@ -1048,11 +1044,6 @@ return false; } -void RenderViewImpl::ApplyNewDisplayModeForWidget( - blink::mojom::DisplayMode new_display_mode) { - GetWebView()->SetDisplayMode(new_display_mode); -} - void RenderViewImpl::ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size, const gfx::Size& max_size) { GetWebView()->EnableAutoResizeMode(min_size, max_size); @@ -1386,7 +1377,6 @@ RenderWidget* popup_widget = RenderWidget::CreateForPopup( widget_routing_id, opener_render_widget->compositor_deps(), - blink::mojom::DisplayMode::kUndefined, /*hidden=*/false, /*never_composited=*/false, std::move(widget_channel_receiver));
diff --git a/content/renderer/render_view_impl.h b/content/renderer/render_view_impl.h index 701aac4..75becca2 100644 --- a/content/renderer/render_view_impl.h +++ b/content/renderer/render_view_impl.h
@@ -368,8 +368,6 @@ void SetActiveForWidget(bool active) override; bool SupportsMultipleWindowsForWidget() override; bool ShouldAckSyntheticInputImmediately() override; - void ApplyNewDisplayModeForWidget( - blink::mojom::DisplayMode new_display_mode) override; void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size, const gfx::Size& max_size) override; void DisableAutoResizeForWidget() override;
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index f461c4e6..fb0a29d8 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -391,33 +391,30 @@ std::unique_ptr<RenderWidget> RenderWidget::CreateForFrame( int32_t widget_routing_id, CompositorDependencies* compositor_deps, - blink::mojom::DisplayMode display_mode, bool never_composited) { if (g_create_render_widget_for_frame) { return g_create_render_widget_for_frame(widget_routing_id, compositor_deps, - display_mode, never_composited, + never_composited, mojo::NullReceiver()); } - return std::make_unique<RenderWidget>( - widget_routing_id, compositor_deps, display_mode, - /*hidden=*/true, never_composited, mojo::NullReceiver()); + return std::make_unique<RenderWidget>(widget_routing_id, compositor_deps, + /*hidden=*/true, never_composited, + mojo::NullReceiver()); } RenderWidget* RenderWidget::CreateForPopup( int32_t widget_routing_id, CompositorDependencies* compositor_deps, - blink::mojom::DisplayMode display_mode, bool hidden, bool never_composited, mojo::PendingReceiver<mojom::Widget> widget_receiver) { - return new RenderWidget(widget_routing_id, compositor_deps, display_mode, - hidden, never_composited, std::move(widget_receiver)); + return new RenderWidget(widget_routing_id, compositor_deps, hidden, + never_composited, std::move(widget_receiver)); } RenderWidget::RenderWidget(int32_t widget_routing_id, CompositorDependencies* compositor_deps, - blink::mojom::DisplayMode display_mode, bool hidden, bool never_composited, mojo::PendingReceiver<mojom::Widget> widget_receiver) @@ -425,7 +422,6 @@ compositor_deps_(compositor_deps), is_hidden_(hidden), never_composited_(never_composited), - display_mode_(display_mode), next_previous_flags_(kInvalidNextPreviousFlagsValue), frame_swap_message_queue_(new FrameSwapMessageQueue(routing_id_)), widget_receiver_(this, std::move(widget_receiver)) { @@ -730,6 +726,13 @@ visual_properties.screen_info.color_space); } + // TODO(danakj): In order to synchronize updates between local roots, the + // display mode should be propagated to RenderFrameProxies and down through + // their RenderWidgetHosts to child RenderWidgets via the VisualProperties + // waterfall, instead of coming to each RenderWidget independently. + // https://developer.mozilla.org/en-US/docs/Web/CSS/@media/display-mode + GetWebWidget()->SetDisplayMode(visual_properties.display_mode); + if (delegate()) { if (size_ != visual_properties.new_size) { // Only hide popups when the size changes. Eg https://crbug.com/761908. @@ -737,11 +740,6 @@ web_view->CancelPagePopup(); } - if (display_mode_ != visual_properties.display_mode) { - display_mode_ = visual_properties.display_mode; - delegate()->ApplyNewDisplayModeForWidget(visual_properties.display_mode); - } - SetAutoResizeMode(visual_properties.auto_resize_enabled, visual_properties.min_size_for_auto_resize, visual_properties.max_size_for_auto_resize, @@ -813,7 +811,6 @@ // TODO(danakj): Isn't the display mode check redundant with the // fullscreen one? if (visual_properties.is_fullscreen_granted != is_fullscreen_granted_ || - visual_properties.display_mode != display_mode_ || visual_properties.screen_info.device_scale_factor != screen_info_.device_scale_factor) ignore_resize_ipc = false; @@ -859,7 +856,6 @@ visible_viewport_size_ = visual_properties.visible_viewport_size; if (!auto_resize_mode_) { - display_mode_ = visual_properties.display_mode; size_ = visual_properties.new_size; ResizeWebWidget(); }
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index a17e429d..b48c2e66 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -53,7 +53,6 @@ #include "ppapi/buildflags/buildflags.h" #include "services/network/public/mojom/referrer_policy.mojom.h" #include "third_party/blink/public/common/input/web_input_event.h" -#include "third_party/blink/public/mojom/manifest/display_mode.mojom.h" #include "third_party/blink/public/platform/viewport_intersection_state.h" #include "third_party/blink/public/platform/web_rect.h" #include "third_party/blink/public/platform/web_text_input_info.h" @@ -153,7 +152,6 @@ public: RenderWidget(int32_t widget_routing_id, CompositorDependencies* compositor_deps, - blink::mojom::DisplayMode display_mode, bool hidden, bool never_composited, mojo::PendingReceiver<mojom::Widget> widget_receiver); @@ -176,7 +174,6 @@ using CreateRenderWidgetFunction = std::unique_ptr<RenderWidget> (*)( int32_t, CompositorDependencies*, - blink::mojom::DisplayMode display_mode, bool never_composited, mojo::PendingReceiver<mojom::Widget> widget_receiver); // Overrides the implementation of CreateForFrame() function below. Used by @@ -190,7 +187,6 @@ static std::unique_ptr<RenderWidget> CreateForFrame( int32_t widget_routing_id, CompositorDependencies* compositor_deps, - blink::mojom::DisplayMode display_mode, bool never_composited); // Creates a RenderWidget for a popup. This is separate from CreateForFrame() @@ -201,7 +197,6 @@ static RenderWidget* CreateForPopup( int32_t widget_routing_id, CompositorDependencies* compositor_deps, - blink::mojom::DisplayMode display_mode, bool hidden, bool never_composited, mojo::PendingReceiver<mojom::Widget> widget_receiver); @@ -263,7 +258,6 @@ const gfx::Size& size() const { return size_; } bool is_fullscreen_granted() const { return is_fullscreen_granted_; } - blink::mojom::DisplayMode display_mode() const { return display_mode_; } bool is_hidden() const { return is_hidden_; } bool has_host_context_menu_location() const { return has_host_context_menu_location_; @@ -898,9 +892,6 @@ // Indicates whether tab-initiated fullscreen was granted. bool is_fullscreen_granted_ = false; - // Indicates the display mode. - blink::mojom::DisplayMode display_mode_; - // It is possible that one ImeEventGuard is nested inside another // ImeEventGuard. We keep track of the outermost one, and update it as needed. ImeEventGuard* ime_event_guard_ = nullptr;
diff --git a/content/renderer/render_widget_delegate.h b/content/renderer/render_widget_delegate.h index bd7d362..50bc8b8 100644 --- a/content/renderer/render_widget_delegate.h +++ b/content/renderer/render_widget_delegate.h
@@ -38,11 +38,6 @@ // These methods called during handling of a SynchronizeVisualProperties // message to handle updating state on the delegate. // - // Called during handling a SynchronizeVisualProperties message, with the new - // display mode that will be applied to the RenderWidget. The display mode in - // the RenderWidget is already changed when this method is called. - virtual void ApplyNewDisplayModeForWidget( - blink::mojom::DisplayMode new_display_mode) = 0; // Called during handling a SynchronizeVisualProperties message, if auto // resize is enabled, with the new auto size limits. virtual void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size,
diff --git a/content/renderer/render_widget_fullscreen_pepper.cc b/content/renderer/render_widget_fullscreen_pepper.cc index 8622d653..6e1bb4e 100644 --- a/content/renderer/render_widget_fullscreen_pepper.cc +++ b/content/renderer/render_widget_fullscreen_pepper.cc
@@ -199,7 +199,6 @@ blink::WebURL main_frame_url) : RenderWidget(routing_id, compositor_deps, - /*display_mode=*/blink::mojom::DisplayMode::kUndefined, /*hidden=*/false, /*never_composited=*/false, std::move(widget_receiver)),
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc index f03bffc..59b4ff7 100644 --- a/content/renderer/render_widget_unittest.cc +++ b/content/renderer/render_widget_unittest.cc
@@ -188,7 +188,6 @@ explicit InteractiveRenderWidget(CompositorDependencies* compositor_deps) : RenderWidget(++next_routing_id_, compositor_deps, - blink::mojom::DisplayMode::kUndefined, /*is_hidden=*/false, /*never_composited=*/false, mojo::NullReceiver()) {} @@ -538,8 +537,6 @@ void SetActiveForWidget(bool active) override {} bool SupportsMultipleWindowsForWidget() override { return true; } bool ShouldAckSyntheticInputImmediately() override { return true; } - void ApplyNewDisplayModeForWidget( - blink::mojom::DisplayMode new_display_mode) override {} void ApplyAutoResizeLimitsForWidget(const gfx::Size& min_size, const gfx::Size& max_size) override {} void DisableAutoResizeForWidget() override {}
diff --git a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt index 452ab4c5..3fae69a 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webgl_conformance_expectations.txt
@@ -287,6 +287,9 @@ crbug.com/1010942 [ win amd vulkan passthrough ] conformance/glsl/samplers/glsl-function-texture2dproj.html [ Failure ] crbug.com/angleproject/4286 [ win amd vulkan passthrough ] conformance/rendering/out-of-bounds-array-buffers.html [ Failure ] +# OpenGL / Win/ Passthrough +crbug.com/angleproject/4555 [ win opengl passthrough ] conformance/misc/type-conversion-test.html [ Skip ] + #################### # Mac failures #
diff --git a/content/test/web_test_support_renderer.cc b/content/test/web_test_support_renderer.cc index 5344842..80040b6 100644 --- a/content/test/web_test_support_renderer.cc +++ b/content/test/web_test_support_renderer.cc
@@ -64,12 +64,11 @@ std::unique_ptr<RenderWidget> CreateRenderWidgetForFrame( int32_t routing_id, CompositorDependencies* compositor_deps, - blink::mojom::DisplayMode display_mode, bool never_composited, mojo::PendingReceiver<mojom::Widget> widget_receiver) { - return std::make_unique<WebWidgetTestProxy>( - routing_id, compositor_deps, display_mode, - /*hidden=*/true, never_composited, std::move(widget_receiver)); + return std::make_unique<WebWidgetTestProxy>(routing_id, compositor_deps, + /*hidden=*/true, never_composited, + std::move(widget_receiver)); } RenderFrameImpl* CreateWebFrameTestProxy(RenderFrameImpl::CreateParams params) {
diff --git a/docs/linux/build_instructions.md b/docs/linux/build_instructions.md index 2381549..c99f9561 100644 --- a/docs/linux/build_instructions.md +++ b/docs/linux/build_instructions.md
@@ -145,7 +145,7 @@ If you are not a Googler and would like to use `Goma` [sign up](https://docs.google.com/forms/d/1NKHcyqYqw3c4jftrLPwvyiPlolRm4Hf6ObrB83wHXy8/viewform). -Once you've allowed to use `Goma` service and installed the client, +Once you're allowed to use `Goma` and have installed the client, [set the following GN args](https://www.chromium.org/developers/gn-build-configuration#TOC-Goma): ```
diff --git a/fuchsia/engine/chromium.cmx b/fuchsia/engine/chromium.cmx deleted file mode 100644 index 8a776f33..0000000 --- a/fuchsia/engine/chromium.cmx +++ /dev/null
@@ -1,14 +0,0 @@ -{ - "sandbox": { - "features": [ - "config-data", - "deprecated-ambient-replace-as-executable", - "root-ssl-certificates", - "vulkan" - ], - "services": [ - "fuchsia.logger.LogSink", - "fuchsia.process.Launcher" - ] - } -}
diff --git a/fuchsia/engine/web_engine_integration_test.cc b/fuchsia/engine/web_engine_integration_test.cc index 13e6b04..819937b 100644 --- a/fuchsia/engine/web_engine_integration_test.cc +++ b/fuchsia/engine/web_engine_integration_test.cc
@@ -263,7 +263,8 @@ // Check that if the CreateContextParams has |remote_debugging_port| set then: // - DevTools becomes available when the first debuggable Frame is created. // - DevTools closes when the last debuggable Frame is closed. -TEST_F(WebEngineIntegrationTest, RemoteDebuggingPort) { +// Test is flaky. http://crbug.com/1067727 +TEST_F(WebEngineIntegrationTest, DISABLED_RemoteDebuggingPort) { StartWebEngine(); // Create a Context with remote debugging enabled via an ephemeral port. @@ -520,4 +521,4 @@ embedded_test_server_.GetURL("/mic.html?NoPermission").spec())); navigation_listener_->RunUntilTitleEquals("ended"); -} \ No newline at end of file +}
diff --git a/fuchsia/runners/cast/cast_runner.cmx b/fuchsia/runners/cast/cast_runner.cmx index 987ad94..43e4234 100644 --- a/fuchsia/runners/cast/cast_runner.cmx +++ b/fuchsia/runners/cast/cast_runner.cmx
@@ -3,7 +3,6 @@ "features": [ "config-data" ], - "$comment": "Not all services are passed to WebEngine, see cast_runner.cc", "services": [ "chromium.cast.ApplicationConfigManager", "fuchsia.accessibility.semantics.SemanticsManager",
diff --git a/google_apis/test/embedded_setup_chromeos.html b/google_apis/test/embedded_setup_chromeos.html index 951a2e9..f99d8e73 100644 --- a/google_apis/test/embedded_setup_chromeos.html +++ b/google_apis/test/embedded_setup_chromeos.html
@@ -17,6 +17,8 @@ document.getElementById('page2').hidden = true; history.replaceState({}, '', window.location.pathname + '#identifier'); gaia.chromeOSLogin.backButton(false); + sendSetPrimaryActionLabel('Next'); + sendSetPrimaryActionEnabled(true); } gaia.chromeOSLogin.registerHtml5Listener = function() { @@ -28,6 +30,10 @@ if (!gaia.chromeOSLogin.initialized_) { gaia.chromeOSLogin.initialized_ = true; goFirstPage(); + } else if (e.data == 'primaryActionHit') { + goNext(); + } else if (e.data == 'secondaryActionHit') { + sendSetSecondaryActionEnabled(false); } } }; @@ -111,6 +117,10 @@ gaia.chromeOSLogin.attemptLogin(email, ""); gaia.chromeOSLogin.backButton(true); + sendSetPrimaryActionLabel('Next'); + sendSetPrimaryActionEnabled(true); + sendSetSecondaryActionLabel('Disable button'); + sendSetSecondaryActionEnabled(true); } else if (!document.getElementById("page2").hidden) { var email = document.getElementById("identifier").value; var password = document.getElementById("password").value;
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc index eb80eea8..6f9264a 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture.cc
@@ -746,13 +746,13 @@ FormatInfo& info = format_info_[i]; if (!viz::GLSupportsFormat(format)) continue; - GLuint image_internal_format = viz::GLInternalFormat(format); - GLenum gl_format = viz::GLDataFormat(format); - GLenum gl_type = viz::GLDataType(format); - bool uncompressed_format_valid = + const GLuint image_internal_format = viz::GLInternalFormat(format); + const GLenum gl_format = viz::GLDataFormat(format); + const GLenum gl_type = viz::GLDataType(format); + const bool uncompressed_format_valid = validators->texture_internal_format.IsValid(image_internal_format) && validators->texture_format.IsValid(gl_format); - bool compressed_format_valid = + const bool compressed_format_valid = validators->compressed_texture_format.IsValid(image_internal_format); if ((uncompressed_format_valid || compressed_format_valid) && validators->pixel_type.IsValid(gl_type)) { @@ -781,21 +781,24 @@ } } if (!info.enabled || !enable_scanout_images || - !IsGpuMemoryBufferFormatSupported(format)) + !IsGpuMemoryBufferFormatSupported(format)) { continue; - gfx::BufferFormat buffer_format = viz::BufferFormat(format); + } + const gfx::BufferFormat buffer_format = viz::BufferFormat(format); switch (buffer_format) { case gfx::BufferFormat::RGBA_8888: case gfx::BufferFormat::BGRA_8888: case gfx::BufferFormat::RGBA_F16: case gfx::BufferFormat::R_8: + case gfx::BufferFormat::BGRA_1010102: + case gfx::BufferFormat::RGBA_1010102: break; default: continue; } info.allow_scanout = true; info.buffer_format = buffer_format; - DCHECK_EQ(info.gl_format, + DCHECK_EQ(info.image_internal_format, gl::BufferFormatToGLInternalFormat(buffer_format)); if (base::Contains(gpu_preferences.texture_target_exception_list, gfx::BufferUsageAndFormat(gfx::BufferUsage::SCANOUT,
diff --git a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc index 061a6a4..5b51b2a2 100644 --- a/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc +++ b/gpu/command_buffer/service/shared_image_backing_factory_gl_texture_unittest.cc
@@ -77,7 +77,7 @@ } class SharedImageBackingFactoryGLTextureTestBase - : public testing::TestWithParam<bool> { + : public testing::TestWithParam<std::tuple<bool, viz::ResourceFormat>> { public: SharedImageBackingFactoryGLTextureTestBase(bool is_thread_safe) : shared_image_manager_( @@ -96,6 +96,13 @@ feature_info->validators()->compressed_texture_format.IsValid( GL_ETC1_RGB8_OES); + if ((get_format() == viz::ResourceFormat::BGRA_1010102 && + !feature_info->feature_flags().chromium_image_ar30) || + (get_format() == viz::ResourceFormat::RGBA_1010102 && + !feature_info->feature_flags().chromium_image_ab30)) { + GTEST_SKIP(); + } + GpuPreferences preferences; preferences.use_passthrough_cmd_decoder = use_passthrough(); backing_factory_ = std::make_unique<SharedImageBackingFactoryGLTexture>( @@ -109,9 +116,12 @@ } bool use_passthrough() { - return GetParam() && gles2::PassthroughCommandDecoderSupported(); + return std::get<0>(GetParam()) && + gles2::PassthroughCommandDecoderSupported(); } + viz::ResourceFormat get_format() { return std::get<1>(GetParam()); } + bool supports_etc1() { return supports_etc1_; } GrContext* gr_context() { return context_state_->gr_context(); } @@ -197,7 +207,7 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, Basic) { auto mailbox = Mailbox::GenerateForSharedImage(); - auto format = viz::ResourceFormat::RGBA_8888; + auto format = get_format(); gfx::Size size(256, 256); auto color_space = gfx::ColorSpace::CreateSRGB(); uint32_t usage = SHARED_IMAGE_USAGE_GLES2; @@ -264,6 +274,10 @@ gl_representation.reset(); } + // Skia does not support RGBA_1010102 as render target, only BGRA_1010102. + if (format == viz::ResourceFormat::RGBA_1010102) + return; + // Finally, validate a SharedImageRepresentationSkia. auto skia_representation = shared_image_representation_factory_->ProduceSkia( mailbox, context_state_.get()); @@ -291,20 +305,20 @@ EXPECT_TRUE(promise_texture); EXPECT_TRUE(begin_semaphores.empty()); EXPECT_TRUE(end_semaphores.empty()); - GrBackendTexture backend_texture = promise_texture->backendTexture(); - EXPECT_TRUE(backend_texture.isValid()); - EXPECT_EQ(size.width(), backend_texture.width()); - EXPECT_EQ(size.height(), backend_texture.height()); - scoped_read_access.reset(); - skia_representation.reset(); + GrBackendTexture backend_texture = promise_texture->backendTexture(); + EXPECT_TRUE(backend_texture.isValid()); + EXPECT_EQ(size.width(), backend_texture.width()); + EXPECT_EQ(size.height(), backend_texture.height()); + scoped_read_access.reset(); + skia_representation.reset(); - shared_image.reset(); - EXPECT_FALSE(mailbox_manager_.ConsumeTexture(mailbox)); + shared_image.reset(); + EXPECT_FALSE(mailbox_manager_.ConsumeTexture(mailbox)); } TEST_P(SharedImageBackingFactoryGLTextureTest, Image) { auto mailbox = Mailbox::GenerateForSharedImage(); - auto format = viz::ResourceFormat::RGBA_8888; + auto format = get_format(); gfx::Size size(256, 256); auto color_space = gfx::ColorSpace::CreateSRGB(); uint32_t usage = SHARED_IMAGE_USAGE_SCANOUT; @@ -378,6 +392,10 @@ gl_representation.reset(); } + // Skia does not support RGBA_1010102 as render target, only BGRA_1010102. + if (format == viz::ResourceFormat::RGBA_1010102) + return; + // Finally, validate a SharedImageRepresentationSkia. auto skia_representation = shared_image_representation_factory_->ProduceSkia( mailbox, context_state_.get()); @@ -417,9 +435,9 @@ if (!use_passthrough() && context_state_->feature_info()->feature_flags().ext_texture_rg) { - // Create a R-8 image texture, and check that the internal_format is that of - // the image (GL_RGBA for TextureImageFactory). This only matters for the - // validating decoder. + // Create a R-8 image texture, and check that the internal_format is that + // of the image (GL_RGBA for TextureImageFactory). This only matters for + // the validating decoder. auto format = viz::ResourceFormat::RED_8; gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle; backing = backing_factory_->CreateSharedImage( @@ -498,7 +516,7 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, InitialDataImage) { auto mailbox = Mailbox::GenerateForSharedImage(); - auto format = viz::ResourceFormat::RGBA_8888; + auto format = get_format(); gfx::Size size(256, 256); auto color_space = gfx::ColorSpace::CreateSRGB(); uint32_t usage = SHARED_IMAGE_USAGE_GLES2 | SHARED_IMAGE_USAGE_SCANOUT; @@ -537,7 +555,7 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, InitialDataWrongSize) { auto mailbox = Mailbox::GenerateForSharedImage(); - auto format = viz::ResourceFormat::RGBA_8888; + auto format = get_format(); gfx::Size size(256, 256); auto color_space = gfx::ColorSpace::CreateSRGB(); uint32_t usage = SHARED_IMAGE_USAGE_GLES2; @@ -566,7 +584,7 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, InvalidSize) { auto mailbox = Mailbox::GenerateForSharedImage(); - auto format = viz::ResourceFormat::RGBA_8888; + auto format = get_format(); gfx::Size size(0, 0); auto color_space = gfx::ColorSpace::CreateSRGB(); gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle; @@ -585,7 +603,7 @@ TEST_P(SharedImageBackingFactoryGLTextureTest, EstimatedSize) { auto mailbox = Mailbox::GenerateForSharedImage(); - auto format = viz::ResourceFormat::RGBA_8888; + auto format = get_format(); gfx::Size size(256, 256); auto color_space = gfx::ColorSpace::CreateSRGB(); gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle; @@ -749,7 +767,7 @@ GpuMemoryBufferImportEmpty) { auto mailbox = Mailbox::GenerateForSharedImage(); gfx::Size size(256, 256); - gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888; + gfx::BufferFormat format = viz::BufferFormat(get_format()); auto color_space = gfx::ColorSpace::CreateSRGB(); uint32_t usage = SHARED_IMAGE_USAGE_GLES2; @@ -764,7 +782,7 @@ GpuMemoryBufferImportNative) { auto mailbox = Mailbox::GenerateForSharedImage(); gfx::Size size(256, 256); - gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888; + gfx::BufferFormat format = viz::BufferFormat(get_format()); auto color_space = gfx::ColorSpace::CreateSRGB(); uint32_t usage = SHARED_IMAGE_USAGE_GLES2; @@ -792,7 +810,7 @@ GpuMemoryBufferImportSharedMemory) { auto mailbox = Mailbox::GenerateForSharedImage(); gfx::Size size(256, 256); - gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888; + gfx::BufferFormat format = viz::BufferFormat(get_format()); auto color_space = gfx::ColorSpace::CreateSRGB(); uint32_t usage = SHARED_IMAGE_USAGE_GLES2; @@ -826,7 +844,7 @@ return; auto mailbox = Mailbox::GenerateForSharedImage(); gfx::Size size(256, 256); - gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888; + gfx::BufferFormat format = viz::BufferFormat(get_format()); auto color_space = gfx::ColorSpace::CreateSRGB(); uint32_t usage = SHARED_IMAGE_USAGE_GLES2; @@ -847,7 +865,7 @@ EXPECT_TRUE(representation); EXPECT_TRUE(representation->GetTexture()->service_id()); EXPECT_EQ(size, representation->size()); - EXPECT_EQ(viz::ResourceFormat::RGBA_8888, representation->format()); + EXPECT_EQ(get_format(), representation->format()); EXPECT_EQ(color_space, representation->color_space()); EXPECT_EQ(usage, representation->usage()); @@ -1044,15 +1062,28 @@ EXPECT_FALSE(mailbox_manager_->ConsumeTexture(mailbox_)); } +#if !defined(OS_ANDROID) +const auto kResourceFormats = + ::testing::Values(viz::ResourceFormat::RGBA_8888, + viz::ResourceFormat::BGRA_1010102, + viz::ResourceFormat::RGBA_1010102); +#else +// High bit depth rendering is not supported on Android. +const auto kResourceFormats = ::testing::Values(viz::ResourceFormat::RGBA_8888); +#endif + INSTANTIATE_TEST_SUITE_P(Service, SharedImageBackingFactoryGLTextureTest, - ::testing::Bool()); + ::testing::Combine(::testing::Bool(), + kResourceFormats)); INSTANTIATE_TEST_SUITE_P(Service, SharedImageBackingFactoryGLTextureThreadSafeTest, - ::testing::Bool()); + ::testing::Combine(::testing::Bool(), + kResourceFormats)); INSTANTIATE_TEST_SUITE_P(Service, SharedImageBackingFactoryGLTextureWithGMBTest, - ::testing::Bool()); + ::testing::Combine(::testing::Bool(), + kResourceFormats)); } // anonymous namespace } // namespace gpu
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.cc b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.cc index 203c58c..db815ad 100644 --- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.cc +++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.cc
@@ -5,6 +5,7 @@ #include "ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.h" #include "base/logging.h" +#include "base/metrics/histogram_functions.h" #include "base/sequenced_task_runner.h" #include "base/task/post_task.h" #include "components/keyed_service/ios/browser_state_dependency_manager.h" @@ -25,6 +26,7 @@ : ChromeBrowserState(std::move(io_task_runner)), otr_state_path_(otr_path), original_chrome_browser_state_(original_chrome_browser_state), + start_time_(base::Time::Now()), prefs_(CreateIncognitoBrowserStatePrefs( static_cast<sync_preferences::PrefServiceSyncable*>( original_chrome_browser_state->GetPrefs()))) { @@ -40,6 +42,11 @@ if (pref_proxy_config_tracker_) pref_proxy_config_tracker_->DetachFromPrefService(); + const base::TimeDelta duration = base::Time::Now() - start_time_; + base::UmaHistogramCustomCounts( + "Profile.Incognito.Lifetime", duration.InMinutes(), 1, + base::TimeDelta::FromDays(28).InMinutes(), 100); + // Clears any data the network stack contains that may be related to the // OTR session. GetApplicationContext()->GetIOSChromeIOThread()->ChangedToOnTheRecord();
diff --git a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.h b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.h index 7a04901..cca2aa1 100644 --- a/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.h +++ b/ios/chrome/browser/browser_state/off_the_record_chrome_browser_state_impl.h
@@ -52,6 +52,9 @@ base::FilePath otr_state_path_; ChromeBrowserState* original_chrome_browser_state_; // weak + // Creation time of the off-the-record BrowserState. + const base::Time start_time_; + std::unique_ptr<sync_preferences::PrefServiceSyncable> prefs_; std::unique_ptr<OffTheRecordChromeBrowserStateIOData::Handle> io_data_;
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm index 5d32abf..387fc04 100644 --- a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm +++ b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
@@ -594,7 +594,7 @@ if (identities.count != 0) { newIdentity = identities[0]; } - if (newIdentity != _defaultIdentity) { + if (![_defaultIdentity isEqual:newIdentity]) { [self selectIdentity:newIdentity]; [self sendConsumerNotificationWithIdentityChanged:YES]; }
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_mediator.mm b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_mediator.mm index c89403b..c519da1 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_mediator.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/identity_chooser/identity_chooser_mediator.mm
@@ -42,7 +42,7 @@ } - (void)setSelectedIdentity:(ChromeIdentity*)selectedIdentity { - if (_selectedIdentity == selectedIdentity) + if ([_selectedIdentity isEqual:selectedIdentity]) return; IdentityChooserItem* previousSelectedItem = [self.consumer identityChooserItemWithGaiaID:self.selectedIdentity.gaiaID];
diff --git a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_mediator.mm b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_mediator.mm index df7f6ea..45ba2e98 100644 --- a/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_mediator.mm +++ b/ios/chrome/browser/ui/authentication/unified_consent/unified_consent_mediator.mm
@@ -51,7 +51,7 @@ } - (void)setSelectedIdentity:(ChromeIdentity*)selectedIdentity { - if (selectedIdentity == self.selectedIdentity) { + if ([self.selectedIdentity isEqual:selectedIdentity]) { return; } // nil is allowed only if there is no other identity. @@ -145,7 +145,7 @@ } - (void)profileUpdate:(ChromeIdentity*)identity { - if (identity == self.selectedIdentity) { + if ([self.selectedIdentity isEqual:identity]) { [self updateViewController]; } }
diff --git a/ios/chrome/browser/ui/browser_view/BUILD.gn b/ios/chrome/browser/ui/browser_view/BUILD.gn index 3ac4343..27ef560 100644 --- a/ios/chrome/browser/ui/browser_view/BUILD.gn +++ b/ios/chrome/browser/ui/browser_view/BUILD.gn
@@ -127,6 +127,7 @@ "//ios/chrome/browser/ui/popup_menu", "//ios/chrome/browser/ui/presenters", "//ios/chrome/browser/ui/print", + "//ios/chrome/browser/ui/qr_generator", "//ios/chrome/browser/ui/qr_scanner:coordinator", "//ios/chrome/browser/ui/reading_list", "//ios/chrome/browser/ui/recent_tabs",
diff --git a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm index 2369add..545cdd7 100644 --- a/ios/chrome/browser/ui/browser_view/browser_coordinator.mm +++ b/ios/chrome/browser/ui/browser_view/browser_coordinator.mm
@@ -53,6 +53,7 @@ #import "ios/chrome/browser/ui/page_info/page_info_legacy_coordinator.h" #import "ios/chrome/browser/ui/passwords/password_breach_coordinator.h" #import "ios/chrome/browser/ui/print/print_controller.h" +#import "ios/chrome/browser/ui/qr_generator/qr_generator_coordinator.h" #import "ios/chrome/browser/ui/qr_scanner/qr_scanner_legacy_coordinator.h" #import "ios/chrome/browser/ui/reading_list/reading_list_coordinator.h" #import "ios/chrome/browser/ui/recent_tabs/recent_tabs_coordinator.h" @@ -62,6 +63,7 @@ #import "ios/chrome/browser/ui/toolbar/accessory/toolbar_accessory_coordinator_delegate.h" #import "ios/chrome/browser/ui/toolbar/accessory/toolbar_accessory_presenter.h" #import "ios/chrome/browser/ui/translate/legacy_translate_infobar_coordinator.h" +#include "ios/chrome/browser/ui/ui_feature_flags.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/features.h" @@ -152,6 +154,9 @@ // TODO(crbug.com/910017): Convert to coordinator. @property(nonatomic, strong) PrintController* printController; +// Coordinator for the QR generator UI. +@property(nonatomic, strong) QRGeneratorCoordinator* qrGeneratorCoordinator; + // Coordinator for the QR scanner. @property(nonatomic, strong) QRScannerLegacyCoordinator* qrScannerCoordinator; @@ -268,6 +273,9 @@ [self.readingListCoordinator stop]; self.readingListCoordinator = nil; + [self.qrGeneratorCoordinator stop]; + self.qrGeneratorCoordinator = nil; + [self.passwordBreachCoordinator stop]; [self.pageInfoCoordinator stop]; @@ -374,6 +382,8 @@ browser:self.browser]; [self.qrScannerCoordinator start]; + /* QRGeneratorCoordinator is created and started by a command. */ + /* ReadingListCoordinator is created and started by a BrowserCommand */ /* RecentTabsCoordinator is created and started by a BrowserCommand */ @@ -440,6 +450,9 @@ self.printController = nil; + [self.qrGeneratorCoordinator stop]; + self.qrGeneratorCoordinator = nil; + [self.qrScannerCoordinator stop]; self.qrScannerCoordinator = nil; @@ -718,7 +731,18 @@ #pragma mark - QRGenerationCommands - (void)generateQRCode:(GenerateQRCodeCommand*)command { - // TODO(crbug.com/1064990): Implement Coordinator and starting here. + DCHECK(base::FeatureList::IsEnabled(kQRCodeGeneration)); + self.qrGeneratorCoordinator = [[QRGeneratorCoordinator alloc] + initWithBaseViewController:self.viewController + browser:self.browser + title:command.title + URL:command.URL]; + [self.qrGeneratorCoordinator start]; +} + +- (void)hideQRCode { + [self.qrGeneratorCoordinator stop]; + self.qrGeneratorCoordinator = nil; } #pragma mark - FormInputAccessoryCoordinatorNavigator
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index 85f8d625..3a06d1c 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -934,7 +934,10 @@ webStateList:self.browser->GetWebStateList()]; StartBroadcastingMainContentUI(self, broadcaster); - self.fullscreenController->SetWebStateList(self.browser->GetWebStateList()); + if (!fullscreen::features::ShouldScopeFullscreenControllerToBrowser()) { + self.fullscreenController->SetWebStateList( + self.browser->GetWebStateList()); + } _fullscreenUIUpdater = std::make_unique<FullscreenUIUpdater>(self.fullscreenController, self); @@ -950,7 +953,9 @@ _fullscreenUIUpdater = nullptr; - self.fullscreenController->SetWebStateList(nullptr); + if (!fullscreen::features::ShouldScopeFullscreenControllerToBrowser()) { + self.fullscreenController->SetWebStateList(nullptr); + } } }
diff --git a/ios/chrome/browser/ui/commands/qr_generation_commands.h b/ios/chrome/browser/ui/commands/qr_generation_commands.h index 5d910cf..8a4b2eb 100644 --- a/ios/chrome/browser/ui/commands/qr_generation_commands.h +++ b/ios/chrome/browser/ui/commands/qr_generation_commands.h
@@ -14,6 +14,9 @@ // Generates a QR code based on the |command| properties and displays it. - (void)generateQRCode:(GenerateQRCodeCommand*)command; +// Dismisses the view showing a QR code, if present. +- (void)hideQRCode; + @end #endif // IOS_CHROME_BROWSER_UI_COMMANDS_QR_GENERATION_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/fullscreen/BUILD.gn b/ios/chrome/browser/ui/fullscreen/BUILD.gn index 42e4cf73..dfd9f65 100644 --- a/ios/chrome/browser/ui/fullscreen/BUILD.gn +++ b/ios/chrome/browser/ui/fullscreen/BUILD.gn
@@ -60,6 +60,8 @@ source_set("internal") { sources = [ + "fullscreen_browser_observer.h", + "fullscreen_browser_observer.mm", "fullscreen_content_adjustment_util.h", "fullscreen_content_adjustment_util.mm", "fullscreen_controller_impl.h", @@ -126,6 +128,7 @@ source_set("unit_tests") { testonly = true sources = [ + "fullscreen_browser_observer_unittest.mm", "fullscreen_mediator_unittest.mm", "fullscreen_model_unittest.mm", "fullscreen_ui_updater_unittest.mm", @@ -141,6 +144,7 @@ ":internal", ":ui", "//base/test:test_support", + "//ios/chrome/browser/main:test_support", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/broadcaster", "//ios/chrome/browser/ui/fullscreen/test",
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer.h b/ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer.h new file mode 100644 index 0000000..04c18785 --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer.h
@@ -0,0 +1,31 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_BROWSER_OBSERVER_H_ +#define IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_BROWSER_OBSERVER_H_ + +#include "base/scoped_observer.h" +#import "ios/chrome/browser/main/browser.h" +#import "ios/chrome/browser/main/browser_observer.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.h" + +// A BrowserObserver that observes the BrowserDestroyed callback. +class FullscreenBrowserObserver : public BrowserObserver { + public: + FullscreenBrowserObserver( + FullscreenWebStateListObserver* web_state_list_observer, + Browser* browser); + ~FullscreenBrowserObserver() override; + + private: + // BrowserObserver + void BrowserDestroyed(Browser* browser) override; + + // The FullscreenWebStateListObserver passed on construction. + FullscreenWebStateListObserver* web_state_list_observer_; + // Scoped observer that facilitates observing an BrowserObserver. + ScopedObserver<Browser, BrowserObserver> scoped_observer_; +}; + +#endif // IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_BROWSER_OBSERVER_H_
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer.mm new file mode 100644 index 0000000..d921e24 --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer.mm
@@ -0,0 +1,33 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer.h" + +#import "ios/chrome/browser/main/browser.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +FullscreenBrowserObserver::FullscreenBrowserObserver( + FullscreenWebStateListObserver* web_state_list_observer, + Browser* browser) + : web_state_list_observer_(web_state_list_observer), + scoped_observer_(this) { + DCHECK(web_state_list_observer_); + // TODO(crbug.com/790886): DCHECK |browser| once FullscreenController is fully + // scoped to a Browser. + if (browser) { + web_state_list_observer_->SetWebStateList(browser->GetWebStateList()); + scoped_observer_.Add(browser); + } +} + +FullscreenBrowserObserver::~FullscreenBrowserObserver() = default; + +void FullscreenBrowserObserver::FullscreenBrowserObserver::BrowserDestroyed( + Browser* browser) { + web_state_list_observer_->SetWebStateList(nullptr); + scoped_observer_.Remove(browser); +}
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer_unittest.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer_unittest.mm new file mode 100644 index 0000000..c3e1918 --- /dev/null +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer_unittest.mm
@@ -0,0 +1,50 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer.h" + +#include "base/test/task_environment.h" +#import "ios/chrome/browser/main/test_browser.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" +#import "ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.h" +#import "ios/chrome/browser/ui/fullscreen/test/test_fullscreen_controller.h" +#import "ios/chrome/browser/web_state_list/web_state_list.h" +#include "testing/platform_test.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +// Tests FullscreenBrowserObserver functionality. +class FullscreenBrowserObserverTest : public PlatformTest { + public: + FullscreenBrowserObserverTest() + : browser_(std::make_unique<TestBrowser>()), + controller_(&model_), + mediator_(&controller_, &model_), + web_state_list_observer_(&controller_, &model_, &mediator_), + browser_observer_(&web_state_list_observer_, browser_.get()) { + web_state_list_observer_.SetWebStateList(browser_.get()->GetWebStateList()); + } + + ~FullscreenBrowserObserverTest() override { mediator_.Disconnect(); } + + protected: + base::test::TaskEnvironment task_environment_; + std::unique_ptr<TestBrowser> browser_; + TestFullscreenController controller_; + FullscreenModel model_; + FullscreenMediator mediator_; + FullscreenWebStateListObserver web_state_list_observer_; + FullscreenBrowserObserver browser_observer_; +}; + +// Tests that FullscreenBrowserObserver resets the FullscreenController's +// WebStateList. +TEST_F(FullscreenBrowserObserverTest, BrowserDestroyed) { + EXPECT_TRUE(web_state_list_observer_.GetWebStateList()); + browser_ = nullptr; + EXPECT_FALSE(web_state_list_observer_.GetWebStateList()); +}
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h index aa371c8b..927f233 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.h
@@ -5,18 +5,20 @@ #ifndef IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_IMPL_H_ #define IOS_CHROME_BROWSER_UI_FULLSCREEN_FULLSCREEN_CONTROLLER_IMPL_H_ +#import "ios/chrome/browser/ui/fullscreen/fullscreen_browser_observer.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_controller.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_mediator.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_model.h" #import "ios/chrome/browser/ui/fullscreen/fullscreen_web_state_list_observer.h" +class Browser; @class ChromeBroadcastOberverBridge; @class FullscreenSystemNotificationObserver; // Implementation of FullscreenController. class FullscreenControllerImpl : public FullscreenController { public: - explicit FullscreenControllerImpl(); + explicit FullscreenControllerImpl(Browser* browser); // Not copyable or movable FullscreenControllerImpl(const FullscreenControllerImpl&) = delete; @@ -56,6 +58,9 @@ FullscreenMediator mediator_; // A WebStateListObserver that updates |model_| for WebStateList changes. FullscreenWebStateListObserver web_state_list_observer_; + // A FullscreenBrowserObserver that resets |web_state_list_| when the Browser + // is destroyed. + FullscreenBrowserObserver fullscreen_browser_observer_; // The bridge used to forward brodcasted UI to |model_|. __strong ChromeBroadcastOberverBridge* bridge_ = nil; // A helper object that listens for system notifications.
diff --git a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm index d6542d9..f88f5ab8 100644 --- a/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm +++ b/ios/chrome/browser/ui/fullscreen/fullscreen_controller_impl.mm
@@ -33,8 +33,12 @@ // BrowserUserData when the flag is turned on by default. class FullscreenControllerContainer : public base::SupportsUserData::Data { public: + FullscreenControllerContainer(Browser* browser) + : fullscreen_controller_( + std::make_unique<FullscreenControllerImpl>(browser)) {} FullscreenControllerContainer() - : fullscreen_controller_(std::make_unique<FullscreenControllerImpl>()) {} + : fullscreen_controller_( + std::make_unique<FullscreenControllerImpl>(nullptr)) {} ~FullscreenControllerContainer() override; FullscreenControllerContainer(const FullscreenControllerContainer&) = delete; @@ -84,7 +88,8 @@ static_cast<FullscreenControllerContainer*>( browser->GetUserData(kFullscreenControllerContainerUserDataKey)); if (!fullscreen_controller_container) { - fullscreen_controller_container = new FullscreenControllerContainer; + fullscreen_controller_container = + new FullscreenControllerContainer(browser); browser->SetUserData(kFullscreenControllerContainerUserDataKey, base::WrapUnique(fullscreen_controller_container)); } @@ -109,10 +114,11 @@ ->GetFullscreenController(); } -FullscreenControllerImpl::FullscreenControllerImpl() +FullscreenControllerImpl::FullscreenControllerImpl(Browser* browser) : broadcaster_([[ChromeBroadcaster alloc] init]), mediator_(this, &model_), web_state_list_observer_(this, &model_, &mediator_), + fullscreen_browser_observer_(&web_state_list_observer_, browser), bridge_([[ChromeBroadcastOberverBridge alloc] initWithObserver:&model_]), notification_observer_([[FullscreenSystemNotificationObserver alloc] initWithController:this
diff --git a/ios/chrome/browser/ui/main/scene_controller.mm b/ios/chrome/browser/ui/main/scene_controller.mm index 42f98bc..36bfb06e 100644 --- a/ios/chrome/browser/ui/main/scene_controller.mm +++ b/ios/chrome/browser/ui/main/scene_controller.mm
@@ -320,8 +320,6 @@ startupInformation:self.mainController appState:self.mainController.appState]; - [self scheduleShowPromo]; - // Before bringing up the UI, make sure the launch mode is correct, and // check for previous crashes. BOOL startInIncognito = @@ -416,6 +414,8 @@ [self showFirstRunUI]; // Do not ever show the 'restore' infobar during first run. self.mainController.restoreHelper = nil; + } else { + [self scheduleShowPromo]; } } @@ -453,6 +453,7 @@ // Initializes the first run UI and presents it to the user. - (void)showFirstRunUI { + DCHECK(!self.signinCoordinator); // Register for the first run dismissal notification to reset // |sceneState.presentingFirstRunUI| flag; [[NSNotificationCenter defaultCenter]
diff --git a/ios/chrome/browser/ui/qr_generator/BUILD.gn b/ios/chrome/browser/ui/qr_generator/BUILD.gn new file mode 100644 index 0000000..b43a487 --- /dev/null +++ b/ios/chrome/browser/ui/qr_generator/BUILD.gn
@@ -0,0 +1,53 @@ +# Copyright 2020 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +source_set("ui") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "qr_generator_view_controller.h", + "qr_generator_view_controller.mm", + ] + deps = [ + "//base", + "//ios/chrome/browser/ui/commands", + "//ios/chrome/common/ui/colors", + "//ui/base", + "//url:url", + ] + libs = [ "UIKit.framework" ] +} + +source_set("qr_generator") { + configs += [ "//build/config/compiler:enable_arc" ] + sources = [ + "qr_generator_coordinator.h", + "qr_generator_coordinator.mm", + ] + deps = [ + ":ui", + "//base", + "//ios/chrome/browser/main:public", + "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/coordinators:chrome_coordinators", + ] +} + +source_set("unit_tests") { + configs += [ "//build/config/compiler:enable_arc" ] + testonly = true + sources = [ "qr_generator_view_controller_unittest.mm" ] + deps = [ + ":ui", + "//base", + "//base/test:test_support", + "//ios/chrome/browser/ui/commands", + "//ios/chrome/common/ui/colors", + "//ios/chrome/test/fakes", + "//ios/web", + "//ios/web/public/test", + "//testing/gtest", + "//third_party/ocmock", + "//ui/base", + ] +}
diff --git a/ios/chrome/browser/ui/qr_generator/qr_generator_coordinator.h b/ios/chrome/browser/ui/qr_generator/qr_generator_coordinator.h new file mode 100644 index 0000000..7130b58 --- /dev/null +++ b/ios/chrome/browser/ui/qr_generator/qr_generator_coordinator.h
@@ -0,0 +1,34 @@ +// 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_QR_GENERATOR_QR_GENERATOR_COORDINATOR_H_ +#define IOS_CHROME_BROWSER_UI_QR_GENERATOR_QR_GENERATOR_COORDINATOR_H_ + +#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h" +#include "url/gurl.h" + +// QRGeneratorCoordinator presents the public interface for the QR code +// generation feature. +@interface QRGeneratorCoordinator : ChromeCoordinator + +// Initializes an instance with a base |viewController|, the current |browser|, +// the |title| and |URL| of a webpage to generate a QR code for. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser + title:(NSString*)title + URL:(const GURL&)URL + NS_DESIGNATED_INITIALIZER; + +// Unavailable, use -initWithBaseViewController:browser:title:URL:. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browserState:(ChromeBrowserState*)browserState + NS_UNAVAILABLE; + +// Unavailable, use -initWithBaseViewController:browser:title:URL:. +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser NS_UNAVAILABLE; + +@end + +#endif // IOS_CHROME_BROWSER_UI_QR_GENERATOR_QR_GENERATOR_COORDINATOR_H_
diff --git a/ios/chrome/browser/ui/qr_generator/qr_generator_coordinator.mm b/ios/chrome/browser/ui/qr_generator/qr_generator_coordinator.mm new file mode 100644 index 0000000..1788e47 --- /dev/null +++ b/ios/chrome/browser/ui/qr_generator/qr_generator_coordinator.mm
@@ -0,0 +1,82 @@ + +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/qr_generator/qr_generator_coordinator.h" + +#include "ios/chrome/browser/main/browser.h" +#import "ios/chrome/browser/ui/commands/command_dispatcher.h" +#import "ios/chrome/browser/ui/commands/qr_generation_commands.h" +#import "ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +@interface QRGeneratorCoordinator () { + // URL of a page to generate a QR code for. + GURL _URL; +} + +// To be used to dispatch commands to the browser. +@property(nonatomic, strong) CommandDispatcher* dispatcher; + +// Main view controller which will be the parent, or ancestor, of other +// view controllers related to this feature. +@property(nonatomic, strong) UINavigationController* viewController; + +// View controller used to display the QR code and actions. +@property(nonatomic, strong) + QRGeneratorViewController* qrGeneratorViewController; + +// Title of a page to generate a QR code for. +@property(nonatomic, copy) NSString* title; + +@end + +@implementation QRGeneratorCoordinator + +- (instancetype)initWithBaseViewController:(UIViewController*)viewController + browser:(Browser*)browser + title:(NSString*)title + URL:(const GURL&)URL { + if (self = [super initWithBaseViewController:viewController + browser:browser]) { + _title = title; + _URL = URL; + } + return self; +} + +#pragma mark - Chrome Coordinator + +- (void)start { + self.dispatcher = self.browser->GetCommandDispatcher(); + + self.qrGeneratorViewController = [[QRGeneratorViewController alloc] init]; + self.qrGeneratorViewController.handler = + HandlerForProtocol(self.dispatcher, QRGenerationCommands); + + self.viewController = [[UINavigationController alloc] + initWithRootViewController:self.qrGeneratorViewController]; + [self.viewController setModalPresentationStyle:UIModalPresentationFormSheet]; + + [self.baseViewController presentViewController:self.viewController + animated:YES + completion:nil]; + [super start]; +} + +- (void)stop { + [self.viewController.presentingViewController + dismissViewControllerAnimated:YES + completion:nil]; + + self.qrGeneratorViewController = nil; + self.viewController = nil; + + [super stop]; +} + +@end
diff --git a/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.h b/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.h new file mode 100644 index 0000000..0039158 --- /dev/null +++ b/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.h
@@ -0,0 +1,20 @@ +// 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_QR_GENERATOR_QR_GENERATOR_VIEW_CONTROLLER_H_ +#define IOS_CHROME_BROWSER_UI_QR_GENERATOR_QR_GENERATOR_VIEW_CONTROLLER_H_ + +#import "ios/chrome/browser/ui/commands/qr_generation_commands.h" + +#import <UIKit/UIKit.h> + +// View controller that displays a QR code representing a given website. +@interface QRGeneratorViewController : UIViewController + +// Command handler for communicating with other components of the app. +@property(nonatomic, weak) id<QRGenerationCommands> handler; + +@end + +#endif // IOS_CHROME_BROWSER_UI_QR_GENERATOR_QR_GENERATOR_VIEW_CONTROLLER_H_
diff --git a/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.mm b/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.mm new file mode 100644 index 0000000..e3a0a04 --- /dev/null +++ b/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.mm
@@ -0,0 +1,49 @@ + +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.h" + +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +NSString* const kQRGeneratorDoneButtonId = @"kQRGeneratorDoneButtonId"; + +@implementation QRGeneratorViewController + +#pragma mark - UIViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + + [self setUpNavigation]; +} + +#pragma mark - Private Methods + +- (void)setUpNavigation { + // Set shadowImage to an empty image to remove the separator between the + // navigation bar and the main content. + self.navigationController.navigationBar.shadowImage = [[UIImage alloc] init]; + + // Set background color. + [self.navigationController.navigationBar setTranslucent:NO]; + [self.navigationController.navigationBar + setBarTintColor:UIColor.cr_systemBackgroundColor]; + [self.navigationController.view + setBackgroundColor:UIColor.cr_systemBackgroundColor]; + + // Add a Done button to the navigation bar. + UIBarButtonItem* doneButton = [[UIBarButtonItem alloc] + initWithBarButtonSystemItem:UIBarButtonSystemItemDone + target:self.handler + action:@selector(hideQRCode)]; + doneButton.accessibilityIdentifier = kQRGeneratorDoneButtonId; + self.navigationItem.rightBarButtonItem = doneButton; +} + +@end
diff --git a/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller_unittest.mm b/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller_unittest.mm new file mode 100644 index 0000000..7157979 --- /dev/null +++ b/ios/chrome/browser/ui/qr_generator/qr_generator_view_controller_unittest.mm
@@ -0,0 +1,63 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#import "ios/chrome/browser/ui/qr_generator/qr_generator_view_controller.h" + +#import "ios/chrome/browser/ui/commands/qr_generation_commands.h" +#import "ios/chrome/common/ui/colors/UIColor+cr_semantic_colors.h" +#include "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" +#include "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +class QRGeneratorViewControllerTest : public PlatformTest { + public: + QRGeneratorViewControllerTest() + : view_controller_([[QRGeneratorViewController alloc] init]) {} + + protected: + QRGeneratorViewController* view_controller_; + + private: + DISALLOW_COPY_AND_ASSIGN(QRGeneratorViewControllerTest); +}; + +// Tests that a Done button gets added to the navigation bar, and its action +// dispatches the right command. +TEST_F(QRGeneratorViewControllerTest, DoneButton_DispatchesCommand) { + // Set-up mocked handler. + id mockedHandler = OCMStrictProtocolMock(@protocol(QRGenerationCommands)); + [[mockedHandler expect] hideQRCode]; + [view_controller_ setHandler:mockedHandler]; + + // Set-up mocked navigation item. + __block UIBarButtonItem* capturedButton; + id navItemMock = OCMStrictClassMock([UINavigationItem class]); + [[navItemMock expect] + setRightBarButtonItem:[OCMArg + checkWithBlock:^BOOL(UIBarButtonItem* button) { + capturedButton = button; + return !!capturedButton; + }]]; + + id vcPartialMock = OCMPartialMock(view_controller_); + OCMStub([vcPartialMock navigationItem]).andReturn(navItemMock); + + [view_controller_ viewDidLoad]; + + // Button should've been given to the navigationItem. + [navItemMock verify]; + + // Simulate a click on the button. + [[UIApplication sharedApplication] sendAction:capturedButton.action + to:capturedButton.target + from:nil + forEvent:nil]; + + // Callback should've gotten invoked. + [mockedHandler verify]; +}
diff --git a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm index b39f97e..b5798f4 100644 --- a/ios/chrome/browser/ui/settings/settings_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/settings_table_view_controller.mm
@@ -1168,7 +1168,7 @@ #pragma mark ChromeIdentityServiceObserver - (void)profileUpdate:(ChromeIdentity*)identity { - if (identity == _identity) { + if ([_identity isEqual:identity]) { [self reloadAccountCell]; } }
diff --git a/ios/chrome/browser/ui/tab_grid/transitions/tab_grid_transition_handler.mm b/ios/chrome/browser/ui/tab_grid/transitions/tab_grid_transition_handler.mm index df06e66e..dc2c68c 100644 --- a/ios/chrome/browser/ui/tab_grid/transitions/tab_grid_transition_handler.mm +++ b/ios/chrome/browser/ui/tab_grid/transitions/tab_grid_transition_handler.mm
@@ -100,6 +100,8 @@ browser.view.frame = tabGrid.view.bounds; [tabGrid.view addSubview:browser.view]; + browser.view.accessibilityViewIsModal = YES; + browser.view.alpha = 0; if (UIAccessibilityIsReduceMotionEnabled() ||
diff --git a/ios/chrome/credential_provider_extension/BUILD.gn b/ios/chrome/credential_provider_extension/BUILD.gn index 760e0fa8..63f4986b 100644 --- a/ios/chrome/credential_provider_extension/BUILD.gn +++ b/ios/chrome/credential_provider_extension/BUILD.gn
@@ -53,6 +53,7 @@ "//base", "//ios/chrome/common/app_group", "//ios/chrome/common/app_group:command", + "//ios/chrome/common/credential_provider", "//ios/chrome/common/ui/colors", "//ios/chrome/common/ui/reauthentication", "//ios/chrome/credential_provider_extension/resources",
diff --git a/ios/chrome/credential_provider_extension/credential_provider_view_controller.mm b/ios/chrome/credential_provider_extension/credential_provider_view_controller.mm index e2abcd2..174b7a0 100644 --- a/ios/chrome/credential_provider_extension/credential_provider_view_controller.mm +++ b/ios/chrome/credential_provider_extension/credential_provider_view_controller.mm
@@ -4,6 +4,8 @@ #import "ios/chrome/credential_provider_extension/credential_provider_view_controller.h" +#import "ios/chrome/common/credential_provider/archivable_credential_store.h" +#import "ios/chrome/common/credential_provider/constants.h" #import "ios/chrome/common/ui/reauthentication/reauthentication_module.h" #import "ios/chrome/credential_provider_extension/reauthentication_handler.h" #import "ios/chrome/credential_provider_extension/ui/credential_list_coordinator.h" @@ -14,6 +16,9 @@ @interface CredentialProviderViewController () <SuccessfulReauthTimeAccessor> +// Interface for the persistent credential store. +@property(nonatomic, strong) id<CredentialStore> credentialStore; + // List coordinator that shows the list of passwords when started. @property(nonatomic, strong) CredentialListCoordinator* listCoordinator; @@ -38,6 +43,7 @@ if (result != ReauthenticationResult::kFailure) { self.listCoordinator = [[CredentialListCoordinator alloc] initWithBaseViewController:self + credentialStore:self.credentialStore context:self.extensionContext serviceIdentifiers:serviceIdentifiers]; [self.listCoordinator start]; @@ -55,6 +61,14 @@ #pragma mark - Properties +- (id<CredentialStore>)credentialStore { + if (!_credentialStore) { + _credentialStore = [[ArchivableCredentialStore alloc] + initWithFileURL:CredentialProviderSharedArchivableStoreURL()]; + } + return _credentialStore; +} + - (ReauthenticationHandler*)reauthenticationHandler { if (!_reauthenticationHandler) { _reauthenticationHandler = [[ReauthenticationHandler alloc]
diff --git a/ios/chrome/credential_provider_extension/ui/credential_list_coordinator.h b/ios/chrome/credential_provider_extension/ui/credential_list_coordinator.h index b8a9c3d..94a633fc 100644 --- a/ios/chrome/credential_provider_extension/ui/credential_list_coordinator.h +++ b/ios/chrome/credential_provider_extension/ui/credential_list_coordinator.h
@@ -10,6 +10,7 @@ @class ASCredentialServiceIdentifier; @class ASCredentialProviderExtensionContext; @class UIViewController; +@protocol CredentialStore; // This feature presents a list of credentials for the user to choose. @interface CredentialListCoordinator : NSObject @@ -19,6 +20,7 @@ // can be nil. - (instancetype) initWithBaseViewController:(UIViewController*)baseViewController + credentialStore:(id<CredentialStore>)credentialStore context:(ASCredentialProviderExtensionContext*)context serviceIdentifiers: (NSArray<ASCredentialServiceIdentifier*>*)serviceIdentifiers
diff --git a/ios/chrome/credential_provider_extension/ui/credential_list_coordinator.mm b/ios/chrome/credential_provider_extension/ui/credential_list_coordinator.mm index 13521c4..5466dbc 100644 --- a/ios/chrome/credential_provider_extension/ui/credential_list_coordinator.mm +++ b/ios/chrome/credential_provider_extension/ui/credential_list_coordinator.mm
@@ -29,6 +29,9 @@ // The mediator of this coordinator. @property(nonatomic, strong) CredentialListMediator* mediator; +// Interface for the persistent credential store. +@property(nonatomic, weak) id<CredentialStore> credentialStore; + // The extension context in which the credential list was started. @property(nonatomic, weak) ASCredentialProviderExtensionContext* context; @@ -42,6 +45,7 @@ - (instancetype) initWithBaseViewController:(UIViewController*)baseViewController + credentialStore:(id<CredentialStore>)credentialStore context:(ASCredentialProviderExtensionContext*)context serviceIdentifiers: (NSArray<ASCredentialServiceIdentifier*>*)serviceIdentifiers { @@ -50,6 +54,7 @@ _baseViewController = baseViewController; _context = context; _serviceIdentifiers = serviceIdentifiers; + _credentialStore = credentialStore; } return self; } @@ -60,6 +65,7 @@ self.mediator = [[CredentialListMediator alloc] initWithConsumer:credentialListViewController UIHandler:self + credentialStore:self.credentialStore context:self.context serviceIdentifiers:self.serviceIdentifiers];
diff --git a/ios/chrome/credential_provider_extension/ui/credential_list_mediator.h b/ios/chrome/credential_provider_extension/ui/credential_list_mediator.h index e8a229b..75d2fb0 100644 --- a/ios/chrome/credential_provider_extension/ui/credential_list_mediator.h +++ b/ios/chrome/credential_provider_extension/ui/credential_list_mediator.h
@@ -11,6 +11,7 @@ @class ASCredentialProviderExtensionContext; @protocol CredentialListConsumer; @protocol CredentialListUIHandler; +@protocol CredentialStore; // This mediator fetches and organizes the credentials for its consumer. @interface CredentialListMediator : NSObject @@ -18,6 +19,7 @@ // |serviceIdentifiers| will be used to prioritize data, can be nil. - (instancetype)initWithConsumer:(id<CredentialListConsumer>)consumer UIHandler:(id<CredentialListUIHandler>)UIHandler + credentialStore:(id<CredentialStore>)credentialStore context:(ASCredentialProviderExtensionContext*)context serviceIdentifiers: (NSArray<ASCredentialServiceIdentifier*>*)serviceIdentifiers
diff --git a/ios/chrome/credential_provider_extension/ui/credential_list_mediator.mm b/ios/chrome/credential_provider_extension/ui/credential_list_mediator.mm index f51eccff..5fb7d0f7 100644 --- a/ios/chrome/credential_provider_extension/ui/credential_list_mediator.mm +++ b/ios/chrome/credential_provider_extension/ui/credential_list_mediator.mm
@@ -6,6 +6,7 @@ #import <AuthenticationServices/AuthenticationServices.h> +#import "ios/chrome/common/credential_provider/credential_store.h" #import "ios/chrome/credential_provider_extension/ui/credential_list_consumer.h" #import "ios/chrome/credential_provider_extension/ui/credential_list_ui_handler.h" @@ -21,6 +22,9 @@ // The consumer for this mediator. @property(nonatomic, weak) id<CredentialListConsumer> consumer; +// Interface for the persistent credential store. +@property(nonatomic, weak) id<CredentialStore> credentialStore; + // The service identifiers to be prioritized. @property(nonatomic, strong) NSArray<ASCredentialServiceIdentifier*>* serviceIdentifiers; @@ -34,6 +38,7 @@ - (instancetype)initWithConsumer:(id<CredentialListConsumer>)consumer UIHandler:(id<CredentialListUIHandler>)UIHandler + credentialStore:(id<CredentialStore>)credentialStore context:(ASCredentialProviderExtensionContext*)context serviceIdentifiers: (NSArray<ASCredentialServiceIdentifier*>*)serviceIdentifiers { @@ -43,15 +48,20 @@ _UIHandler = UIHandler; _consumer = consumer; _consumer.delegate = self; + _credentialStore = credentialStore; _context = context; } return self; } - (void)fetchCredentials { - // TODO(crbug.com/1045454): Implement this method. For now present the empty - // credentials screen all the time. - [self.UIHandler showEmptyCredentials]; + // TODO(crbug.com/1045454): Implement ordering and suggestions. + NSArray<id<Credential>>* allCredentials = self.credentialStore.credentials; + if (!allCredentials.count) { + [self.UIHandler showEmptyCredentials]; + return; + } + [self.consumer presentSuggestedPasswords:nil allPasswords:allCredentials]; } #pragma mark - CredentialListConsumerDelegate
diff --git a/ios/chrome/test/BUILD.gn b/ios/chrome/test/BUILD.gn index 073e605..8b7662f4 100644 --- a/ios/chrome/test/BUILD.gn +++ b/ios/chrome/test/BUILD.gn
@@ -282,6 +282,7 @@ "//ios/chrome/browser/ui/overlays/web_content_area/java_script_dialogs:unit_tests", "//ios/chrome/browser/ui/popup_menu:unit_tests", "//ios/chrome/browser/ui/presenters:unit_tests", + "//ios/chrome/browser/ui/qr_generator:unit_tests", "//ios/chrome/browser/ui/reading_list:unit_tests", "//ios/chrome/browser/ui/recent_tabs:unit_tests", "//ios/chrome/browser/ui/sad_tab:unit_tests",
diff --git a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc index ce765c85..efe9f60 100644 --- a/media/gpu/ipc/service/gpu_video_decode_accelerator.cc +++ b/media/gpu/ipc/service/gpu_video_decode_accelerator.cc
@@ -466,42 +466,45 @@ return; } - gpu::gles2::TextureRef* texture_ref = - texture_manager->GetTexture(buffer_texture_ids[j]); - if (texture_ref) { - gpu::gles2::Texture* info = texture_ref->texture(); - if (texture_target_ == GL_TEXTURE_EXTERNAL_OES || - texture_target_ == GL_TEXTURE_RECTANGLE_ARB) { - // These textures have their dimensions defined by the underlying - // storage. - // Use |texture_dimensions_| for this size. - texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, - GL_RGBA, texture_dimensions_.width(), - texture_dimensions_.height(), 1, 0, - GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); - } else { - // For other targets, texture dimensions should already be defined. - GLsizei width = 0, height = 0; - info->GetLevelSize(texture_target_, 0, &width, &height, nullptr); - if (width != texture_dimensions_.width() || - height != texture_dimensions_.height()) { - DLOG(ERROR) << "Size mismatch for texture id " - << buffer_texture_ids[j]; - NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT); - return; - } + if (texture_manager) { + gpu::gles2::TextureRef* texture_ref = + texture_manager->GetTexture(buffer_texture_ids[j]); + if (texture_ref) { + gpu::gles2::Texture* info = texture_ref->texture(); + if (texture_target_ == GL_TEXTURE_EXTERNAL_OES || + texture_target_ == GL_TEXTURE_RECTANGLE_ARB) { + // These textures have their dimensions defined by the underlying + // storage. + // Use |texture_dimensions_| for this size. + texture_manager->SetLevelInfo( + texture_ref, texture_target_, 0, GL_RGBA, + texture_dimensions_.width(), texture_dimensions_.height(), 1, 0, + GL_RGBA, GL_UNSIGNED_BYTE, gfx::Rect()); + } else { + // For other targets, texture dimensions should already be defined. + GLsizei width = 0, height = 0; + info->GetLevelSize(texture_target_, 0, &width, &height, nullptr); + if (width != texture_dimensions_.width() || + height != texture_dimensions_.height()) { + DLOG(ERROR) << "Size mismatch for texture id " + << buffer_texture_ids[j]; + NotifyError(VideoDecodeAccelerator::INVALID_ARGUMENT); + return; + } - // TODO(dshwang): after moving to D3D11, remove this. - // https://crbug.com/438691 - GLenum format = video_decode_accelerator_->GetSurfaceInternalFormat(); - if (format != GL_RGBA) { - DCHECK(format == GL_BGRA_EXT); - texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, - format, width, height, 1, 0, format, - GL_UNSIGNED_BYTE, gfx::Rect()); + // TODO(dshwang): after moving to D3D11, remove this. + // https://crbug.com/438691 + GLenum format = + video_decode_accelerator_->GetSurfaceInternalFormat(); + if (format != GL_RGBA) { + DCHECK(format == GL_BGRA_EXT); + texture_manager->SetLevelInfo(texture_ref, texture_target_, 0, + format, width, height, 1, 0, format, + GL_UNSIGNED_BYTE, gfx::Rect()); + } } + current_textures.push_back(texture_ref); } - current_textures.push_back(texture_ref); } service_ids.push_back(texture_base->service_id()); }
diff --git a/net/quic/mock_crypto_client_stream.cc b/net/quic/mock_crypto_client_stream.cc index 2eba680..93e9706 100644 --- a/net/quic/mock_crypto_client_stream.cc +++ b/net/quic/mock_crypto_client_stream.cc
@@ -182,7 +182,7 @@ std::make_unique<NullDecrypter>(Perspective::IS_CLIENT)); } session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, nullptr); - session()->connection()->SetEncrypter( + session()->OnNewEncryptionKeyAvailable( ENCRYPTION_FORWARD_SECURE, std::make_unique<NullEncrypter>(Perspective::IS_CLIENT)); } @@ -264,7 +264,7 @@ std::make_unique<NullDecrypter>(Perspective::IS_CLIENT)); } session()->connection()->SetEncrypter(ENCRYPTION_INITIAL, nullptr); - session()->connection()->SetEncrypter( + session()->OnNewEncryptionKeyAvailable( ENCRYPTION_FORWARD_SECURE, std::make_unique<NullEncrypter>(Perspective::IS_CLIENT)); }
diff --git a/net/quic/quic_chromium_client_session_test.cc b/net/quic/quic_chromium_client_session_test.cc index 71e76fc..81bdb37 100644 --- a/net/quic/quic_chromium_client_session_test.cc +++ b/net/quic/quic_chromium_client_session_test.cc
@@ -1900,7 +1900,8 @@ } TEST_P(QuicChromiumClientSessionTest, DetectPathDegradingDuringHandshake) { - if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) { + if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 || + GetQuicReloadableFlag(quic_use_blackhole_detector)) { // TODO(nharper, b/112643533): Figure out why this test fails when TLS is // enabled and fix it. return;
diff --git a/net/quic/quic_flags_list.h b/net/quic/quic_flags_list.h index a30f23e..8ef66a8e 100644 --- a/net/quic/quic_flags_list.h +++ b/net/quic/quic_flags_list.h
@@ -380,11 +380,11 @@ // keys are available). QUIC_FLAG(bool, FLAGS_quic_restart_flag_quic_send_settings_on_write_key_available, - false) + true) // If true, use blackhole detector in QuicConnection to detect path degrading // and network blackhole. -QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_blackhole_detector, false) +QUIC_FLAG(bool, FLAGS_quic_reloadable_flag_quic_use_blackhole_detector, true) // If true, use idle network detector to detect handshake timeout and idle // network timeout.
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 75204a8c..1cb6fa2 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -3307,8 +3307,10 @@ // Verify that if a QUIC connection RTOs, the QuicHttpStream will // return QUIC_PROTOCOL_ERROR. TEST_P(QuicNetworkTransactionTest, TooManyRtosAfterHandshakeConfirmed) { - if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) { + if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 || + GetQuicReloadableFlag(quic_use_blackhole_detector)) { // QUIC with TLS1.3 handshake doesn't support 0-rtt. + // TODO(fayang): Add time driven TOO_MANY_RTOS test. return; } @@ -3436,8 +3438,10 @@ // QUIC will not be marked as broken. TEST_P(QuicNetworkTransactionTest, TooManyRtosAfterHandshakeConfirmedAndStreamReset) { - if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3) { + if (version_.handshake_protocol == quic::PROTOCOL_TLS1_3 || + GetQuicReloadableFlag(quic_use_blackhole_detector)) { // QUIC with TLS1.3 handshake doesn't support 0-rtt. + // TODO(fayang): Add time driven TOO_MANY_RTOS test. return; }
diff --git a/services/network/network_context.cc b/services/network/network_context.cc index 3422b14..65fcd744 100644 --- a/services/network/network_context.cc +++ b/services/network/network_context.cc
@@ -97,8 +97,10 @@ #include "services/network/throttling/network_conditions.h" #include "services/network/throttling/throttling_controller.h" #include "services/network/throttling/throttling_network_transaction_factory.h" +#include "services/network/trust_tokens/has_trust_tokens_answerer.h" #include "services/network/trust_tokens/pending_trust_token_store.h" #include "services/network/trust_tokens/sqlite_trust_token_persister.h" +#include "services/network/trust_tokens/suitable_trust_token_origin.h" #include "services/network/trust_tokens/trust_token_parameterization.h" #include "services/network/trust_tokens/trust_token_store.h" #include "services/network/url_loader.h" @@ -572,6 +574,25 @@ std::move(receiver)); } +void NetworkContext::GetHasTrustTokensAnswerer( + mojo::PendingReceiver<mojom::HasTrustTokensAnswerer> receiver, + const url::Origin& top_frame_origin) { + // Only called when Trust Tokens is enabled, i.e. trust_token_store_ is + // non-null. + DCHECK(trust_token_store_); + + base::Optional<SuitableTrustTokenOrigin> suitable_top_frame_origin = + SuitableTrustTokenOrigin::Create(top_frame_origin); + + // It's safe to dereference |suitable_top_frame_origin| here as, during the + // process of vending the HasTrustTokensAnswerer, the browser ensures that + // the requesting context's top frame origin is suitable for Trust Tokens. + auto answerer = std::make_unique<HasTrustTokensAnswerer>( + std::move(*suitable_top_frame_origin), trust_token_store_.get()); + + has_trust_tokens_answerers_.Add(std::move(answerer), std::move(receiver)); +} + void NetworkContext::OnProxyLookupComplete( ProxyLookupRequest* proxy_lookup_request) { auto it = proxy_lookup_requests_.find(proxy_lookup_request);
diff --git a/services/network/network_context.h b/services/network/network_context.h index b529d0d4..1c1446d 100644 --- a/services/network/network_context.h +++ b/services/network/network_context.h
@@ -195,6 +195,9 @@ bool is_service_worker, int32_t process_id, int32_t routing_id) override; + void GetHasTrustTokensAnswerer( + mojo::PendingReceiver<mojom::HasTrustTokensAnswerer> receiver, + const url::Origin& top_frame_origin) override; void ClearNetworkingHistorySince( base::Time time, base::OnceClosure completion_callback) override; @@ -577,6 +580,12 @@ // See the comment for |trust_token_store()|. std::unique_ptr<PendingTrustTokenStore> trust_token_store_; + // Ordering: this must be after |trust_token_store_| since the + // HasTrustTokensAnswerers are provided non-owning pointers to + // |trust_token_store_|. + mojo::UniqueReceiverSet<mojom::HasTrustTokensAnswerer> + has_trust_tokens_answerers_; + #if !defined(OS_IOS) std::unique_ptr<WebSocketFactory> websocket_factory_; #endif // !defined(OS_IOS)
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom index 797d8c6..02675e0c 100644 --- a/services/network/public/mojom/network_context.mojom +++ b/services/network/public/mojom/network_context.mojom
@@ -39,6 +39,7 @@ import "services/network/public/mojom/site_for_cookies.mojom"; import "services/network/public/mojom/ssl_config.mojom"; import "services/network/public/mojom/tcp_socket.mojom"; +import "services/network/public/mojom/trust_tokens.mojom"; import "services/network/public/mojom/udp_socket.mojom"; import "services/network/public/mojom/url_loader.mojom"; import "services/network/public/mojom/url_loader_factory.mojom"; @@ -864,6 +865,24 @@ bool is_service_worker, int32 process_id, int32 routing_id); + // Provides a HasTrustTokensAnswerer scoped to the given top-frame origin + // (subsequent calls to its HasTrustTokens(issuer) method will attempt to + // associate |issuer| with |top_frame_origin|, in the sense of + // TrustTokenStore::SetAssociation, and reject if |top_frame_origin| is + // already at its number-of-associated-issuers limit). + // + // The caller must ensure (enforced by ReportBadMessage) that + // |top_frame_origin| is both + // (1) potentially trustworthy and + // (2) either HTTP or HTTPS. + // + // The first is a general security requirement; the second is in order to + // ensure that the origin has a unique serialization (and, consequently, is + // suitable for keying persistent Trust Tokens state). + GetHasTrustTokensAnswerer( + pending_receiver<HasTrustTokensAnswerer> has_trust_tokens_answerer, + url.mojom.Origin top_frame_origin); + // Clears network objects with implicit URL history information. Data related // to events that happened prior to |start_time| may be retained. Only applies // to network objects without more specific methods (Cookies,
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h index 7d09d1b..51593e2 100644 --- a/services/network/test/test_network_context.h +++ b/services/network/test/test_network_context.h
@@ -59,6 +59,9 @@ bool is_service_worker, int32_t process_id, int32_t routing_id) override {} + void GetHasTrustTokensAnswerer( + mojo::PendingReceiver<mojom::HasTrustTokensAnswerer> receiver, + const url::Origin& top_frame_origin) override {} void ClearNetworkingHistorySince( base::Time start_time, ClearNetworkingHistorySinceCallback callback) override {}
diff --git a/testing/buildbot/filters/android.emulator.content_browsertests.filter b/testing/buildbot/filters/android.emulator.content_browsertests.filter index c2f3b49..1f5b340 100644 --- a/testing/buildbot/filters/android.emulator.content_browsertests.filter +++ b/testing/buildbot/filters/android.emulator.content_browsertests.filter
@@ -1,8 +1,8 @@ # crbug.com/1054829 --All/TouchActionBrowserTest.PanXAtYAreaWithTimeout/* --All/TouchActionBrowserTest.TouchActionNone/* --All/TouchActionBrowserTest.TwoFingerPanXAtYAreaWithTimeout/* --All/TouchActionBrowserTest.BlockDoubleTapDragZoom/* +-All/TouchActionBrowserTest.PanXAtYAreaWithTimeout +-All/TouchActionBrowserTest.TouchActionNone +-All/TouchActionBrowserTest.TwoFingerPanXAtYAreaWithTimeout +-All/TouchActionBrowserTest.BlockDoubleTapDragZoom # crbug.com/1056878 -BackForwardCacheBrowserTest.VideoSuspendAndResume
diff --git a/testing/test.gni b/testing/test.gni index eda4330..d2b54c2 100644 --- a/testing/test.gni +++ b/testing/test.gni
@@ -217,7 +217,7 @@ package = ":$_pkg_target" package_name_override = _output_name - deps = [ "//testing/buildbot/filters:fuchsia_filters" ] + data_deps = [ "//testing/buildbot/filters:fuchsia_filters" ] } cr_fuchsia_package(_pkg_target) {
diff --git a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc index 771b0b1..0363733f 100644 --- a/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc +++ b/third_party/blink/common/scheduler/web_scheduler_tracked_feature.cc
@@ -91,8 +91,6 @@ return "WebFileSystem"; case WebSchedulerTrackedFeature::kAppBanner: return "AppBanner"; - case WebSchedulerTrackedFeature::kPrinting: - return "Printing"; } }
diff --git a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h index a71ad8cb..736fd04 100644 --- a/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h +++ b/third_party/blink/public/common/scheduler/web_scheduler_tracked_feature.h
@@ -85,10 +85,9 @@ kOutstandingNetworkRequestXHR = 41, kAppBanner = 42, - kPrinting = 43, // NB: This enum is used in a bitmask, so kMaxValue must be less than 64. - kMaxValue = kPrinting + kMaxValue = kAppBanner }; static_assert(static_cast<uint32_t>(WebSchedulerTrackedFeature::kMaxValue) < 64,
diff --git a/third_party/blink/public/mojom/appcache/appcache.mojom b/third_party/blink/public/mojom/appcache/appcache.mojom index f3ea903..39d2707 100644 --- a/third_party/blink/public/mojom/appcache/appcache.mojom +++ b/third_party/blink/public/mojom/appcache/appcache.mojom
@@ -49,7 +49,6 @@ bool is_foreign; bool is_explicit; int64 response_id; - mojo_base.mojom.Time token_expires; }; struct AppCacheErrorDetails {
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 a416dc5..764f8fe 100644 --- a/third_party/blink/public/mojom/web_feature/web_feature.mojom +++ b/third_party/blink/public/mojom/web_feature/web_feature.mojom
@@ -2539,6 +2539,7 @@ // The above items are available in M83 branch. kWrongBaselineOfButtonElement = 3201, + kV8Document_HasTrustToken_Method = 3202, // 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_view.h b/third_party/blink/public/web/web_view.h index 406c19b..02dd65e 100644 --- a/third_party/blink/public/web/web_view.h +++ b/third_party/blink/public/web/web_view.h
@@ -35,7 +35,6 @@ #include "mojo/public/cpp/bindings/scoped_interface_endpoint_handle.h" #include "third_party/blink/public/common/page/page_visibility_state.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-shared.h" -#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" #include "third_party/blink/public/platform/web_drag_operation.h" #include "third_party/blink/public/platform/web_string.h" #include "third_party/skia/include/core/SkColor.h" @@ -279,9 +278,6 @@ // Indicates that view's preferred size changes will be sent to the browser. virtual void EnablePreferredSizeChangedMode() = 0; - // Sets the display mode of the web app. - virtual void SetDisplayMode(blink::mojom::DisplayMode) = 0; - // Sets the ratio as computed by computePageScaleConstraints. // TODO(oshima): Remove this once the device scale factor implementation is // fully migrated to use zooming mechanism.
diff --git a/third_party/blink/public/web/web_widget.h b/third_party/blink/public/web/web_widget.h index a8fb3381..5a5c579 100644 --- a/third_party/blink/public/web/web_widget.h +++ b/third_party/blink/public/web/web_widget.h
@@ -39,6 +39,7 @@ #include "cc/trees/layer_tree_host_client.h" #include "third_party/blink/public/common/input/web_menu_source_type.h" #include "third_party/blink/public/common/metrics/document_update_reason.h" +#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/platform/web_input_event_result.h" #include "third_party/blink/public/platform/web_rect.h" @@ -199,6 +200,10 @@ // Called to inform the WebWidget that it has gained or lost keyboard focus. virtual void SetFocus(bool) {} + // Sets the display mode, which comes from the top-level browsing context and + // is applied to all widgets. + virtual void SetDisplayMode(mojom::DisplayMode) {} + // Returns the anchor and focus bounds of the current selection. // If the selection range is empty, it returns the caret bounds. virtual bool SelectionBounds(WebRect& anchor, WebRect& focus) const {
diff --git a/third_party/blink/renderer/core/css/media_values.cc b/third_party/blink/renderer/core/css/media_values.cc index 3ff366de..fda4355 100644 --- a/third_party/blink/renderer/core/css/media_values.cc +++ b/third_party/blink/renderer/core/css/media_values.cc
@@ -21,6 +21,7 @@ #include "third_party/blink/renderer/core/page/chrome_client.h" #include "third_party/blink/renderer/core/page/page.h" #include "third_party/blink/renderer/platform/graphics/color_space_gamut.h" +#include "third_party/blink/renderer/platform/widget/frame_widget.h" namespace blink { @@ -123,18 +124,19 @@ return frame->View()->MediaType(); } -blink::mojom::DisplayMode MediaValues::CalculateDisplayMode(LocalFrame* frame) { +mojom::blink::DisplayMode MediaValues::CalculateDisplayMode(LocalFrame* frame) { DCHECK(frame); + blink::mojom::DisplayMode mode = frame->GetPage()->GetSettings().GetDisplayModeOverride(); - - if (mode != blink::mojom::DisplayMode::kUndefined) + if (mode != mojom::blink::DisplayMode::kUndefined) return mode; - if (!frame->View()) - return blink::mojom::DisplayMode::kBrowser; + FrameWidget* widget = frame->GetWidgetForLocalRoot(); + if (!widget) // Is null in non-ordinary Pages. + return mojom::blink::DisplayMode::kBrowser; - return frame->View()->DisplayMode(); + return widget->DisplayMode(); } bool MediaValues::CalculateThreeDEnabled(LocalFrame* frame) {
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 09f4c78..690f174 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -48,6 +48,7 @@ #include "services/metrics/public/cpp/ukm_source_id.h" #include "services/metrics/public/mojom/ukm_interface.mojom-blink.h" #include "services/network/public/mojom/ip_address_space.mojom-blink.h" +#include "services/network/public/mojom/trust_tokens.mojom-blink.h" #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" #include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/common/feature_policy/document_policy_features.h" @@ -71,6 +72,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v0_custom_element_constructor_builder.h" #include "third_party/blink/renderer/bindings/core/v8/v8_element_creation_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_element_registration_options.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/bindings/core/v8/window_proxy.h" #include "third_party/blink/renderer/core/accessibility/ax_context.h" #include "third_party/blink/renderer/core/accessibility/ax_object_cache.h" @@ -767,6 +769,7 @@ display_lock_document_state_( MakeGarbageCollected<DisplayLockDocumentState>(this)), permission_service_(GetExecutionContext()), + has_trust_tokens_answerer_(GetExecutionContext()), font_preload_manager_(*this) { security_initializer.ApplyPendingDataToDocument(*this); GetOriginTrialContext()->BindExecutionContext(GetExecutionContext()); @@ -6221,6 +6224,110 @@ return promise; } +ScriptPromise Document::hasTrustToken(ScriptState* script_state, + const String& issuer, + ExceptionState& exception_state) { + ScriptPromiseResolver* resolver = + MakeGarbageCollected<ScriptPromiseResolver>(script_state); + + ScriptPromise promise = resolver->Promise(); + + // Trust Tokens state is keyed by issuer and top-frame origins that + // are both (1) HTTP or HTTPS and (2) potentially trustworthy. Consequently, + // we can return early if either the issuer or the top-frame origin fails to + // satisfy either of these requirements. + KURL issuer_url = KURL(issuer); + auto issuer_origin = SecurityOrigin::Create(issuer_url); + if (!issuer_url.ProtocolIsInHTTPFamily() || + !issuer_origin->IsPotentiallyTrustworthy()) { + exception_state.ThrowTypeError( + "hasTrustToken: Trust token issuer origins must be both HTTP(S) and " + "secure (\"potentially trustworthy\")."); + resolver->Reject(exception_state); + return promise; + } + + scoped_refptr<const SecurityOrigin> top_frame_origin = TopFrameOrigin(); + if (!top_frame_origin) { + // Note: One case where there might be no top frame origin is if this + // document is destroyed. In this case, this function will return + // `undefined`. Still bother adding the exception and rejecting, just in + // case there are other situations in which the top frame origin might be + // absent. + exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError, + "hasTrustToken: Cannot execute in " + "documents lacking top-frame origins."); + resolver->Reject(exception_state); + return promise; + } + + if (!top_frame_origin->IsPotentiallyTrustworthy() || + (top_frame_origin->Protocol() != url::kHttpsScheme && + top_frame_origin->Protocol() != url::kHttpScheme)) { + exception_state.ThrowDOMException( + DOMExceptionCode::kNotAllowedError, + "hasTrustToken: Cannot execute in " + "documents without secure, HTTP(S), top-frame origins."); + resolver->Reject(exception_state); + return promise; + } + + if (!has_trust_tokens_answerer_.is_bound()) { + GetBrowserInterfaceBroker().GetInterface( + has_trust_tokens_answerer_.BindNewPipeAndPassReceiver( + GetExecutionContext()->GetTaskRunner(TaskType::kInternalDefault))); + has_trust_tokens_answerer_.set_disconnect_handler( + WTF::Bind(&Document::HasTrustTokensAnswererConnectionError, + WrapWeakPersistent(this))); + } + + pending_has_trust_tokens_resolvers_.insert(resolver); + + has_trust_tokens_answerer_->HasTrustTokens( + issuer_origin, + WTF::Bind( + [](WeakPersistent<ScriptPromiseResolver> resolver, + WeakPersistent<Document> document, + network::mojom::blink::HasTrustTokensResultPtr result) { + // If there was a Mojo connection error, the promise was already + // resolved and deleted. + if (!base::Contains(document->pending_has_trust_tokens_resolvers_, + resolver)) { + return; + } + + if (result->status == + network::mojom::blink::TrustTokenOperationStatus::kOk) { + resolver->Resolve(result->has_trust_tokens); + } else { + ScriptState* state = resolver->GetScriptState(); + ScriptState::Scope scope(state); + resolver->Reject(V8ThrowDOMException::CreateOrEmpty( + state->GetIsolate(), DOMExceptionCode::kOperationError, + "Failed to retrieve hasTrustToken response. (Would " + "associating the given issuer with this top-level origin " + "have exceeded its number-of-issuers limit?)")); + } + + document->pending_has_trust_tokens_resolvers_.erase(resolver); + }, + WrapWeakPersistent(resolver), WrapWeakPersistent(this))); + + return promise; +} + +void Document::HasTrustTokensAnswererConnectionError() { + has_trust_tokens_answerer_.reset(); + for (const auto& resolver : pending_has_trust_tokens_resolvers_) { + ScriptState* state = resolver->GetScriptState(); + ScriptState::Scope scope(state); + resolver->Reject(V8ThrowDOMException::CreateOrEmpty( + state->GetIsolate(), DOMExceptionCode::kOperationError, + "Internal error retrieving hasTrustToken response.")); + } + pending_has_trust_tokens_resolvers_.clear(); +} + static bool IsValidNameNonASCII(const LChar* characters, unsigned length) { if (!IsValidNameStart(characters[0])) return false; @@ -8228,6 +8335,8 @@ visitor->Trace(display_lock_document_state_); visitor->Trace(form_to_pending_submission_); visitor->Trace(permission_service_); + visitor->Trace(has_trust_tokens_answerer_); + visitor->Trace(pending_has_trust_tokens_resolvers_); visitor->Trace(font_preload_manager_); Supplementable<Document>::Trace(visitor); TreeScope::Trace(visitor);
diff --git a/third_party/blink/renderer/core/dom/document.h b/third_party/blink/renderer/core/dom/document.h index 08671a4..8d3ea58 100644 --- a/third_party/blink/renderer/core/dom/document.h +++ b/third_party/blink/renderer/core/dom/document.h
@@ -38,10 +38,12 @@ #include "base/timer/elapsed_timer.h" #include "net/cookies/site_for_cookies.h" #include "services/metrics/public/cpp/ukm_source_id.h" +#include "services/network/public/mojom/trust_tokens.mojom-blink.h" #include "third_party/blink/public/common/metrics/document_update_reason.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h" #include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h" #include "third_party/blink/public/mojom/scroll/scrollbar_mode.mojom-blink.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" #include "third_party/blink/renderer/core/accessibility/axid.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/css/media_value_change.h" @@ -1138,6 +1140,7 @@ const KURL& CookieURL() const { return cookie_url_; } void SetCookieURL(const KURL& url) { cookie_url_ = url; } + // Returns null if the document is not attached to a frame. scoped_refptr<const SecurityOrigin> TopFrameOrigin() const; net::SiteForCookies SiteForCookies() const; @@ -1153,6 +1156,15 @@ ScriptPromise hasStorageAccess(ScriptState* script_state) const; ScriptPromise requestStorageAccess(ScriptState* script_state); + // Sends a query via Mojo to ask whether the user has any trust tokens. This + // can reject on permissions errors (e.g. associating |issuer| with the + // top-level origin would exceed the top-level origin's limit on the number of + // associated issuers) or on other internal errors (e.g. the network service + // is unavailable). + ScriptPromise hasTrustToken(ScriptState* script_state, + const String& issuer, + ExceptionState&); + // The following implements the rule from HTML 4 for what valid names are. // To get this right for all the XML cases, we probably have to improve this // or move it and make it sensitive to the type of document. @@ -1765,6 +1777,7 @@ } private: + friend class DocumentTest; friend class IgnoreDestructiveWriteCountIncrementer; friend class ThrowOnDynamicMarkupInsertionCountIncrementer; friend class IgnoreOpensDuringUnloadCountIncrementer; @@ -1903,6 +1916,10 @@ void ExecuteFormSubmission(HTMLFormElement* form_element); + // Handles a connection error to |has_trust_tokens_answerer_| by rejecting all + // pending promises created by |hasTrustToken|. + void HasTrustTokensAnswererConnectionError(); + DocumentLifecycle lifecycle_; bool evaluate_media_queries_on_style_recalc_; @@ -2318,6 +2335,22 @@ // storage or not. HeapMojoRemote<mojom::blink::PermissionService> permission_service_; + // Mojo remote used to answer API calls asking whether the user has trust + // tokens (https://github.com/wicg/trust-token-api). The other endpoint + // is in the network service, which may crash and restart. To handle this: + // 1. |pending_has_trust_tokens_resolvers_| keeps track of promises + // depending on |has_trust_tokens_answerer_|'s answers; + // 2. |HasTrustTokensAnswererConnectionError| handles connection errors by + // rejecting all pending promises and clearing the pending set. + HeapMojoRemote<network::mojom::blink::HasTrustTokensAnswerer> + has_trust_tokens_answerer_; + + // In order to be able to answer promises when the Mojo remote disconnects, + // maintain all pending promises here, deleting them on successful completion + // or on connection error, whichever comes first. + HeapHashSet<Member<ScriptPromiseResolver>> + pending_has_trust_tokens_resolvers_; + FontPreloadManager font_preload_manager_; };
diff --git a/third_party/blink/renderer/core/dom/document.idl b/third_party/blink/renderer/core/dom/document.idl index a8025f5..efce87b 100644 --- a/third_party/blink/renderer/core/dom/document.idl +++ b/third_party/blink/renderer/core/dom/document.idl
@@ -200,6 +200,9 @@ [MeasureAs=PrefixedPageVisibility, ImplementedAs=visibilityState] readonly attribute DOMString webkitVisibilityState; [MeasureAs=PrefixedPageVisibility, ImplementedAs=hidden] readonly attribute boolean webkitHidden; + // Trust Token API (https://github.com/wicg/trust-token-api) + [CallWith=ScriptState, Measure, RaisesException, NewObject, SecureContext, RuntimeEnabled=TrustTokens] Promise<boolean> hasTrustToken(USVString issuer); + // Event handler attributes attribute EventHandler onbeforecopy; attribute EventHandler onbeforecut;
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc index 5d3721c..923a1b5 100644 --- a/third_party/blink/renderer/core/dom/document_test.cc +++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -38,11 +38,15 @@ #include "services/network/public/mojom/referrer_policy.mojom-blink.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/browser_interface_broker_proxy.h" #include "third_party/blink/public/common/feature_policy/document_policy_features.h" #include "third_party/blink/public/mojom/feature_policy/feature_policy_feature.mojom-blink.h" #include "third_party/blink/renderer/bindings/core/v8/isolated_world_csp.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/core/css/media_query_list_listener.h" #include "third_party/blink/renderer/core/css/media_query_matcher.h" #include "third_party/blink/renderer/core/dom/document_fragment.h" @@ -82,6 +86,12 @@ using network::mojom::ContentSecurityPolicyType; class DocumentTest : public PageTestBase { + public: + static void SimulateHasTrustTokensAnswererConnectionError( + Document* document) { + document->HasTrustTokensAnswererConnectionError(); + } + protected: void TearDown() override { ThreadState::Current()->CollectAllGarbageForTesting(); @@ -329,6 +339,19 @@ bool notified_ = false; }; +bool IsDOMException(ScriptState* script_state, + ScriptValue value, + DOMExceptionCode code) { + auto* dom_exception = V8DOMException::ToImplWithTypeCheck( + script_state->GetIsolate(), value.V8Value()); + if (!dom_exception) + return false; + + // Unfortunately, it's not enough to check |dom_exception->code() == code|, + // as DOMException::code is only populated for the DOMExceptionCodes with + // "legacy code" numeric values. + return dom_exception->name() == DOMException(code).name(); +} } // anonymous namespace TEST_F(DocumentTest, CreateRangeAdjustedToTreeScopeWithPositionInShadowTree) { @@ -1219,6 +1242,177 @@ EXPECT_EQ(DoubleSize(400, 960), page_size); } +TEST(Document, HandlesDisconnectDuringHasTrustToken) { + // Check that a Mojo handle disconnecting during hasTrustToken operation + // execution results in the promise getting rejected with the proper + // exception. + V8TestingScope scope(KURL("https://trusttoken.example")); + + Document& document = scope.GetDocument(); + + auto promise = + document.hasTrustToken(scope.GetScriptState(), "https://issuer.example", + scope.GetExceptionState()); + DocumentTest::SimulateHasTrustTokensAnswererConnectionError(&document); + + ASSERT_TRUE(promise.IsAssociatedWith(scope.GetScriptState())); + + ScriptPromiseTester promise_tester(scope.GetScriptState(), promise); + promise_tester.WaitUntilSettled(); + EXPECT_TRUE(promise_tester.IsRejected()); + EXPECT_TRUE(IsDOMException(scope.GetScriptState(), promise_tester.Value(), + DOMExceptionCode::kOperationError)); +} + +TEST(Document, RejectsHasTrustTokenCallFromNonHttpNonHttpsDocument) { + // Check that hasTrustToken getting called from a secure, but + // non-http/non-https, document results in an exception being thrown. + V8TestingScope scope(KURL("file:///trusttoken.txt")); + + Document& document = scope.GetDocument(); + ScriptState* script_state = scope.GetScriptState(); + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kExecutionContext, "Document", + "hasTrustToken"); + + auto promise = document.hasTrustToken(script_state, "https://issuer.example", + exception_state); + + ScriptPromiseTester promise_tester(script_state, promise); + promise_tester.WaitUntilSettled(); + EXPECT_TRUE(promise_tester.IsRejected()); + EXPECT_TRUE(IsDOMException(script_state, promise_tester.Value(), + DOMExceptionCode::kNotAllowedError)); +} + +namespace { +class MockHasTrustTokensAnswerer + : public network::mojom::blink::HasTrustTokensAnswerer { + public: + enum Outcome { kError, kTrue, kFalse }; + explicit MockHasTrustTokensAnswerer(Outcome outcome) : outcome_(outcome) {} + + void HasTrustTokens( + const ::scoped_refptr<const ::blink::SecurityOrigin>& issuer, + HasTrustTokensCallback callback) override { + auto result = network::mojom::blink::HasTrustTokensResult::New(); + result->status = network::mojom::blink::TrustTokenOperationStatus::kOk; + switch (outcome_) { + case kTrue: { + result->has_trust_tokens = true; + std::move(callback).Run(std::move(result)); + return; + } + case kFalse: { + result->has_trust_tokens = false; + std::move(callback).Run(std::move(result)); + return; + } + case kError: { + result->status = + network::mojom::blink::TrustTokenOperationStatus::kUnknownError; + std::move(callback).Run(std::move(result)); + } + } + } + + void Bind(mojo::ScopedMessagePipeHandle handle) { + receiver_.Bind( + mojo::PendingReceiver<network::mojom::blink::HasTrustTokensAnswerer>( + std::move(handle))); + } + + private: + Outcome outcome_; + mojo::Receiver<network::mojom::blink::HasTrustTokensAnswerer> receiver_{this}; +}; +} // namespace + +TEST(Document, HasTrustTokenSuccess) { + V8TestingScope scope(KURL("https://secure.example")); + + MockHasTrustTokensAnswerer answerer(MockHasTrustTokensAnswerer::kTrue); + + Document& document = scope.GetDocument(); + document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting( + network::mojom::blink::HasTrustTokensAnswerer::Name_, + WTF::BindRepeating(&MockHasTrustTokensAnswerer::Bind, + WTF::Unretained(&answerer))); + + ScriptState* script_state = scope.GetScriptState(); + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kExecutionContext, "Document", + "hasTrustToken"); + + auto promise = document.hasTrustToken(script_state, "https://issuer.example", + exception_state); + + ScriptPromiseTester promise_tester(script_state, promise); + promise_tester.WaitUntilSettled(); + EXPECT_TRUE(promise_tester.IsFulfilled()); + EXPECT_TRUE(promise_tester.Value().V8Value()->IsTrue()); + + document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting( + network::mojom::blink::HasTrustTokensAnswerer::Name_, {}); +} + +TEST(Document, HasTrustTokenSuccessWithFalseValue) { + V8TestingScope scope(KURL("https://secure.example")); + + MockHasTrustTokensAnswerer answerer(MockHasTrustTokensAnswerer::kFalse); + + Document& document = scope.GetDocument(); + document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting( + network::mojom::blink::HasTrustTokensAnswerer::Name_, + WTF::BindRepeating(&MockHasTrustTokensAnswerer::Bind, + WTF::Unretained(&answerer))); + + ScriptState* script_state = scope.GetScriptState(); + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kExecutionContext, "Document", + "hasTrustToken"); + + auto promise = document.hasTrustToken(script_state, "https://issuer.example", + exception_state); + + ScriptPromiseTester promise_tester(script_state, promise); + promise_tester.WaitUntilSettled(); + EXPECT_TRUE(promise_tester.IsFulfilled()); + EXPECT_TRUE(promise_tester.Value().V8Value()->IsFalse()); + + document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting( + network::mojom::blink::HasTrustTokensAnswerer::Name_, {}); +} + +TEST(Document, HasTrustTokenOperationError) { + V8TestingScope scope(KURL("https://secure.example")); + + MockHasTrustTokensAnswerer answerer(MockHasTrustTokensAnswerer::kError); + + Document& document = scope.GetDocument(); + document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting( + network::mojom::blink::HasTrustTokensAnswerer::Name_, + WTF::BindRepeating(&MockHasTrustTokensAnswerer::Bind, + WTF::Unretained(&answerer))); + + ScriptState* script_state = scope.GetScriptState(); + ExceptionState exception_state(script_state->GetIsolate(), + ExceptionState::kExecutionContext, "Document", + "hasTrustToken"); + + auto promise = document.hasTrustToken(script_state, "https://issuer.example", + exception_state); + + ScriptPromiseTester promise_tester(script_state, promise); + promise_tester.WaitUntilSettled(); + EXPECT_TRUE(promise_tester.IsRejected()); + EXPECT_TRUE(IsDOMException(script_state, promise_tester.Value(), + DOMExceptionCode::kOperationError)); + + document.GetFrame()->GetBrowserInterfaceBroker().SetBinderForTesting( + network::mojom::blink::HasTrustTokensAnswerer::Name_, {}); +} + /** * Tests for viewport-fit propagation. */
diff --git a/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc b/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc index f71a66f0..1728a59 100644 --- a/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc +++ b/third_party/blink/renderer/core/exported/web_frame_content_dumper.cc
@@ -103,6 +103,10 @@ return WebString(); DCHECK(web_view->MainFrameWidget()); + // Updating the document lifecycle isn't enough, the BeginFrame() step + // should come first which runs events such as notifying of media query + // changes or raf-based events. + web_view->MainFrameWidget()->BeginFrame(base::TimeTicks::Now()); web_view->MainFrameWidget()->UpdateAllLifecyclePhases( DocumentUpdateReason::kTest);
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc index 43fc2bb..3d6eef0d 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.cc +++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
@@ -401,14 +401,6 @@ } } -void WebViewImpl::SetDisplayMode(blink::mojom::DisplayMode mode) { - display_mode_ = mode; - if (!MainFrameImpl() || !MainFrameImpl()->GetFrameView()) - return; - - MainFrameImpl()->GetFrameView()->SetDisplayMode(mode); -} - void WebViewImpl::MouseContextMenu(const WebMouseEvent& event) { if (!MainFrameImpl() || !MainFrameImpl()->GetFrameView()) return;
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.h b/third_party/blink/renderer/core/exported/web_view_impl.h index 60cfa74..ae5fb3f 100644 --- a/third_party/blink/renderer/core/exported/web_view_impl.h +++ b/third_party/blink/renderer/core/exported/web_view_impl.h
@@ -41,7 +41,6 @@ #include "third_party/blink/public/common/input/web_input_event.h" #include "third_party/blink/public/mojom/frame/frame.mojom-blink.h" #include "third_party/blink/public/mojom/input/focus_type.mojom-blink-forward.h" -#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" #include "third_party/blink/public/mojom/page/page.mojom-blink.h" #include "third_party/blink/public/platform/web_input_event_result.h" #include "third_party/blink/public/platform/web_rect.h" @@ -181,7 +180,6 @@ WebSize ContentsPreferredMinimumSize() override; void UpdatePreferredSize() override; void EnablePreferredSizeChangedMode() override; - void SetDisplayMode(blink::mojom::DisplayMode) override; void SetDeviceScaleFactor(float) override; void SetZoomFactorForDeviceScaleFactor(float) override; float ZoomFactorForDeviceScaleFactor() override { @@ -397,7 +395,6 @@ WebSize Size(); IntSize MainFrameSize(); - blink::mojom::DisplayMode DisplayMode() const { return display_mode_; } PageScaleConstraintsSet& GetPageScaleConstraintsSet() const; @@ -689,7 +686,6 @@ bool should_dispatch_first_visually_non_empty_layout_ = false; bool should_dispatch_first_layout_after_finished_parsing_ = false; bool should_dispatch_first_layout_after_finished_loading_ = false; - blink::mojom::DisplayMode display_mode_ = blink::mojom::DisplayMode::kBrowser; // TODO(bokan): Temporary debugging added to diagnose // https://crbug.com/992315. Somehow we're synchronously calling
diff --git a/third_party/blink/renderer/core/exported/web_view_test.cc b/third_party/blink/renderer/core/exported/web_view_test.cc index 59433d10..970b1a2fc 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -67,7 +67,6 @@ #include "third_party/blink/public/web/web_element.h" #include "third_party/blink/public/web/web_frame.h" #include "third_party/blink/public/web/web_frame_content_dumper.h" -#include "third_party/blink/public/web/web_frame_widget.h" #include "third_party/blink/public/web/web_hit_test_result.h" #include "third_party/blink/public/web/web_input_method_controller.h" #include "third_party/blink/public/web/web_local_frame.h" @@ -80,6 +79,8 @@ #include "third_party/blink/public/web/web_widget.h" #include "third_party/blink/public/web/web_widget_client.h" #include "third_party/blink/renderer/bindings/core/v8/v8_document.h" +#include "third_party/blink/renderer/core/css/media_query_list_listener.h" +#include "third_party/blink/renderer/core/css/media_query_matcher.h" #include "third_party/blink/renderer/core/dom/document.h" #include "third_party/blink/renderer/core/dom/element.h" #include "third_party/blink/renderer/core/dom/node_computed_style.h" @@ -95,6 +96,7 @@ #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/frame/visual_viewport.h" +#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h" #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/fullscreen/fullscreen.h" #include "third_party/blink/renderer/core/html/forms/external_date_time_chooser.h" @@ -3948,19 +3950,70 @@ TEST_F(WebViewTest, ChangeDisplayMode) { RegisterMockedHttpURLLoad("display_mode.html"); - WebView* web_view = + WebViewImpl* web_view = web_view_helper_.InitializeAndLoad(base_url_ + "display_mode.html"); - std::string content = - WebFrameContentDumper::DumpWebViewAsText(web_view, 21).Utf8(); + String content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21); EXPECT_EQ("regular-ui", content); - web_view->SetDisplayMode(blink::mojom::DisplayMode::kMinimalUi); - content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21).Utf8(); + web_view->MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode( + mojom::blink::DisplayMode::kMinimalUi); + content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21); EXPECT_EQ("minimal-ui", content); web_view_helper_.Reset(); } +TEST_F(WebViewTest, ChangeDisplayModeChildFrame) { + RegisterMockedHttpURLLoad("iframe-display_mode.html"); + RegisterMockedHttpURLLoad("display_mode.html"); + WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( + base_url_ + "iframe-display_mode.html"); + + String content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21); + // An iframe inserts whitespace into the content. + EXPECT_EQ("regular-ui", content.StripWhiteSpace()); + + web_view->MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode( + mojom::blink::DisplayMode::kMinimalUi); + content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21); + // An iframe inserts whitespace into the content. + EXPECT_EQ("minimal-ui", content.StripWhiteSpace()); + web_view_helper_.Reset(); +} + +TEST_F(WebViewTest, ChangeDisplayModeAlertsListener) { + RegisterMockedHttpURLLoad("display_mode_listener.html"); + WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( + base_url_ + "display_mode_listener.html"); + + String content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21); + EXPECT_EQ("regular-ui", content); + + web_view->MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode( + mojom::blink::DisplayMode::kMinimalUi); + content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21); + EXPECT_EQ("minimal-ui", content); + web_view_helper_.Reset(); +} + +TEST_F(WebViewTest, ChangeDisplayModeChildFrameAlertsListener) { + RegisterMockedHttpURLLoad("iframe-display_mode_listener.html"); + RegisterMockedHttpURLLoad("display_mode_listener.html"); + WebViewImpl* web_view = web_view_helper_.InitializeAndLoad( + base_url_ + "iframe-display_mode_listener.html"); + + String content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21); + // An iframe inserts whitespace into the content. + EXPECT_EQ("regular-ui", content.StripWhiteSpace()); + + web_view->MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode( + mojom::blink::DisplayMode::kMinimalUi); + content = WebFrameContentDumper::DumpWebViewAsText(web_view, 21); + // An iframe inserts whitespace into the content. + EXPECT_EQ("minimal-ui", content.StripWhiteSpace()); + web_view_helper_.Reset(); +} + TEST_F(WebViewTest, AddFrameInCloseUnload) { CreateChildCounterFrameClient frame_client; RegisterMockedHttpURLLoad("add_frame_in_unload.html");
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index ab0d55c3..0b3593de 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -902,6 +902,16 @@ } } +void LocalFrame::MediaQueryAffectingValueChangedForLocalSubtree( + MediaValueChange value) { + GetDocument()->MediaQueryAffectingValueChanged(value); + for (Frame* child = Tree().FirstChild(); child; + child = child->Tree().NextSibling()) { + if (auto* child_local_frame = DynamicTo<LocalFrame>(child)) + child_local_frame->MediaQueryAffectingValueChangedForLocalSubtree(value); + } +} + double LocalFrame::DevicePixelRatio() const { if (!page_) return 0;
diff --git a/third_party/blink/renderer/core/frame/local_frame.h b/third_party/blink/renderer/core/frame/local_frame.h index 30763d3..e280e66b 100644 --- a/third_party/blink/renderer/core/frame/local_frame.h +++ b/third_party/blink/renderer/core/frame/local_frame.h
@@ -261,6 +261,10 @@ void DeviceScaleFactorChanged(); double DevicePixelRatio() const; + // Informs the local root's document and its local descendant subtree that a + // media query value changed. + void MediaQueryAffectingValueChangedForLocalSubtree(MediaValueChange); + String SelectedText() const; String SelectedTextForClipboard() const;
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 b97c7484..86f072c 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -230,7 +230,6 @@ LocalFrameView::LocalFrameView(LocalFrame& frame, IntRect frame_rect) : FrameView(frame_rect), frame_(frame), - display_mode_(blink::mojom::DisplayMode::kBrowser), can_have_scrollbars_(true), has_pending_layout_(false), layout_scheduling_enabled_(true), @@ -1181,18 +1180,6 @@ part_update_set_.insert(&object); } -void LocalFrameView::SetDisplayMode(blink::mojom::DisplayMode mode) { - if (mode == display_mode_) - return; - - display_mode_ = mode; - - if (frame_->GetDocument()) { - frame_->GetDocument()->MediaQueryAffectingValueChanged( - MediaValueChange::kOther); - } -} - void LocalFrameView::SetDisplayShape(DisplayShape display_shape) { if (display_shape == display_shape_) return;
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index f9bc706..fb416c0 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -30,7 +30,6 @@ #include "third_party/blink/public/common/metrics/document_update_reason.h" #include "third_party/blink/public/mojom/frame/lifecycle.mojom-blink-forward.h" -#include "third_party/blink/public/mojom/manifest/display_mode.mojom-shared.h" #include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink-forward.h" #include "third_party/blink/public/platform/shape_properties.h" #include "third_party/blink/renderer/core/core_export.h" @@ -275,9 +274,6 @@ void SetMediaType(const AtomicString&); void AdjustMediaTypeForPrinting(bool printing); - blink::mojom::DisplayMode DisplayMode() { return display_mode_; } - void SetDisplayMode(blink::mojom::DisplayMode); - DisplayShape GetDisplayShape() { return display_shape_; } void SetDisplayShape(DisplayShape); @@ -858,8 +854,6 @@ Member<LocalFrame> frame_; - blink::mojom::DisplayMode display_mode_; - DisplayShape display_shape_; bool can_have_scrollbars_;
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc index 6d5fb29..5a6a8ceb 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_base.cc +++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.cc
@@ -458,6 +458,10 @@ listener_class); } +mojom::blink::DisplayMode WebFrameWidgetBase::DisplayMode() const { + return display_mode_; +} + void WebFrameWidgetBase::StartDeferringCommits(base::TimeDelta timeout) { if (!View()->does_composite()) return; @@ -631,6 +635,15 @@ ApplyViewportChanges(args); } +void WebFrameWidgetBase::SetDisplayMode(mojom::blink::DisplayMode mode) { + if (mode != display_mode_) { + display_mode_ = mode; + LocalFrame* frame = LocalRootImpl()->GetFrame(); + frame->MediaQueryAffectingValueChangedForLocalSubtree( + MediaValueChange::kOther); + } +} + void WebFrameWidgetBase::RequestAnimationAfterDelay( const base::TimeDelta& delay) { DCHECK(request_animation_after_delay_timer_.get());
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_base.h b/third_party/blink/renderer/core/frame/web_frame_widget_base.h index 2663b0e..740df401 100644 --- a/third_party/blink/renderer/core/frame/web_frame_widget_base.h +++ b/third_party/blink/renderer/core/frame/web_frame_widget_base.h
@@ -14,6 +14,7 @@ #include "mojo/public/cpp/bindings/associated_remote.h" #include "services/network/public/mojom/referrer_policy.mojom-blink-forward.h" #include "third_party/blink/public/common/input/web_gesture_device.h" +#include "third_party/blink/public/mojom/manifest/display_mode.mojom-blink.h" #include "third_party/blink/public/mojom/page/widget.mojom-blink.h" #include "third_party/blink/public/platform/cross_variant_mojo_util.h" #include "third_party/blink/public/platform/web_coalesced_input_event.h" @@ -111,6 +112,7 @@ cc::EventListenerProperties) final; cc::EventListenerProperties EventListenerProperties( cc::EventListenerClass) const final; + mojom::blink::DisplayMode DisplayMode() const override; // WebFrameWidget implementation. void Close() override; @@ -167,6 +169,7 @@ void SetCompositorVisible(bool visible) override; void UpdateVisualState() override; void WillBeginCompositorFrame() final; + void SetDisplayMode(mojom::blink::DisplayMode) override; // WidgetBaseClient methods. void DispatchRafAlignedInput(base::TimeTicks frame_time) override; @@ -296,6 +299,8 @@ void CancelDrag(); void RequestAnimationAfterDelayTimerFired(TimerBase*); + static bool ignore_input_events_; + WebWidgetClient* client_; // WebFrameWidget is associated with a subtree of the frame tree, @@ -303,7 +308,7 @@ // points to the root of that subtree. Member<WebLocalFrameImpl> local_root_; - static bool ignore_input_events_; + mojom::blink::DisplayMode display_mode_; // This is owned by the LayerTreeHostImpl, and should only be used on the // compositor thread, so we keep the TaskRunner where you post tasks to
diff --git a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc index e4f4ed4..f0255b4 100644 --- a/third_party/blink/renderer/core/frame/web_local_frame_impl.cc +++ b/third_party/blink/renderer/core/frame/web_local_frame_impl.cc
@@ -254,7 +254,6 @@ #include "third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h" #include "third_party/blink/renderer/platform/loader/fetch/resource_request.h" #include "third_party/blink/renderer/platform/scheduler/public/frame_scheduler.h" -#include "third_party/blink/renderer/platform/scheduler/public/scheduling_policy.h" #include "third_party/blink/renderer/platform/text/text_direction.h" #include "third_party/blink/renderer/platform/weborigin/kurl.h" #include "third_party/blink/renderer/platform/weborigin/scheme_registry.h" @@ -1492,11 +1491,6 @@ is_in_printing_ = true; #endif - // Disable BackForwardCache when printing API is used. - GetFrame()->GetFrameScheduler()->RegisterStickyFeature( - blink::SchedulingPolicy::Feature::kPrinting, - {blink::SchedulingPolicy::RecordMetricsForBackForwardCache()}); - GetFrame()->GetDocument()->SetPrinting(Document::kBeforePrinting); DispatchPrintEventRecursively(event_type_names::kBeforeprint); } @@ -1949,8 +1943,6 @@ web_view->MaxAutoSize()); } - GetFrame()->View()->SetDisplayMode(web_view->DisplayMode()); - if (frame_widget_) frame_widget_->DidCreateLocalRootView(); }
diff --git a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc index 9829728..fbe1cc5 100644 --- a/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc +++ b/third_party/blink/renderer/core/html/canvas/canvas_async_blob_creator.cc
@@ -309,8 +309,9 @@ // deadlines (6.7s or 13s) bypass the web test running deadline (6s) // and result in timeouts on different tests. We use // enforce_idle_encoding_for_test_ to test idle encoding in unit tests. - // We also don't use idle tasks in workers because there's no proper idle - // queue there and tasks can take too long without requestAnimationFrame. + // We also don't use idle tasks in workers because the short idle periods are + // not implemented, so the idle task can take a long time even when the thread + // is not busy. bool use_idle_encoding = WTF::IsMainThread() && (mime_type_ != kMimeTypeWebp) && (enforce_idle_encoding_for_test_ ||
diff --git a/third_party/blink/renderer/core/input/event_handler_test.cc b/third_party/blink/renderer/core/input/event_handler_test.cc index cca36d9..a18739e7 100644 --- a/third_party/blink/renderer/core/input/event_handler_test.cc +++ b/third_party/blink/renderer/core/input/event_handler_test.cc
@@ -28,6 +28,8 @@ #include "third_party/blink/renderer/core/frame/local_frame_view.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/frame/visual_viewport.h" +#include "third_party/blink/renderer/core/frame/web_frame_widget_base.h" +#include "third_party/blink/renderer/core/frame/web_local_frame_impl.h" #include "third_party/blink/renderer/core/html/canvas/html_canvas_element.h" #include "third_party/blink/renderer/core/html/forms/html_input_element.h" #include "third_party/blink/renderer/core/html/html_iframe_element.h" @@ -2211,7 +2213,8 @@ GetDocument().GetSettings()->SetDontSendKeyEventsToJavascript(true); GetDocument().GetSettings()->SetScrollAnimatorEnabled(false); GetDocument().GetSettings()->SetWebAppScope(GetDocument().Url()); - GetDocument().View()->SetDisplayMode(blink::mojom::DisplayMode::kFullscreen); + WebView().MainFrameImpl()->LocalRootFrameWidget()->SetDisplayMode( + blink::mojom::DisplayMode::kFullscreen); request.Complete(R"HTML( <!DOCTYPE html> <style>
diff --git a/third_party/blink/renderer/core/input/keyboard_event_manager.cc b/third_party/blink/renderer/core/input/keyboard_event_manager.cc index 8589587..124043f 100644 --- a/third_party/blink/renderer/core/input/keyboard_event_manager.cc +++ b/third_party/blink/renderer/core/input/keyboard_event_manager.cc
@@ -30,6 +30,7 @@ #include "third_party/blink/renderer/core/page/spatial_navigation.h" #include "third_party/blink/renderer/core/page/spatial_navigation_controller.h" #include "third_party/blink/renderer/platform/keyboard_codes.h" +#include "third_party/blink/renderer/platform/widget/frame_widget.h" #include "third_party/blink/renderer/platform/windows_keyboard_codes.h" #include "ui/events/keycodes/dom/keycode_converter.h" @@ -236,8 +237,8 @@ if (!should_send_key_events_to_js && frame_->GetDocument()->IsInWebAppScope()) { - DCHECK(frame_->View()); - blink::mojom::DisplayMode display_mode = frame_->View()->DisplayMode(); + mojom::blink::DisplayMode display_mode = + frame_->GetWidgetForLocalRoot()->DisplayMode(); should_send_key_events_to_js = display_mode == blink::mojom::DisplayMode::kMinimalUi || display_mode == blink::mojom::DisplayMode::kStandalone ||
diff --git a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc index a7c94b07..c9f9662 100644 --- a/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc +++ b/third_party/blink/renderer/core/paint/compositing/composited_layer_mapping.cc
@@ -448,9 +448,6 @@ UpdateElementId(); - graphics_layer_->SetHasWillChangeTransformHint( - style.HasWillChangeTransformHint()); - if (style.Preserves3D() && style.HasOpacity() && owning_layer_.Has3DTransformedDescendant()) { UseCounter::Count(layout_object.GetDocument(),
diff --git a/third_party/blink/renderer/core/paint/paint_layer.cc b/third_party/blink/renderer/core/paint/paint_layer.cc index 5736b22c..f764ea5b 100644 --- a/third_party/blink/renderer/core/paint/paint_layer.cc +++ b/third_party/blink/renderer/core/paint/paint_layer.cc
@@ -366,6 +366,7 @@ } bool PaintLayer::ScrollsWithRespectTo(const PaintLayer* other) const { + DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()); if (FixedToViewport() != other->FixedToViewport()) return true; // If either element sticks we cannot trivially determine that the layers do
diff --git a/third_party/blink/renderer/core/testing/data/display_mode_listener.html b/third_party/blink/renderer/core/testing/data/display_mode_listener.html new file mode 100644 index 0000000..1c744ed --- /dev/null +++ b/third_party/blink/renderer/core/testing/data/display_mode_listener.html
@@ -0,0 +1,20 @@ +<!doctype html> +<html> + <style> + #minimal { display: none; } +</style> +<body> + +<div id="minimal">minimal-ui</div> + +<div id="regular">regular-ui</div> + +<script> + function mediaquery() { + document.getElementById('minimal').style.display = "block"; + document.getElementById('regular').style.display = "none"; + } + window.matchMedia('(display-mode: minimal-ui)').addListener(mediaquery); +</script> +</body> +</html>
diff --git a/third_party/blink/renderer/core/testing/data/iframe-display_mode.html b/third_party/blink/renderer/core/testing/data/iframe-display_mode.html new file mode 100644 index 0000000..5f1b4bee --- /dev/null +++ b/third_party/blink/renderer/core/testing/data/iframe-display_mode.html
@@ -0,0 +1,6 @@ +<!doctype html> +<html> + <body> + <iframe src="display_mode.html"></iframe> +</body> +</html>
diff --git a/third_party/blink/renderer/core/testing/data/iframe-display_mode_listener.html b/third_party/blink/renderer/core/testing/data/iframe-display_mode_listener.html new file mode 100644 index 0000000..735f30f --- /dev/null +++ b/third_party/blink/renderer/core/testing/data/iframe-display_mode_listener.html
@@ -0,0 +1,6 @@ +<!doctype html> +<html> + <body> + <iframe src="display_mode_listener.html"></iframe> +</body> +</html>
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc index c494d2f..984b4f7 100644 --- a/third_party/blink/renderer/core/testing/internals.cc +++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -2165,6 +2165,7 @@ bool Internals::scrollsWithRespectTo(Element* element1, Element* element2, ExceptionState& exception_state) { + DCHECK(!RuntimeEnabledFeatures::CompositeAfterPaintEnabled()); DCHECK(element1 && element2); element1->GetDocument().View()->UpdateAllLifecyclePhases( DocumentUpdateReason::kTest);
diff --git a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc index 962fb260..8ec4ba1 100644 --- a/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc +++ b/third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_controller_impl.cc
@@ -24,6 +24,7 @@ #include "third_party/blink/renderer/modules/picture_in_picture/picture_in_picture_window.h" #include "third_party/blink/renderer/platform/heap/heap.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" +#include "third_party/blink/renderer/platform/widget/frame_widget.h" #include "third_party/blink/renderer/platform/wtf/functional.h" namespace blink { @@ -318,12 +319,15 @@ // - Document runs in a Chrome Extension. // - Document is in fullscreen. // - Document is in a PWA window that runs in the scope of the PWA. + bool is_in_pwa_window = false; + if (GetSupplementable()->GetFrame()) { + mojom::blink::DisplayMode display_mode = + GetSupplementable()->GetFrame()->GetWidgetForLocalRoot()->DisplayMode(); + is_in_pwa_window = display_mode != mojom::blink::DisplayMode::kBrowser; + } if (!(GetSupplementable()->Url().ProtocolIs("chrome-extension") || Fullscreen::FullscreenElementFrom(*GetSupplementable()) || - (GetSupplementable()->View() && - GetSupplementable()->View()->DisplayMode() != - blink::mojom::DisplayMode::kBrowser && - GetSupplementable()->IsInWebAppScope()))) { + (is_in_pwa_window && GetSupplementable()->IsInWebAppScope()))) { return false; }
diff --git a/third_party/blink/renderer/modules/presentation/presentation_connection.cc b/third_party/blink/renderer/modules/presentation/presentation_connection.cc index 85905a3..de49ab2 100644 --- a/third_party/blink/renderer/modules/presentation/presentation_connection.cc +++ b/third_party/blink/renderer/modules/presentation/presentation_connection.cc
@@ -240,7 +240,7 @@ DCHECK(request); auto* connection = MakeGarbageCollected<ControllerPresentationConnection>( - *controller->GetSupplementable(), controller, presentation_info.id, + *controller->GetFrame(), controller, presentation_info.id, presentation_info.url); controller->RegisterConnection(connection);
diff --git a/third_party/blink/renderer/modules/presentation/presentation_controller.cc b/third_party/blink/renderer/modules/presentation/presentation_controller.cc index f2e7db76..5dd3bf68 100644 --- a/third_party/blink/renderer/modules/presentation/presentation_controller.cc +++ b/third_party/blink/renderer/modules/presentation/presentation_controller.cc
@@ -22,6 +22,7 @@ PresentationController::PresentationController(LocalFrame& frame) : Supplement<LocalFrame>(frame), + ExecutionContextLifecycleObserver(frame.GetDocument()), presentation_controller_receiver_(this, frame.DomWindow()) {} PresentationController::~PresentationController() = default; @@ -59,6 +60,7 @@ visitor->Trace(connections_); visitor->Trace(availability_state_); Supplement<LocalFrame>::Trace(visitor); + ExecutionContextLifecycleObserver::Trace(visitor); } void PresentationController::SetPresentation(Presentation* presentation) { @@ -151,10 +153,10 @@ mojo::Remote<mojom::blink::PresentationService>& PresentationController::GetPresentationService() { - if (!presentation_service_remote_ && GetSupplementable()) { + if (!presentation_service_remote_ && GetFrame()) { scoped_refptr<base::SingleThreadTaskRunner> task_runner = - GetSupplementable()->GetTaskRunner(TaskType::kPresentation); - GetSupplementable()->GetBrowserInterfaceBroker().GetInterface( + GetFrame()->GetTaskRunner(TaskType::kPresentation); + GetFrame()->GetBrowserInterfaceBroker().GetInterface( presentation_service_remote_.BindNewPipeAndPassReceiver(task_runner)); presentation_service_remote_->SetController( presentation_controller_receiver_.BindNewPipeAndPassRemote(
diff --git a/third_party/blink/renderer/modules/presentation/presentation_controller.h b/third_party/blink/renderer/modules/presentation/presentation_controller.h index a5789e6..ba9cfbb 100644 --- a/third_party/blink/renderer/modules/presentation/presentation_controller.h +++ b/third_party/blink/renderer/modules/presentation/presentation_controller.h
@@ -8,6 +8,7 @@ #include "base/macros.h" #include "mojo/public/cpp/bindings/remote.h" #include "third_party/blink/public/mojom/presentation/presentation.mojom-blink.h" +#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/modules/modules_export.h" @@ -30,6 +31,7 @@ class MODULES_EXPORT PresentationController : public GarbageCollected<PresentationController>, public Supplement<LocalFrame>, + public ExecutionContextLifecycleObserver, public mojom::blink::PresentationController { USING_GARBAGE_COLLECTED_MIXIN(PresentationController); @@ -77,6 +79,9 @@ virtual void RemoveAvailabilityObserver(PresentationAvailabilityObserver*); private: + // Implementation of ExecutionContextLifecycleObserver. + void ContextDestroyed() override {} + // mojom::blink::PresentationController implementation. void OnScreenAvailabilityUpdated(const KURL&, mojom::blink::ScreenAvailability) override;
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 df03c3500..e353199 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
@@ -11,12 +11,13 @@ // 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_12 = 0x00090000; static const uint32_t kBlinkLocalCTVersionNumber10_13 = 0x000A0000; +static const uint32_t kBlinkLocalCTVersionNumber10_14 = 0x000B0000; bool CoreTextVersionSupportsVariations() { return &CTGetCoreTextVersion && - CTGetCoreTextVersion() >= kBlinkLocalCTVersionNumber10_12; + CTGetCoreTextVersion() >= kBlinkLocalCTVersionNumber10_14; } // CoreText versions below 10.13 display COLR cpal as black/foreground-color
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc index f800478..75ad3a1 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -322,11 +322,10 @@ namespace { -int AdjustedFocusRingOffset(int offset, int width) { - if (::features::IsFormControlsRefreshEnabled()) { - // For FormControlsRefresh just use the value of outline-offset. - return offset; - } +int AdjustedFocusRingOffset(int offset) { + // For FormControlsRefresh we just use the value of outline-offset so we don't + // need to call this method. + DCHECK(!::features::IsFormControlsRefreshEnabled()); #if defined(OS_MACOSX) return offset + 2; @@ -344,10 +343,10 @@ // only half of the width is outside of the offset. if (::features::IsFormControlsRefreshEnabled()) { // For FormControlsRefresh 2/3 of the width is outside of the offset. - return AdjustedFocusRingOffset(offset, width) + std::ceil(width / 3.f) * 2; + return offset + std::ceil(width / 3.f) * 2; } - return AdjustedFocusRingOffset(offset, width) + (width + 1) / 2; + return AdjustedFocusRingOffset(offset) + (width + 1) / 2; } void GraphicsContext::DrawFocusRingPath(const SkPath& path, @@ -394,9 +393,8 @@ SkRegion focus_ring_region; if (!::features::IsFormControlsRefreshEnabled()) { - // For FormControlsRefresh the offset is already adjusted by - // GraphicsContext::DrawFocusRing. - offset = AdjustedFocusRingOffset(offset, std::ceil(width)); + // For FormControlsRefresh we don't need to adjust the offset. + offset = AdjustedFocusRingOffset(offset); } for (unsigned i = 0; i < rect_count; i++) { SkIRect r = rects[i]; @@ -430,7 +428,6 @@ const float first_border_width = (width / 3) * 2; const float second_border_width = width - first_border_width; - offset = AdjustedFocusRingOffset(offset, std::ceil(width)); // How much space the focus ring would like to take from the actual border. const float inside_border_width = 1; if (min_border_width >= inside_border_width) {
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.cc b/third_party/blink/renderer/platform/graphics/graphics_layer.cc index 22e4bd8f..365eb7c 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.cc
@@ -180,11 +180,6 @@ #endif } -void GraphicsLayer::SetHasWillChangeTransformHint( - bool has_will_change_transform) { - CcLayer()->SetHasWillChangeTransformHint(has_will_change_transform); -} - void GraphicsLayer::SetParent(GraphicsLayer* layer) { #if DCHECK_IS_ON() DCHECK(!layer || !layer->HasAncestor(this));
diff --git a/third_party/blink/renderer/platform/graphics/graphics_layer.h b/third_party/blink/renderer/platform/graphics/graphics_layer.h index 710ce05..973734d 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_layer.h +++ b/third_party/blink/renderer/platform/graphics/graphics_layer.h
@@ -214,8 +214,6 @@ const cc::Layer&, JSONObject&) const override; - void SetHasWillChangeTransformHint(bool); - bool HasLayerState() const { return layer_state_.get(); } void SetLayerState(const PropertyTreeState&, const IntPoint& layer_offset); const PropertyTreeState& GetPropertyTreeState() const {
diff --git a/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc b/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc index 386766e..edcd2bb6 100644 --- a/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc +++ b/third_party/blink/renderer/platform/scheduler/common/scheduling_policy.cc
@@ -52,7 +52,6 @@ case Feature::kWebNfc: case Feature::kWebFileSystem: case Feature::kAppBanner: - case Feature::kPrinting: return true; } }
diff --git a/third_party/blink/renderer/platform/widget/frame_widget.h b/third_party/blink/renderer/platform/widget/frame_widget.h index fffcf36..01e5f8b 100644 --- a/third_party/blink/renderer/platform/widget/frame_widget.h +++ b/third_party/blink/renderer/platform/widget/frame_widget.h
@@ -5,6 +5,7 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_FRAME_WIDGET_H_ #define THIRD_PARTY_BLINK_RENDERER_PLATFORM_WIDGET_FRAME_WIDGET_H_ +#include "third_party/blink/public/mojom/manifest/display_mode.mojom-blink.h" #include "third_party/blink/public/web/web_swap_result.h" #include "third_party/blink/public/web/web_widget_client.h" #include "third_party/blink/renderer/platform/platform_export.h" @@ -74,6 +75,9 @@ cc::EventListenerProperties) = 0; virtual cc::EventListenerProperties EventListenerProperties( cc::EventListenerClass) const = 0; + + // Returns the DisplayMode in use for the widget. + virtual mojom::blink::DisplayMode DisplayMode() const = 0; }; } // namespace blink
diff --git a/third_party/blink/web_tests/FlagExpectations/composite-after-paint b/third_party/blink/web_tests/FlagExpectations/composite-after-paint index ca3f44b5..5b82b7c 100644 --- a/third_party/blink/web_tests/FlagExpectations/composite-after-paint +++ b/third_party/blink/web_tests/FlagExpectations/composite-after-paint
@@ -26,6 +26,11 @@ virtual/controls-refresh-hc/* [ Skip ] virtual/web-components-v0-disabled/* [ Skip ] +# They test Layer::ScrollsWithRespectTo() which is for pre-CompositeAfterPaint only. +compositing/overflow/scrolls-with-respect-to-nested.html [ Skip ] +compositing/overflow/scrolls-with-respect-to-transform.html [ Skip ] +compositing/overflow/scrolls-with-respect-to.html [ Skip ] + # Can't rebaseline because the file path is too long. virtual/compositor_threaded_scrollbar_scrolling/paint/invalidation/scroll/sticky/invalidate-after-composited-scroll-with-sticky.html [ Skip ] @@ -56,9 +61,6 @@ compositing/masks/broken-mask.html [ Failure ] compositing/masks/mask-with-removed-filters.html [ Failure ] -crbug.com/667946 compositing/overflow/scrolls-with-respect-to-nested.html [ Failure ] -crbug.com/667946 compositing/overflow/scrolls-with-respect-to-transform.html [ Failure ] -crbug.com/667946 compositing/overflow/scrolls-with-respect-to.html [ Failure ] external/wpt/css/css-transforms/transform3d-backface-visibility-006.html [ Failure ] external/wpt/portals/portals-rendering.html [ Failure ] fullscreen/compositor-touch-hit-rects-fullscreen-video-controls.html [ Failure ] @@ -78,11 +80,7 @@ # No composited scrolling for overflow:hidden (on marquee). compositing/overflow/do-not-repaint-if-scrolling-composited-layers.html [ Failure ] -# Extra layers for non-fast scrolling areas. -compositing/overflow/textarea-scroll-touch.html [ Failure ] - # Subpixel or invisible color differences that look benign, but we can't rebaseline ref tests. -compositing/overflow/ancestor-with-clip-path.html [ Failure ] fullscreen/rendering/backdrop-object.html [ Failure ] # Passes on bot, timeouts locally. @@ -103,9 +101,6 @@ # Outline paints incorrectly with columns. crbug.com/1047358 paint/pagination/composited-paginated-outlined-box.html [ Failure ] -# Crash on weird clip hierarchy in multiple columns -compositing/geometry/composited-in-columns.html [ Crash ] - # Ad frame highlight size is incorrect crbug.com/1047359 http/tests/subresource_filter/ad-highlight-frame-resized.html [ Failure ] @@ -121,7 +116,3 @@ compositing/gestures/gesture-tapHighlight-composited-img.html [ Pass Failure ] http/tests/images/image-decode-in-frame.html [ Pass Failure ] - -# TODO(iopopesc) these need to be rebaselined for FormControlsRefresh focus ring. -crbug.com/1035582 virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi.html [ Failure ] -crbug.com/1035582 compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents.html [ Failure ]
diff --git a/third_party/blink/web_tests/LeakExpectations b/third_party/blink/web_tests/LeakExpectations index 7f0bb48..f54b726d 100644 --- a/third_party/blink/web_tests/LeakExpectations +++ b/third_party/blink/web_tests/LeakExpectations
@@ -119,6 +119,7 @@ crbug.com/1038388 [ Linux ] http/tests/devtools/tracing/timeline-time/timeline-time.js [ Pass Failure ] # Sheriff 2020-04-03 +crbug.com/1067650 [ Linux ] http/tests/devtools/tracing/timeline-misc/timeline-load-event.js [ Pass Failure ] crbug.com/1067650 [ Linux ] virtual/threaded/http/tests/devtools/tracing/timeline-misc/timeline-load-event.js [ Pass Failure ] # Sheriff 2020-04-06
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 57de3c3..b8896fbc 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -274,7 +274,7 @@ # These appear to be actually incorrect at device_scale_factor 2.0: crbug.com/968791 crbug.com/1051044 virtual/scalefactor200/css3/filters/effect-reference-image-lazy-attach.html [ Failure ] -crbug.com/968791 crbug.com/1051044 virtual/scalefactor200/css3/filters/effect-reference-image.html [ Failure ] +crbug.com/968791 crbug.com/1051044 virtual/scalefactor200/external/wpt/css/filter-effects/effect-reference-feimage.html [ Failure ] crbug.com/968791 crbug.com/1051044 virtual/scalefactor200/css3/filters/effect-reference-image-hw.html [ Failure ] crbug.com/968791 virtual/scalefactor200/external/wpt/css/filter-effects/filters-test-brightness-003.html [ Failure ] @@ -2342,7 +2342,7 @@ crbug.com/377696 printing/setPrinting.html [ Failure ] -crbug.com/1051044 css3/filters/effect-reference-image.html [ Pass Failure ] +crbug.com/1051044 external/wpt/css/filter-effects/effect-reference-feimage.html [ Pass Failure ] crbug.com/1051044 css3/filters/effect-reference-image-lazy-attach.html [ Pass Failure ] crbug.com/524160 [ Debug ] http/tests/media/media-source/stream_memory_tests/mediasource-appendbuffer-quota-exceeded-default-buffers.html [ Timeout ] @@ -5141,7 +5141,7 @@ crbug.com/855816 [ Win ] virtual/stable/http/tests/navigation/rename-subframe-goback.html [ Pass Timeout ] # User Activation -crbug.com/736415 external/wpt/html/user-activation/navigation-state-reset-crossorigin.sub.tentative.html [ Failure ] +crbug.com/736415 external/wpt/html/user-activation/navigation-state-reset-crossorigin.sub.tentative.html [ Failure Timeout ] crbug.com/736415 external/wpt/html/user-activation/navigation-state-reset-sameorigin.tentative.html [ Failure ] # Sheriff 2018-07-05 @@ -6586,14 +6586,20 @@ # Sheriff 2020-03-27 crbug.com/1064839 fast/hidpi/image-srcset-svg-canvas.html [ Pass Failure ] crbug.com/1065335 [ Win ] fast/hidpi/image-srcset-relative-svg-canvas.html [ Pass Failure ] + # Sheriff 2020-03-31 crbug.com/1065335 [ Win ] fast/hidpi/image-srcset-relative-svg-canvas-2x.html [ Pass Failure ] # Sheriff 2020-04-01 crbug.com/1066122 virtual/threaded-no-composited-antialiasing/animations/events/animation-iteration-event.html [ Pass Failure ] crbug.com/1066732 fast/events/platform-wheelevent-paging-x-in-scrolling-div.html [ Pass Failure ] crbug.com/1066732 fast/events/platform-wheelevent-paging-y-in-scrolling-div.html [ Pass Failure ] + +# These tests will pass once the --enable-features=TrustTokens flag is on by default. +crbug.com/1061765 external/wpt/trust-tokens/end-to-end/* [ Skip ] + # Sheriff 2020-04-02 crbug.com/1067084 virtual/paint-timing/external/wpt/paint-timing/fcp-only/fcp-with-rtl.html [ Pass Failure ] + # Sheriff 2020-04-04 crbug.com/1067533 [ Mac10.10 ] external/wpt/shape-detection/idlharness.https.any.sharedworker.html [ Pass Failure ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 373b011..b732c40 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -738,5 +738,10 @@ "prefix": "web-bluetooth-new-permissions-backend", "bases": ["bluetooth", "external/wpt/bluetooth"], "args": ["--enable-features=WebBluetoothNewPermissionsBackend"] + }, + { + "prefix": "trust-tokens", + "bases": [ "external/wpt/trust-tokens/end-to-end" ], + "args": [ "--enable-features=TrustTokens" ] } ]
diff --git a/third_party/blink/web_tests/compositing/overflow/ancestor-with-clip-path-expected.html b/third_party/blink/web_tests/compositing/overflow/ancestor-with-clip-path-expected.html index a6d1b20..e7d45dd6 100644 --- a/third_party/blink/web_tests/compositing/overflow/ancestor-with-clip-path-expected.html +++ b/third_party/blink/web_tests/compositing/overflow/ancestor-with-clip-path-expected.html
@@ -1,6 +1,13 @@ <!DOCTYPE HTML> <style> +body { + margin: 0 +} + #scroller { + position: relative; + top: -150px; + left: -50px; overflow: scroll; height: 300px; width: 300px; @@ -8,10 +15,13 @@ } #outer { - height: 800px; + position: absolute; + top: 150px; + left: 50px; width: 250px; + height: 300px; + overflow: hidden; background-color: blue; - clip-path: polygon(40px 550px,432px 302px,409px 237px,46px 156px); } #scrolled { @@ -21,17 +31,17 @@ } #fixed { - position: fixed; + position: absolute; height: 100px; width: 100px; background-color: green; - top: 400px; - left: 100px; + top: 250px; + left: 50px; } </style> <div id="outer"> <div id="scroller"> <div id="scrolled"></div> - <div id="fixed"></div> </div> + <div id="fixed"></div> </div>
diff --git a/third_party/blink/web_tests/compositing/overflow/ancestor-with-clip-path.html b/third_party/blink/web_tests/compositing/overflow/ancestor-with-clip-path.html index 5f1995e..f6653ca 100644 --- a/third_party/blink/web_tests/compositing/overflow/ancestor-with-clip-path.html +++ b/third_party/blink/web_tests/compositing/overflow/ancestor-with-clip-path.html
@@ -1,6 +1,10 @@ <!DOCTYPE HTML> <script src="../../resources/run-after-layout-and-paint.js"></script> <style> +body { + margin: 0; +} + #scroller { overflow: scroll; height: 300px; @@ -9,8 +13,8 @@ } #outer { - height: 800px; - width: 250px; + height: 550px; + width: 300px; background-color: blue; } @@ -41,7 +45,7 @@ onload = function() { runAfterLayoutAndPaint(function() { - outer.style.clipPath = "polygon(40px 550px,432px 302px,409px 237px,46px 156px)"; + outer.style.clipPath = "polygon(50px 450px, 400px 450px, 400px 150px, 50px 150px)"; }, true); }; </script>
diff --git a/third_party/blink/web_tests/css3/filters/effect-reference-image-expected.html b/third_party/blink/web_tests/css3/filters/effect-reference-image-expected.html deleted file mode 100644 index f8ddbf1..0000000 --- a/third_party/blink/web_tests/css3/filters/effect-reference-image-expected.html +++ /dev/null
@@ -1 +0,0 @@ -<img src="resources/reference.png">
diff --git a/third_party/blink/web_tests/css3/filters/effect-reference-image.html b/third_party/blink/web_tests/css3/filters/effect-reference-image.html deleted file mode 100644 index 2d76dbf..0000000 --- a/third_party/blink/web_tests/css3/filters/effect-reference-image.html +++ /dev/null
@@ -1,13 +0,0 @@ -<style> - #filtered { - width: 160px; - height: 90px; - filter: url(#imagereplace); - } -</style> -<div id="filtered"></div> -<svg xmlns="http://www.w3.org/3000/svg" width="0" height="0" xmlns:xlink="http://www.w3.org/1999/xlink"> - <filter id="imagereplace" x="0%" y="0%" width="100%" height="100%"> - <feimage xlink:href="resources/reference.png"/> - </filter> -</svg>
diff --git a/third_party/blink/web_tests/css3/filters/effect-reference-obb-dimensions.html b/third_party/blink/web_tests/css3/filters/effect-reference-obb-dimensions.html deleted file mode 100644 index de0a07c..0000000 --- a/third_party/blink/web_tests/css3/filters/effect-reference-obb-dimensions.html +++ /dev/null
@@ -1,20 +0,0 @@ -<!DOCTYPE html> -<style> -body { - margin: 0; - padding: 0; -} -#target { - position: absolute; - width: 100px; - height: 100px; - background-color: green; - filter: url('#bboxOffset'); -} -</style> -<div id="target"></div> -<svg height="0"> - <filter id="bboxOffset" primitiveUnits="objectBoundingBox" x="0" y="0" width="1.25" height="1.25"> - <feOffset dx="0.2" dy="0.2"/> - </filter> -</svg>
diff --git a/third_party/blink/web_tests/css3/filters/effect-reference-on-span-crash-expected.txt b/third_party/blink/web_tests/css3/filters/effect-reference-on-span-crash-expected.txt deleted file mode 100644 index 524f271..0000000 --- a/third_party/blink/web_tests/css3/filters/effect-reference-on-span-crash-expected.txt +++ /dev/null
@@ -1 +0,0 @@ - This test passes by not crashing.
diff --git a/third_party/blink/web_tests/css3/filters/effect-reference-on-span-crash.html b/third_party/blink/web_tests/css3/filters/effect-reference-on-span-crash.html deleted file mode 100644 index ad9302c..0000000 --- a/third_party/blink/web_tests/css3/filters/effect-reference-on-span-crash.html +++ /dev/null
@@ -1,13 +0,0 @@ -<script> -if (window.testRunner) { - testRunner.dumpAsText(); -} -</script> -<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1"> - <defs> - <filter id="colormatrix" color-interpolation-filters="sRGB"> - <feColorMatrix type="hueRotate" values="180"/> - </filter> - </defs> -</svg> -<span style="background-color: green; filter: url(#colormatrix);">This test passes by not crashing.</span>
diff --git a/third_party/blink/web_tests/css3/filters/effect-reference-rename-2.html b/third_party/blink/web_tests/css3/filters/effect-reference-rename-2.html deleted file mode 100644 index 62cc52e..0000000 --- a/third_party/blink/web_tests/css3/filters/effect-reference-rename-2.html +++ /dev/null
@@ -1,13 +0,0 @@ -<!DOCTYPE html> -<script src="../../resources/run-after-layout-and-paint.js"></script> -<svg height="0"> - <filter id="NotMyFilter"> - <feColorMatrix type="hueRotate" values="90"/> - </filter> -</svg> -<div style="width: 100px; height: 100px; background-color: red; filter: url(#MyFilter);"></div> -<script> -runAfterLayoutAndPaint(function() { - document.getElementById("NotMyFilter").id = "MyFilter"; -}, true); -</script>
diff --git a/third_party/blink/web_tests/css3/filters/root-renderer-with-opacity-filter-expected.html b/third_party/blink/web_tests/css3/filters/root-renderer-with-opacity-filter-expected.html deleted file mode 100644 index 77723d8..0000000 --- a/third_party/blink/web_tests/css3/filters/root-renderer-with-opacity-filter-expected.html +++ /dev/null
@@ -1,4 +0,0 @@ -<!DOCTYPE html> -<html> -<body style="filter: opacity(0.501)"> -This test ensures we properly paint the root renderer when an opacity filter is applied.
diff --git a/third_party/blink/web_tests/css3/filters/root-renderer-with-opacity-filter.html b/third_party/blink/web_tests/css3/filters/root-renderer-with-opacity-filter.html deleted file mode 100644 index f05e5f8..0000000 --- a/third_party/blink/web_tests/css3/filters/root-renderer-with-opacity-filter.html +++ /dev/null
@@ -1,3 +0,0 @@ -<!DOCTYPE html> -<html style="filter: opacity(0.501)"> -This test ensures we properly paint the root renderer when an opacity filter is applied.
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json index 9d420c8e..822f820 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_7.json
@@ -108515,6 +108515,18 @@ {} ] ], + "css/filter-effects/effect-reference-delete.html": [ + [ + "css/filter-effects/effect-reference-delete.html", + [ + [ + "/css/filter-effects/reference/effect-reference-delete-ref.html", + "==" + ] + ], + {} + ] + ], "css/filter-effects/effect-reference-lighting-no-light.tentative.html": [ [ "css/filter-effects/effect-reference-lighting-no-light.tentative.html", @@ -108527,6 +108539,18 @@ {} ] ], + "css/filter-effects/effect-reference-merge-no-inputs.tentative.html": [ + [ + "css/filter-effects/effect-reference-merge-no-inputs.tentative.html", + [ + [ + "/css/filter-effects/reference/effect-reference-merge-no-inputs.tentative-ref.html", + "==" + ] + ], + {} + ] + ], "css/filter-effects/effect-reference-rename-001.html": [ [ "css/filter-effects/effect-reference-rename-001.html", @@ -108755,6 +108779,18 @@ {} ] ], + "css/filter-effects/filter-region-negative-positioned-child-001.html": [ + [ + "css/filter-effects/filter-region-negative-positioned-child-001.html", + [ + [ + "/css/filter-effects/reference/filter-region-negative-positioned-child-001-ref.html", + "==" + ] + ], + {} + ] + ], "css/filter-effects/filter-saturate-001-test.html": [ [ "css/filter-effects/filter-saturate-001-test.html", @@ -134942,6 +134978,9 @@ "common/reftest-wait.js.headers": [ [] ], + "common/rendering-utils.js": [ + [] + ], "common/sab.js": [ [] ], @@ -159950,15 +159989,24 @@ "css/filter-effects/reference/effect-reference-after-001-ref.html": [ [] ], + "css/filter-effects/reference/effect-reference-delete-ref.html": [ + [] + ], "css/filter-effects/reference/effect-reference-lighting-no-light.tentative-ref.html": [ [] ], + "css/filter-effects/reference/effect-reference-merge-no-inputs.tentative-ref.html": [ + [] + ], "css/filter-effects/reference/effect-reference-rename-001-ref.html": [ [] ], "css/filter-effects/reference/empty-element-with-filter-ref.html": [ [] ], + "css/filter-effects/reference/filter-region-negative-positioned-child-001-ref.html": [ + [] + ], "css/filter-effects/reference/filter-url-to-non-existent-filter-001-ref.html": [ [] ], @@ -353104,6 +353152,10 @@ "6805c323df5a975231648b830e33ce183c3cbbd3", "support" ], + "common/rendering-utils.js": [ + "46283bd5d078a14922e24160053017b6e8cb072c", + "support" + ], "common/sab.js": [ "c7fd1a742e64f66744b416584952effe29fda208", "support" @@ -441037,7 +441089,7 @@ "reftest" ], "css/filter-effects/background-image-blur-repaint.html": [ - "7b3df263081ecceb6517e056e60cfaa35b9981a0", + "4a3c00c7ad334a67312346ce57aa81ac96d024d2", "reftest" ], "css/filter-effects/blur-clip-stacking-context-001.html": [ @@ -441240,10 +441292,18 @@ "a6de2465027e99ff6239dd45524862465dde847f", "reftest" ], + "css/filter-effects/effect-reference-delete.html": [ + "314c9a7d123bd65b04483956513337116f7e0382", + "reftest" + ], "css/filter-effects/effect-reference-lighting-no-light.tentative.html": [ "beefd47a544d5c82b4b1d468ce99938e6d9924d9", "reftest" ], + "css/filter-effects/effect-reference-merge-no-inputs.tentative.html": [ + "4fb67db643dd5aebdbff53a0773035747c18836c", + "reftest" + ], "css/filter-effects/effect-reference-rename-001.html": [ "6c8374536f4cf748784b7a58fc158d230ea3557f", "reftest" @@ -441364,6 +441424,10 @@ "add64624b500d9688940834e76d63f4b0bb51489", "reftest" ], + "css/filter-effects/filter-region-negative-positioned-child-001.html": [ + "8f302ab52abe2f1008ca60d46fbc77d8ce35c22a", + "reftest" + ], "css/filter-effects/filter-saturate-001-ref.html": [ "4f654f9c554d1e2ab98960ec291419d44375c1ae", "support" @@ -441612,10 +441676,18 @@ "45192b13451fdfe2f00c17dbc84d30a770426e86", "support" ], + "css/filter-effects/reference/effect-reference-delete-ref.html": [ + "918715265fa4c1b95ec46d04014ea82e73cbcd40", + "support" + ], "css/filter-effects/reference/effect-reference-lighting-no-light.tentative-ref.html": [ "e863a6703b2acebbdb10a5eef342cbbd1b6b5bc9", "support" ], + "css/filter-effects/reference/effect-reference-merge-no-inputs.tentative-ref.html": [ + "5743e0c3de96ba4fbdf814bf5ec997e0c93e65da", + "support" + ], "css/filter-effects/reference/effect-reference-rename-001-ref.html": [ "fe3beae2d4997a7603153c5c885f01c7ca656bcd", "support" @@ -441624,6 +441696,10 @@ "cf2c997f6c0d60cac9896c0b0014189cea7790bc", "support" ], + "css/filter-effects/reference/filter-region-negative-positioned-child-001-ref.html": [ + "c9da47b1b434303f0111e8d1f03d5518e8f573fc", + "support" + ], "css/filter-effects/reference/filter-url-to-non-existent-filter-001-ref.html": [ "c1aeed8c441e6f72c6faa893d64ae30bdacbec06", "support" @@ -484713,7 +484789,7 @@ "support" ], "interfaces/css-typed-om.idl": [ - "df9669e5637f18de89792facba8fabe234d658f8", + "00d3f49bfe653ce4782e13e6c0d46c65783874cc", "support" ], "interfaces/cssom-view.idl": [ @@ -484937,7 +485013,7 @@ "support" ], "interfaces/permissions.idl": [ - "9cde372a127188ef1081ad390d5301d2d8b198f8", + "d45c7f93cac7683a76e89d0e7f429f5f3cb695d9", "support" ], "interfaces/picture-in-picture.idl": [ @@ -485165,7 +485241,7 @@ "support" ], "interfaces/worklets.idl": [ - "16187664b3b4124758c84d054b02b8ddbf585508", + "f89eacd50bd58c02860c84b6e4c486ab978a5018", "support" ], "interfaces/xhr.idl": [
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-feimage.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-feimage.html new file mode 100644 index 0000000..a1c3744 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-feimage.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<title>CSS Filters: feImage and CSS reference filters.</title> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#feImageElement"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty"> +<link rel="match" href="reference/effect-reference-feimage-ref.html"> +<meta name="assert" content="This test ensures that CSS reference filters supports feImage."/> +<style> + #filtered { + width: 160px; + height: 90px; + filter: url(#imagereplace); + } +</style> +<div id="filtered"></div> +<svg width="0" height="0"> + <filter id="imagereplace" x="0%" y="0%" width="100%" height="100%"> + <feimage xlink:href="support/color-palette.png"/> + </filter> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-obb-dimensions.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-obb-dimensions.html new file mode 100644 index 0000000..2bb424d9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-obb-dimensions.html
@@ -0,0 +1,28 @@ +<!DOCTYPE html> +<title>CSS Filters: objectBoundingBox type of primitiveUnits in SVG filters</title> +<link rel="author" title="Fredrik Söderquist" href="mailto:fs@opera.com"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects/#InterfaceSVGFilterElement"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects/#attr-valuedef-primitiveunits-objectboundingbox"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=532938"> +<link rel="match" href="reference/effect-reference-obb-dimensions-ref.html"> +<meta name="assert" content="Check that primitiveUnits of type objectBoundingBox get properly applied in SVG filter primitives."/> + +<style> +body { + margin: 0; + padding: 0; +} +#target { + position: absolute; + width: 100px; + height: 100px; + background-color: green; + filter: url('#bboxOffset'); +} +</style> +<div id="target"></div> +<svg height="0"> + <filter id="bboxOffset" primitiveUnits="objectBoundingBox" x="0" y="0" width="1.25" height="1.25"> + <feOffset dx="0.2" dy="0.2"/> + </filter> +</svg>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-on-span.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-on-span.html new file mode 100644 index 0000000..66bd8fa88 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-on-span.html
@@ -0,0 +1,19 @@ +<!DOCTYPE html> +<html> +<title>CSS Filters: filters on <span> elements</title> +<link rel="author" title="Stephen White" href="mailto:senorblanco@chromium.org"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=513408"> +<link rel="match" href="reference/effect-reference-on-span-ref.html"> +<meta name="assert" content="Check that a CSS filter to a <span> element works as expected."/> + +<body> +<svg xmlns="http://www.w3.org/2000/svg" width="0" height="0" version="1.1"> + <defs> + <filter id="colormatrix" color-interpolation-filters="sRGB"> + <feColorMatrix values="0 0 0 0 0, 0 0 0 0 0, 1 0 0 0 0, 0 0 0 1 0"/> + </filter> + </defs> +</svg><span style="background-color: red; filter: url(#colormatrix);">This text's background should be blue.</span> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-rename-002.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-rename-002.html new file mode 100644 index 0000000..8652881 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/effect-reference-rename-002.html
@@ -0,0 +1,27 @@ +<!DOCTYPE html> +<html class="reftest-wait"> +<title>CSS Filters: reference to renamed SVG filter</title> +<link rel="author" title="Fredrik Söderquist" href="mailto:fs@opera.com"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects-1/#FilterProperty"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=453019"> +<link rel="match" href="reference/effect-reference-rename-002-ref.html"> +<meta name="assert" content="Check that a SVG filter, initially named differently than what an element expects, gets applied to such element once renamed, after rendering the first frame."/> + +<script src="/common/reftest-wait.js"></script> +<script src="/common/rendering-utils.js"></script> + +<body> +<svg height="0"> + <filter id="NotMyFilter"> + <feColorMatrix type="hueRotate" values="90"/> + </filter> +</svg> +<div style="width: 100px; height: 100px; background-color: red; filter: url(#MyFilter);"></div> +<script> +waitForAtLeastOneFrame().then(function() { + document.getElementById("NotMyFilter").id = "MyFilter"; + takeScreenshot(); +}); +</script> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-feimage-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-feimage-ref.html new file mode 100644 index 0000000..9b982b3c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-feimage-ref.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<img src="../support/color-palette.png">
diff --git a/third_party/blink/web_tests/css3/filters/effect-reference-obb-dimensions-expected.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-obb-dimensions-ref.html similarity index 100% rename from third_party/blink/web_tests/css3/filters/effect-reference-obb-dimensions-expected.html rename to third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-obb-dimensions-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-on-span-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-on-span-ref.html new file mode 100644 index 0000000..76a7953 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-on-span-ref.html
@@ -0,0 +1,5 @@ +<html> +<body> +<span style="background-color: blue;">This text's background should be blue.</span> +</body> +</html>
diff --git a/third_party/blink/web_tests/css3/filters/effect-reference-rename-2-expected.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-rename-002-ref.html similarity index 100% rename from third_party/blink/web_tests/css3/filters/effect-reference-rename-2-expected.html rename to third_party/blink/web_tests/external/wpt/css/filter-effects/reference/effect-reference-rename-002-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/root-element-with-opacity-filter-001-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/root-element-with-opacity-filter-001-ref.html new file mode 100644 index 0000000..cd16e54c --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/reference/root-element-with-opacity-filter-001-ref.html
@@ -0,0 +1,4 @@ +<!DOCTYPE html> +<html> +<body style="filter: opacity(0.501)"> +This test ensures we properly paint the root element when an opacity filter is applied.
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/root-element-with-opacity-filter-001.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/root-element-with-opacity-filter-001.html new file mode 100644 index 0000000..577e2bd4 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/root-element-with-opacity-filter-001.html
@@ -0,0 +1,9 @@ +<!DOCTYPE html> +<title>Opacity Filter: root element opacity filter</title> +<link rel="help" href="https://drafts.fxtf.org/filter-effects/#FilterProperty"> +<link rel="help" href="https://drafts.fxtf.org/filter-effects/#funcdef-filter-opacity"> +<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=349587"> +<link rel="match" href="reference/root-element-with-opacity-filter-001-ref.html"> +<meta name="assert" content="This test ensures that the root renderer has an opacity filter"/> +<html style="filter: opacity(0.501)"> +This test ensures we properly paint the root element when an opacity filter is applied.
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/css-typed-om.idl b/third_party/blink/web_tests/external/wpt/interfaces/css-typed-om.idl index df9669e..00d3f49 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/css-typed-om.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/css-typed-om.idl
@@ -41,9 +41,9 @@ [SameObject] readonly attribute StylePropertyMap attributeStyleMap; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(sequence<CSSUnparsedSegment> members)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSUnparsedValue : CSSStyleValue { + constructor(sequence<CSSUnparsedSegment> members); iterable<CSSUnparsedSegment>; readonly attribute unsigned long length; getter CSSUnparsedSegment (unsigned long index); @@ -52,16 +52,16 @@ typedef (USVString or CSSVariableReferenceValue) CSSUnparsedSegment; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(USVString variable, optional CSSUnparsedValue? fallback = null)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSVariableReferenceValue { + constructor(USVString variable, optional CSSUnparsedValue? fallback = null); attribute USVString variable; readonly attribute CSSUnparsedValue? fallback; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(USVString value)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSKeywordValue : CSSStyleValue { + constructor(USVString value); attribute USVString value; }; @@ -108,9 +108,9 @@ [Exposed=Window] static CSSNumericValue parse(USVString cssText); }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(double value, USVString unit)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSUnitValue : CSSNumericValue { + constructor(double value, USVString unit); attribute double value; readonly attribute USVString unit; }; @@ -120,45 +120,45 @@ readonly attribute CSSMathOperator operator; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumberish... args)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSMathSum : CSSMathValue { + constructor(CSSNumberish... args); readonly attribute CSSNumericArray values; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumberish... args)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSMathProduct : CSSMathValue { + constructor(CSSNumberish... args); readonly attribute CSSNumericArray values; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumberish arg)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSMathNegate : CSSMathValue { + constructor(CSSNumberish arg); readonly attribute CSSNumericValue value; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumberish arg)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSMathInvert : CSSMathValue { + constructor(CSSNumberish arg); readonly attribute CSSNumericValue value; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumberish... args)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSMathMin : CSSMathValue { + constructor(CSSNumberish... args); readonly attribute CSSNumericArray values; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumberish... args)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSMathMax : CSSMathValue { + constructor(CSSNumberish... args); readonly attribute CSSNumericArray values; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumberish min, CSSNumberish val, CSSNumberish max)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSMathClamp : CSSMathValue { + constructor(CSSNumberish min, CSSNumberish val, CSSNumberish max); readonly attribute CSSNumericValue min; readonly attribute CSSNumericValue val; readonly attribute CSSNumericValue max; @@ -230,9 +230,9 @@ CSSUnitValue fr(double value); }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(sequence<CSSTransformComponent> transforms)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSTransformValue : CSSStyleValue { + constructor(sequence<CSSTransformComponent> transforms); iterable<CSSTransformComponent>; readonly attribute unsigned long length; getter CSSTransformComponent (unsigned long index); @@ -249,63 +249,63 @@ DOMMatrix toMatrix(); }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumericValue x, CSSNumericValue y, optional CSSNumericValue z)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSTranslate : CSSTransformComponent { + constructor(CSSNumericValue x, CSSNumericValue y, optional CSSNumericValue z); attribute CSSNumericValue x; attribute CSSNumericValue y; attribute CSSNumericValue z; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumericValue angle), - Constructor(CSSNumberish x, CSSNumberish y, CSSNumberish z, CSSNumericValue angle)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSRotate : CSSTransformComponent { + constructor(CSSNumericValue angle); + constructor(CSSNumberish x, CSSNumberish y, CSSNumberish z, CSSNumericValue angle); attribute CSSNumberish x; attribute CSSNumberish y; attribute CSSNumberish z; attribute CSSNumericValue angle; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumberish x, CSSNumberish y, optional CSSNumberish z)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSScale : CSSTransformComponent { + constructor(CSSNumberish x, CSSNumberish y, optional CSSNumberish z); attribute CSSNumberish x; attribute CSSNumberish y; attribute CSSNumberish z; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumericValue ax, CSSNumericValue ay)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSSkew : CSSTransformComponent { + constructor(CSSNumericValue ax, CSSNumericValue ay); attribute CSSNumericValue ax; attribute CSSNumericValue ay; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumericValue ax)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSSkewX : CSSTransformComponent { + constructor(CSSNumericValue ax); attribute CSSNumericValue ax; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumericValue ay)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSSkewY : CSSTransformComponent { + constructor(CSSNumericValue ay); attribute CSSNumericValue ay; }; /* Note that skew(x,y) is *not* the same as skewX(x) skewY(y), thus the separate interfaces for all three. */ -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(CSSNumericValue length)] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSPerspective : CSSTransformComponent { + constructor(CSSNumericValue length); attribute CSSNumericValue length; }; -[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet), - Constructor(DOMMatrixReadOnly matrix, optional CSSMatrixComponentOptions options = {})] +[Exposed=(Window, Worker, PaintWorklet, LayoutWorklet)] interface CSSMatrixComponent : CSSTransformComponent { + constructor(DOMMatrixReadOnly matrix, optional CSSMatrixComponentOptions options = {}); attribute DOMMatrix matrix; };
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/permissions.idl b/third_party/blink/web_tests/external/wpt/interfaces/permissions.idl index 9cde372a..d45c7f9 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/permissions.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/permissions.idl
@@ -46,6 +46,10 @@ DOMString deviceId; }; +dictionary CameraDevicePermissionDescriptor : DevicePermissionDescriptor { + boolean panTiltZoom = false; +}; + dictionary PermissionSetParameters { required PermissionDescriptor descriptor; required PermissionState state;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/worklets.idl b/third_party/blink/web_tests/external/wpt/interfaces/worklets.idl index 1618766..f89eacd5 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/worklets.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/worklets.idl
@@ -9,7 +9,7 @@ [Exposed=Window] interface Worklet { - [NewObject] Promise<void> addModule(USVString moduleURL, optional WorkletOptions options); + [NewObject] Promise<void> addModule(USVString moduleURL, optional WorkletOptions options = {}); }; dictionary WorkletOptions {
diff --git a/third_party/blink/web_tests/external/wpt/trust-tokens/end-to-end/README.txt b/third_party/blink/web_tests/external/wpt/trust-tokens/end-to-end/README.txt new file mode 100644 index 0000000..a86468d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/trust-tokens/end-to-end/README.txt
@@ -0,0 +1,4 @@ +These tests confirm that Trust Tokens protocol operations executed correctly end +to end (in contrast to just checking, as the parent directory's +trust-token-parameter-validation does, that a method's interface is present and +correctly rejects invalid arguments).
diff --git a/third_party/blink/web_tests/external/wpt/trust-tokens/end-to-end/has-trust-token-with-no-top-frame.tentative.https.html b/third_party/blink/web_tests/external/wpt/trust-tokens/end-to-end/has-trust-token-with-no-top-frame.tentative.https.html new file mode 100644 index 0000000..4788cd990 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/trust-tokens/end-to-end/has-trust-token-with-no-top-frame.tentative.https.html
@@ -0,0 +1,22 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Tests the Trust Token API's hasTrustToken behavior in documents with no top frame</title> +<link rel="help" href="https://github.com/WICG/trust-token-api" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> + <script> + 'use strict'; + + const frame = document.createElement('iframe'); + document.body.appendChild(frame); + const cachedDocument = window[0].document; + frame.remove(); + + test(() => { + assert_equals(cachedDocument.hasTrustToken("https://issuer.example"), undefined, + "Can't construct a Promise in a destroyed execution context."); + }, 'hasTrustToken in a destroyed document.'); + </script> +</body>
diff --git a/third_party/blink/web_tests/external/wpt/trust-tokens/end-to-end/has-trust-token.tentative.https.html b/third_party/blink/web_tests/external/wpt/trust-tokens/end-to-end/has-trust-token.tentative.https.html new file mode 100644 index 0000000..17e037f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/trust-tokens/end-to-end/has-trust-token.tentative.https.html
@@ -0,0 +1,58 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>Tests the Trust Token API's hasTrustToken function (tentative: the API is a prototype).</title> +<link rel="help" href="https://github.com/WICG/trust-token-api#trust-token-redemption" /> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> + 'use strict'; + + promise_test((t) => { + return promise_rejects_js(t, TypeError, document.hasTrustToken( + "http://not-a-secure-url.example")); + }, + 'hasTrustToken requires a secure URL as its issuer argument.'); + + promise_test((t) => { + return promise_rejects_js(t, TypeError, document.hasTrustToken( + "file:///")); + }, + 'hasTrustToken requires a HTTP(S) URL as its issuer argument.'); + + // These hasTrustToken calls all affect global state: each call in the form + // of hasTrustToken(issuer) will result in |issuer| becoming associated in + // persistent storage with the calling top frame's origin. + // + // TODO(davidvc, crbug.com/1061764): Add a way to reset the global state after + // the test concludes. + // + // TODO(davidvc, crbug.com/1063140): Once it's possible to write WPTs that + // result in a trust token being deposited in storage, this should be + // expanded to cover the case where the user _does_ have a token. + promise_test(async (t) => { + let result = await document.hasTrustToken("https://issuer.example/"); + assert_false(result, "The client should not possess any trust tokens for " + + "https://issuer.example since it has not executed an issuance operation" + + " against that issuer."); + + result = await document.hasTrustToken("https://issuer2.example/"); + assert_false(result, "The client should not possess any trust tokens for" + + " https://issuer2.example since it has not executed an issuance " + + "operation against that issuer."); + + await promise_rejects_dom(t, "OperationError", document.hasTrustToken( + "https://issuer3.example/"), + "The first two hasTrustToken operations associated this top-level" + + " origin with the maximum number of issuers (2), so an attempt to " + + " execute hasTrustToken against another issuer should fail."); + + result = await document.hasTrustToken("https://issuer2.example/"); + assert_false(result, "Since this top-level origin is already associated " + + "with https://issuer2.example, subsequent hasTrustToken operations should " + + "not error out even though the top-level origin is at its " + + "number-of-issuers limit."); + }, "When given a valid, secure origin, hasTrustToken should succeed " + + "unless associating that origin with the top-level domain would exceed " + + "the top-level origin's number-of-associated-issuers limit."); +</script>
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents-expected.png b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents-expected.png new file mode 100644 index 0000000..f8c749d --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/do-not-paint-outline-into-composited-scrolling-contents-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/textarea-scroll-touch-expected.txt b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/textarea-scroll-touch-expected.txt new file mode 100644 index 0000000..bb824aa --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/composite-after-paint/compositing/overflow/textarea-scroll-touch-expected.txt
@@ -0,0 +1,103 @@ + +{ + "layers": [ + { + "name": "Scrolling background of LayoutView #document", + "bounds": [800, 600], + "contentsOpaque": true, + "backgroundColor": "#FFFFFF" + }, + { + "name": "LayoutTextControl TEXTAREA", + "position": [1, 1], + "bounds": [189, 124], + "drawsContent": false, + "transform": 1 + }, + { + "name": "Scroll corner of LayoutTextControl TEXTAREA", + "position": [193, 18], + "bounds": [261, 126] + }, + { + "name": "LayoutTextControl TEXTAREA", + "position": [1, 1], + "bounds": [189, 328], + "backgroundColor": "#CCCCCC", + "transform": 2 + }, + { + "name": "VerticalScrollbar", + "position": [190, 1], + "bounds": [15, 109], + "transform": 1 + }, + { + "name": "LayoutTextControl TEXTAREA", + "position": [1, 1], + "bounds": [189, 124], + "drawsContent": false, + "transform": 3 + }, + { + "name": "Scroll corner of LayoutTextControl TEXTAREA", + "position": [175, 95], + "bounds": [30, 30], + "transform": 3 + }, + { + "name": "LayoutTextControl TEXTAREA", + "position": [1, 1], + "bounds": [189, 328], + "backgroundColor": "#CCCCCC", + "transform": 4 + }, + { + "name": "VerticalScrollbar", + "position": [190, 1], + "bounds": [15, 109], + "transform": 3 + } + ], + "transforms": [ + { + "id": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [18, 18, 0, 1] + ] + }, + { + "id": 2, + "parent": 1, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, -50, 0, 1] + ] + }, + { + "id": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [248, 18, 0, 1] + ] + }, + { + "id": 4, + "parent": 3, + "transform": [ + [1, 0, 0, 0], + [0, 1, 0, 0], + [0, 0, 1, 0], + [0, -50, 0, 1] + ] + } + ] +} +
diff --git a/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png b/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png deleted file mode 100644 index a19bae81..0000000 --- a/third_party/blink/web_tests/flag-specific/composite-after-paint/virtual/scalefactor200withzoom/fast/hidpi/static/validation-bubble-appearance-hidpi-expected.png +++ /dev/null Binary files differ
diff --git a/third_party/blink/web_tests/virtual/trust-tokens/external/wpt/trust-tokens/end-to-end/README.txt b/third_party/blink/web_tests/virtual/trust-tokens/external/wpt/trust-tokens/end-to-end/README.txt new file mode 100644 index 0000000..c981686 --- /dev/null +++ b/third_party/blink/web_tests/virtual/trust-tokens/external/wpt/trust-tokens/end-to-end/README.txt
@@ -0,0 +1,3 @@ +Enable the network service side of the Trust Token API +(https://github.com/wicg/trust-token-api) with --enable-features=TrustTokens in +order to test API calls end to end.
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 f517567..3d1692e 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
@@ -1768,6 +1768,7 @@ method getSelection method hasFocus method hasStorageAccess + method hasTrustToken method importNode method open method prepend
diff --git a/tools/binary_size/find_large_commits.py b/tools/binary_size/find_large_commits.py index 58d0b16..59438c8 100755 --- a/tools/binary_size/find_large_commits.py +++ b/tools/binary_size/find_large_commits.py
@@ -34,15 +34,17 @@ def _LookupCommitInfo(rev): - sha1 = subprocess.check_output(['git', 'crrev-parse', str(rev)]).strip() - desc = subprocess.check_output(['git', 'log', '-n1', sha1]) + sha1 = subprocess.check_output( + ['git', 'crrev-parse', str(rev)], encoding="utf-8").strip() + desc = subprocess.check_output(['git', 'log', '-n1', sha1], encoding="utf-8") author = re.search(r'Author: .*?<(.*?)>', desc).group(1) day, year = re.search(r'Date:\s+\w+\s+(\w+ \d+)\s+.*?\s+(\d+)', desc).groups() date = '{} {}'.format(day, year) title = re.search(r'\n +(\S.*)', desc).group(1).replace('\t', ' ') milestone = None if 'Roll AFDO' not in title: - releases = subprocess.check_output(['git', 'find-releases', sha1]) + releases = subprocess.check_output(['git', 'find-releases', sha1], + encoding="utf-8") version = re.search('initially in (\d\d)', releases) milestone = '' if version:
diff --git a/tools/binary_size/generate_milestone_reports.py b/tools/binary_size/generate_milestone_reports.py index fd98e1f..61c81da 100755 --- a/tools/binary_size/generate_milestone_reports.py +++ b/tools/binary_size/generate_milestone_reports.py
@@ -139,7 +139,6 @@ temp_dir = tempfile.mkdtemp() try: subpaths = set(x.size_file_subpath for x in reports) - logging.warning('Downloading %d .size files', len(subpaths)) arg_tuples = ((p, temp_dir, base_url) for p in subpaths) for _ in _Shard(_DownloadOneSizeFile, arg_tuples): pass @@ -178,8 +177,6 @@ def main(): parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( - 'directory', help='Directory to save report files to (must not exist).') - parser.add_argument( '--size-file-bucket', required=True, help='GCS bucket to find size files in. (e.g. "gs://bucket/subdir")') @@ -187,58 +184,36 @@ '--sync', action='store_true', help='Sync data files to GCS (otherwise just prints out command to run).') - parser.add_argument( - '--skip-existing', - action='store_true', - help='Used to control skipping existing reports, now does nothing.') - args = parser.parse_args() size_file_bucket = args.size_file_bucket.rstrip('/') if not size_file_bucket.startswith('gs://'): parser.error('Size file bucket must start with gs://') - _MakeDirectory(args.directory) - if os.listdir(args.directory): - parser.error('Directory must be empty') - reports_to_make = set(_EnumerateReports()) + logging.warning('Downloading %d size files.', len(reports_to_make)) with _DownloadSizeFiles(args.size_file_bucket, reports_to_make) as sizes_dir: - logging.warning('Downloading %d size files.', len(reports_to_make)) - for i, r in enumerate(reports_to_make): - _BuildOneReport(r, args.directory, sizes_dir) - sys.stdout.write('\rGenerated {} of {}'.format(i + 1, - len(reports_to_make))) - sys.stdout.flush() - sys.stdout.write('\n') + staging_dir = os.path.join(sizes_dir, 'staging') + _MakeDirectory(staging_dir) - _WriteMilestonesJson(os.path.join(args.directory, 'milestones.json')) + for r in reports_to_make: + _BuildOneReport(r, staging_dir, sizes_dir) - logging.warning('Reports saved to %s', args.directory) - cmd = [ - _GSUTIL, - '-m', - 'rsync', - '-J', - '-a', - 'public-read', - '-r', - args.directory, - _PUSH_URL, - ] + _WriteMilestonesJson(os.path.join(staging_dir, 'milestones.json')) - if args.sync: - subprocess.check_call(cmd) - subprocess.check_call([ - _GSUTIL, 'setmeta', '-h', 'Cache-Control:no-cache', - _PUSH_URL + 'milestones.json' - ]) - else: - print() - print('Sync files by running:') - print(' ', ' '.join(cmd)) + if args.sync: + subprocess.check_call([ + _GSUTIL, '-m', 'rsync', '-J', '-a', 'public-read', '-r', staging_dir, + _PUSH_URL + ]) + subprocess.check_call([ + _GSUTIL, 'setmeta', '-h', 'Cache-Control:no-cache', + _PUSH_URL + 'milestones.json' + ]) + else: + logging.warning('Finished dry run. Run with --sync to upload.') if __name__ == '__main__':
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a5c46ff..7d33689 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -20326,6 +20326,17 @@ <int value="3" label="NON_ERROR_PAGE_URL_AND_NO_ERROR_INFO"/> </enum> +<enum name="EulaScreenUserAction"> + <summary>Actions which happen on the screen.</summary> + <int value="0" label="Accept button clicked"/> + <int value="1" label="Back button clicked"/> + <int value="2" label="Additional ToS shown"/> + <int value="3" label="Security settings shown"/> + <int value="4" label="Learn more about usage stats shown"/> + <int value="5" label="Stats usage unselected"/> + <int value="6" label="Stats usage selected"/> +</enum> + <enum name="EVCTCompliance"> <obsolete> Deprecated 06/2017. @@ -26913,6 +26924,7 @@ <int value="3199" label="CrossOriginEmbedderPolicyRequireCorp"/> <int value="3200" label="CoopAndCoepIsolated"/> <int value="3201" label="WrongBaselineOfButtonElement"/> + <int value="3202" label="V8Document_HasTrustToken_Method"/> </enum> <enum name="FeaturePolicyAllowlistType"> @@ -69268,7 +69280,6 @@ <int value="40" label="OutstandingNetworkRequestFetch"/> <int value="41" label="OutstandingNetworkRequestXHR"/> <int value="42" label="AppBanner"/> - <int value="43" label="Printing"/> </enum> <enum name="WebShareMethod"> @@ -69298,6 +69309,8 @@ <int value="8" label="Connection help opened"/> <int value="9" label="Site settings opened"/> <int value="10" label="Security details opened"/> + <int value="11" label="Third-party cookies allowed for site"/> + <int value="12" label="Third-party cookies blocked for site"/> </enum> <enum name="WebSiteSettingsAllSitesAction">
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index c3220515..680d444 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -43063,6 +43063,10 @@ <histogram name="Download.Start.ContentType.InsecureChain" enum="DownloadContentType" expires_after="2020-09-06"> + <obsolete> + Removed in 04/2020. Superseded by mixed download metrics under + Download.InsecureBlocking. + </obsolete> <owner>cthomp@chromium.org</owner> <owner>estark@chromium.org</owner> <summary> @@ -43086,6 +43090,10 @@ <histogram name="Download.Start.ContentType.SecureChain" enum="DownloadContentType" expires_after="2020-05-03"> + <obsolete> + Removed in 04/2020. Superseded by mixed download metrics under + Download.InsecureBlocking. + </obsolete> <owner>cthomp@chromium.org</owner> <owner>estark@chromium.org</owner> <summary> @@ -79240,7 +79248,7 @@ expires_after="2020-08-09"> <!-- Name completed by a combination of the following two histogram_suffixes: --> -<!-- histogram_suffixes name="GPU.PeakMemoryUsage" --> +<!-- histogram_suffixes name="GPU.PeakMemoryAllocationSourceBase" --> <!-- and histogram_suffixes name="GPU.PeakMemoryAllocationSource" --> @@ -108837,6 +108845,13 @@ <summary>Time spent on error screens during update.</summary> </histogram> +<histogram name="OOBE.EulaScreen.UserActions" enum="EulaScreenUserAction" + expires_after="2021-02-02"> + <owner>raleksandrov@google.com</owner> + <owner>cros-oac@google.com</owner> + <summary>Counts all user actions on the EulaScreen.</summary> +</histogram> + <histogram name="OOBE.EULAToSignInTime" units="ms" expires_after="never"> <!-- expires-never: Core metric for monitoring initial Gaia loading regressions. --> @@ -135530,6 +135545,9 @@ <histogram name="ResourceReporter.BrowserProcess.CpuUsage" enum="ResourceReporterCpuUsage" expires_after="M85"> + <obsolete> + Removed 04/2020. + </obsolete> <owner>afakhry@chromium.org</owner> <summary> The CPU usage range reported for the browser process when the Chrome OS @@ -135541,6 +135559,9 @@ <histogram name="ResourceReporter.BrowserProcess.MemoryUsage" enum="ResourceReporterMemoryUsage" expires_after="M85"> + <obsolete> + Removed 04/2020. + </obsolete> <owner>afakhry@chromium.org</owner> <summary> The system memory usage range reported for the browser process when the @@ -135552,6 +135573,9 @@ <histogram name="ResourceReporter.GpuProcess.CpuUsage" enum="ResourceReporterCpuUsage" expires_after="M85"> + <obsolete> + Removed 04/2020. + </obsolete> <owner>afakhry@chromium.org</owner> <summary> The CPU usage range reported for the GPU process when the Chrome OS device @@ -135563,6 +135587,9 @@ <histogram name="ResourceReporter.GpuProcess.MemoryUsage" enum="ResourceReporterMemoryUsage" expires_after="M85"> + <obsolete> + Removed 04/2020. + </obsolete> <owner>afakhry@chromium.org</owner> <summary> The system's RAM memory usage range reported for the GPU process when the @@ -151706,7 +151733,10 @@ </histogram> <histogram name="Signin.OAuthMultiloginResponseStatus" - enum="OAuthMultiloginResponseStatus" expires_after="2020-04-19"> + enum="OAuthMultiloginResponseStatus" expires_after="never"> +<!-- expires-never: This reports the status received from gaia Multilogin and +should be kept to monitor/debug signin Multilogin issues--> + <owner>droger@chromium.org</owner> <owner>msarda@chromium.org</owner> <summary>Response status received from gaia Multilogin.</summary> @@ -182347,8 +182377,9 @@ </histogram> <histogram name="WebsiteSettings.Action" enum="WebsiteSettingsAction" - expires_after="M81"> + expires_after="M87"> <owner>estark@chromium.org</owner> + <owner>dullweber@chromium.org</owner> <summary> Tracks actions with the website setting (a.k.a. page info / origin info) bubble, such as opening it up or clicking on the Connection tab. @@ -189939,13 +189970,20 @@ <affected-histogram name="Memory.GPU.PeakMemoryAllocationSource.Scroll"/> </histogram_suffixes> -<histogram_suffixes name="GPU.PeakMemoryUsage" separator="."> +<histogram_suffixes name="GPU.PeakMemoryAllocationSourcesBase" separator="."> <suffix base="true" name="ChangeTab" label="Changing Tabs."/> <suffix base="true" name="PageLoad" label="Page Load."/> <suffix base="true" name="Scroll" label="Scroll."/> <affected-histogram name="Memory.GPU.PeakMemoryAllocationSource"/> </histogram_suffixes> +<histogram_suffixes name="GPU.PeakMemoryUsage" separator="."> + <suffix name="ChangeTab" label="Changing Tabs."/> + <suffix name="PageLoad" label="Page Load."/> + <suffix name="Scroll" label="Scroll."/> + <affected-histogram name="Memory.GPU.PeakMemoryUsage"/> +</histogram_suffixes> + <histogram_suffixes name="GPU.ProtectedVideoType" separator="."> <suffix name="Clear" label="Clear"/> <suffix name="HardwareProtected" label="HardwareProtected"/>
diff --git a/tools/metrics/rappor/rappor.xml b/tools/metrics/rappor/rappor.xml index c7b03f7..2f0e0127 100644 --- a/tools/metrics/rappor/rappor.xml +++ b/tools/metrics/rappor/rappor.xml
@@ -161,6 +161,9 @@ </rappor-metric> <rappor-metric name="ResourceReporter.Cpu" type="UMA_RAPPOR_TYPE"> + <obsolete> + Removed 04/2020. + </obsolete> <owner>afakhry@chromium.org</owner> <summary> A Chrome task, its process priority, and its CPU usage range. @@ -200,6 +203,9 @@ </rappor-metric> <rappor-metric name="ResourceReporter.Memory" type="UMA_RAPPOR_TYPE"> + <obsolete> + Removed 04/2020. + </obsolete> <owner>afakhry@chromium.org</owner> <summary> A Chrome task, and its memory usage range.
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index 2039dbe5..669a42a1 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -456,12 +456,26 @@ ] } +android_library("clipboard_java_test_support") { + testonly = true + annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] + + sources = + [ "javatests/src/org/chromium/ui/base/ClipboardAndroidTestSupport.java" ] + + deps = [ + "//base:base_java", + "//base:base_java_test_support", + ] +} + android_library("ui_javatests") { testonly = true sources = [ "javatests/src/org/chromium/ui/base/ClipboardAndroidTest.java" ] deps = [ + ":clipboard_java_test_support", ":ui_java", ":ui_java_test_support", "//base:base_java", @@ -470,12 +484,11 @@ "//content/public/test/android:content_java_test_support", "//third_party/junit", ] - - annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] } generate_jni("ui_javatest_jni_headers") { testonly = true - sources = [ "javatests/src/org/chromium/ui/base/ClipboardAndroidTest.java" ] + sources = + [ "javatests/src/org/chromium/ui/base/ClipboardAndroidTestSupport.java" ] }
diff --git a/ui/android/javatests/src/org/chromium/ui/base/ClipboardAndroidTest.java b/ui/android/javatests/src/org/chromium/ui/base/ClipboardAndroidTest.java index 1567e248..e5450a5 100644 --- a/ui/android/javatests/src/org/chromium/ui/base/ClipboardAndroidTest.java +++ b/ui/android/javatests/src/org/chromium/ui/base/ClipboardAndroidTest.java
@@ -14,10 +14,7 @@ import org.junit.Test; import org.junit.runner.RunWith; -import org.chromium.base.annotations.JNINamespace; -import org.chromium.base.annotations.NativeMethods; import org.chromium.base.test.BaseJUnit4ClassRunner; -import org.chromium.base.test.util.DisabledTest; import org.chromium.content_public.browser.test.NativeLibraryTestRule; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.TestThreadUtils; @@ -26,7 +23,6 @@ /** * Clipboard tests for Android platform that depend on access to the ClipboardManager. */ -@JNINamespace("ui") @RunWith(BaseJUnit4ClassRunner.class) public class ClipboardAndroidTest extends DummyUiActivityTestCase { @Rule @@ -40,7 +36,8 @@ @Override public void tearDownTest() throws Exception { - ClipboardAndroidTestJni.get().cleanup(); + ClipboardAndroidTestSupport.cleanup(); + super.tearDownTest(); } /** @@ -49,7 +46,6 @@ */ @Test @SmallTest - @DisabledTest(message = "https://crbug.com/1067719") public void internalClipboardInvalidation() { CriteriaHelper.pollUiThread(() -> getActivity().hasWindowFocus()); @@ -57,7 +53,7 @@ final String originalText = "foo"; TestThreadUtils.runOnUiThreadBlocking(() -> { Assert.assertTrue("Original text was not written to the native clipboard.", - ClipboardAndroidTestJni.get().nativeWriteHtml(originalText)); + ClipboardAndroidTestSupport.writeHtml(originalText)); }); // Assert that the ClipboardManager contains the original text. Then simulate another @@ -76,14 +72,7 @@ // Assert that the overwrite from another application is registered by the native clipboard. TestThreadUtils.runOnUiThreadBlocking(() -> { Assert.assertTrue("Invalidating text not found in the native clipboard.", - ClipboardAndroidTestJni.get().nativeClipboardContains(invalidatingText)); + ClipboardAndroidTestSupport.clipboardContains(invalidatingText)); }); } - - @NativeMethods - interface Natives { - void cleanup(); - boolean nativeWriteHtml(String htmlText); - boolean nativeClipboardContains(String text); - } }
diff --git a/ui/android/javatests/src/org/chromium/ui/base/ClipboardAndroidTestSupport.java b/ui/android/javatests/src/org/chromium/ui/base/ClipboardAndroidTestSupport.java new file mode 100644 index 0000000..cd45a37 --- /dev/null +++ b/ui/android/javatests/src/org/chromium/ui/base/ClipboardAndroidTestSupport.java
@@ -0,0 +1,44 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.ui.base; + +import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.annotations.NativeMethods; + +/** + * JNI methods for {@link ClipboardAndroidTest}. + */ +@JNINamespace("ui") +public class ClipboardAndroidTestSupport { + /** + * Cleans up clipboard on native side. + */ + public static void cleanup() { + ClipboardAndroidTestSupportJni.get().cleanup(); + } + + /** + * Writes HTML to the native side clipboard. + * @param htmlText the htmlText to write. + */ + public static boolean writeHtml(String htmlText) { + return ClipboardAndroidTestSupportJni.get().nativeWriteHtml(htmlText); + } + + /** + * Checks that the native side clipboard contains. + * @param text the expected text. + */ + public static boolean clipboardContains(String text) { + return ClipboardAndroidTestSupportJni.get().nativeClipboardContains(text); + } + + @NativeMethods + interface Natives { + void cleanup(); + boolean nativeWriteHtml(String htmlText); + boolean nativeClipboardContains(String text); + } +}
diff --git a/ui/base/clipboard/DEPS b/ui/base/clipboard/DEPS index 952f025..e703203 100644 --- a/ui/base/clipboard/DEPS +++ b/ui/base/clipboard/DEPS
@@ -1,7 +1,7 @@ include_rules = [ "+mojo/public/cpp/base", "+third_party/mozilla", - "+ui/android/ui_javatest_jni_headers/ClipboardAndroidTest_jni.h", + "+ui/android/ui_javatest_jni_headers/ClipboardAndroidTestSupport_jni.h", "+ui/base/ui_base_jni_headers", "-ui/ozone/*", "+ui/ozone/buildflags.h",
diff --git a/ui/base/clipboard/clipboard_android_test_support.cc b/ui/base/clipboard/clipboard_android_test_support.cc index 3df5e46..c14b76b 100644 --- a/ui/base/clipboard/clipboard_android_test_support.cc +++ b/ui/base/clipboard/clipboard_android_test_support.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/android/ui_javatest_jni_headers/ClipboardAndroidTest_jni.h" +#include "ui/android/ui_javatest_jni_headers/ClipboardAndroidTestSupport_jni.h" #include <string> @@ -15,11 +15,11 @@ namespace ui { -void JNI_ClipboardAndroidTest_Cleanup(JNIEnv* env) { +void JNI_ClipboardAndroidTestSupport_Cleanup(JNIEnv* env) { Clipboard::DestroyClipboardForCurrentThread(); } -jboolean JNI_ClipboardAndroidTest_NativeWriteHtml( +jboolean JNI_ClipboardAndroidTestSupport_NativeWriteHtml( JNIEnv* env, const base::android::JavaParamRef<jstring>& j_html_text) { { @@ -39,7 +39,7 @@ ClipboardBuffer::kCopyPaste); } -jboolean JNI_ClipboardAndroidTest_NativeClipboardContains( +jboolean JNI_ClipboardAndroidTestSupport_NativeClipboardContains( JNIEnv* env, const base::android::JavaParamRef<jstring>& j_text) { // The Java side of the test pretended to be another app using
diff --git a/ui/base/l10n/l10n_util.cc b/ui/base/l10n/l10n_util.cc index 70cae720..f21fee3 100644 --- a/ui/base/l10n/l10n_util.cc +++ b/ui/base/l10n/l10n_util.cc
@@ -888,6 +888,12 @@ } } +void GetAcceptLanguages(std::vector<std::string>* locale_codes) { + for (const char* accept_language : kAcceptLanguageList) { + locale_codes->push_back(accept_language); + } +} + bool IsLanguageAccepted(const std::string& display_locale, const std::string& locale) { for (const char* accept_language : kAcceptLanguageList) {
diff --git a/ui/base/l10n/l10n_util.h b/ui/base/l10n/l10n_util.h index a371dc42..21de1482 100644 --- a/ui/base/l10n/l10n_util.h +++ b/ui/base/l10n/l10n_util.h
@@ -212,6 +212,9 @@ const std::string& display_locale, std::vector<std::string>* locale_codes); +// Returns a vector of untranslated locale codes usable for accept-languages. +UI_BASE_EXPORT void GetAcceptLanguages(std::vector<std::string>* locale_codes); + // Returns true if |locale| is in a predefined AcceptLanguageList and // a display name for the |locale| is available in the locale |display_locale|. UI_BASE_EXPORT bool IsLanguageAccepted(const std::string& display_locale,
diff --git a/ui/message_center/views/message_popup_view.cc b/ui/message_center/views/message_popup_view.cc index a8ee041..bd6fac81 100644 --- a/ui/message_center/views/message_popup_view.cc +++ b/ui/message_center/views/message_popup_view.cc
@@ -113,7 +113,7 @@ views::Widget* widget = new views::Widget(); popup_collection_->ConfigureWidgetInitParamsForContainer(widget, ¶ms); widget->set_focus_on_creation(false); - widget->AddObserver(this); + observer_.Add(widget); #if defined(OS_WIN) // We want to ensure that this toast always goes to the native desktop, @@ -204,6 +204,10 @@ popup_collection_->Update(); } +void MessagePopupView::OnWidgetDestroyed(views::Widget* widget) { + observer_.Remove(widget); +} + bool MessagePopupView::IsWidgetValid() const { return GetWidget() && !GetWidget()->IsClosed(); }
diff --git a/ui/message_center/views/message_popup_view.h b/ui/message_center/views/message_popup_view.h index 550925a..9b5476c5d 100644 --- a/ui/message_center/views/message_popup_view.h +++ b/ui/message_center/views/message_popup_view.h
@@ -5,7 +5,9 @@ #ifndef UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_VIEW_H_ #define UI_MESSAGE_CENTER_VIEWS_MESSAGE_POPUP_VIEW_H_ +#include "base/scoped_observer.h" #include "ui/message_center/message_center_export.h" +#include "ui/views/widget/widget.h" #include "ui/views/widget/widget_delegate.h" #include "ui/views/widget/widget_observer.h" @@ -59,6 +61,7 @@ // views::WidgetObserver: void OnWidgetActivationChanged(views::Widget* widget, bool active) override; + void OnWidgetDestroyed(views::Widget* widget) override; bool is_hovered() const { return is_hovered_; } bool is_active() const { return is_active_; } @@ -83,6 +86,8 @@ bool is_hovered_ = false; bool is_active_ = false; + ScopedObserver<views::Widget, views::WidgetObserver> observer_{this}; + DISALLOW_COPY_AND_ASSIGN(MessagePopupView); };
diff --git a/ui/platform_window/x11/x11_window.cc b/ui/platform_window/x11/x11_window.cc index 98b442e..e42446d 100644 --- a/ui/platform_window/x11/x11_window.cc +++ b/ui/platform_window/x11/x11_window.cc
@@ -61,7 +61,6 @@ return WindowType::kPopup; case PlatformWindowType::kDrag: return WindowType::kDrag; - break; case PlatformWindowType::kBubble: return WindowType::kBubble; }
diff --git a/ui/views/accessibility/ax_virtual_view.cc b/ui/views/accessibility/ax_virtual_view.cc index cf273bc..ea292416 100644 --- a/ui/views/accessibility/ax_virtual_view.cc +++ b/ui/views/accessibility/ax_virtual_view.cc
@@ -11,6 +11,7 @@ #include <utility> #include "base/callback.h" +#include "base/containers/adapters.h" #include "base/no_destructor.h" #include "build/build_config.h" #include "ui/accessibility/ax_action_data.h" @@ -236,6 +237,15 @@ if (populate_data_callback_ && GetOwnerView()) populate_data_callback_.Run(&node_data); + + // According to the ARIA spec, the node should not be ignored if it is + // focusable. This is to ensure that the focusable node is both understandable + // and operable. + if (node_data.HasState(ax::mojom::State::kIgnored) && + node_data.HasState(ax::mojom::State::kFocusable)) { + node_data.RemoveState(ax::mojom::State::kIgnored); + } + return node_data; } @@ -302,12 +312,24 @@ const ui::AXCoordinateSystem coordinate_system, const ui::AXClippingBehavior clipping_behavior, ui::AXOffscreenResult* offscreen_result) const { + // We could optionally add clipping here if ever needed. + // TODO(nektar): Implement bounds that are relative to the parent. + gfx::Rect bounds = gfx::ToEnclosingRect(GetData().relative_bounds.bounds); + View* owner_view = GetOwnerView(); + if (owner_view && owner_view->GetWidget()) + View::ConvertRectToScreen(owner_view, &bounds); switch (coordinate_system) { case ui::AXCoordinateSystem::kScreenDIPs: - // We could optionally add clipping here if ever needed. - // TODO(nektar): Implement bounds that are relative to the parent. - return gfx::ToEnclosingRect(custom_data_.relative_bounds.bounds); - case ui::AXCoordinateSystem::kScreenPhysicalPixels: + return bounds; + case ui::AXCoordinateSystem::kScreenPhysicalPixels: { + float scale_factor = 1.0; + if (owner_view && owner_view->GetWidget()) { + gfx::NativeView native_view = owner_view->GetWidget()->GetNativeView(); + if (native_view) + scale_factor = ui::GetScaleFactorForNativeView(native_view); + } + return gfx::ScaleToEnclosingRect(bounds, scale_factor); + } case ui::AXCoordinateSystem::kRootFrame: case ui::AXCoordinateSystem::kFrame: NOTIMPLEMENTED(); @@ -318,27 +340,39 @@ gfx::NativeViewAccessible AXVirtualView::HitTestSync( int screen_physical_pixel_x, int screen_physical_pixel_y) const { - if (custom_data_.relative_bounds.bounds.Contains( - static_cast<float>(screen_physical_pixel_x), - static_cast<float>(screen_physical_pixel_y))) { - if (!IsIgnored()) - return GetNativeObject(); - } + const ui::AXNodeData& node_data = GetData(); + if (node_data.HasState(ax::mojom::State::kInvisible)) + return nullptr; // Check if the point is within any of the virtual children of this view. // AXVirtualView's HitTestSync is a recursive function that will return the // deepest child, since it does not support relative bounds. - for (const std::unique_ptr<AXVirtualView>& child : children_) { + // Search the greater indices first, since they're on top in the z-order. + for (const std::unique_ptr<AXVirtualView>& child : + base::Reversed(children_)) { gfx::NativeViewAccessible result = child->HitTestSync(screen_physical_pixel_x, screen_physical_pixel_y); if (result) return result; } + + // If it's not inside any of our virtual children, and it's inside the bounds + // of this virtual view, then it's inside this virtual view. + gfx::Rect bounds_in_screen_physical_pixels = + GetBoundsRect(ui::AXCoordinateSystem::kScreenPhysicalPixels, + ui::AXClippingBehavior::kUnclipped); + if (bounds_in_screen_physical_pixels.Contains( + static_cast<float>(screen_physical_pixel_x), + static_cast<float>(screen_physical_pixel_y)) && + !node_data.IsIgnored()) { + return GetNativeObject(); + } + return nullptr; } gfx::NativeViewAccessible AXVirtualView::GetFocus() { - auto* owner_view = GetOwnerView(); + View* owner_view = GetOwnerView(); if (owner_view) { if (!(owner_view->HasFocus())) { return nullptr; @@ -389,15 +423,7 @@ } bool AXVirtualView::IsIgnored() const { - const ui::AXNodeData& node_data = GetData(); - - // According to the ARIA spec, the node should not be ignored if it is - // focusable. This is to ensure that the focusable node is both understandable - // and operable. - if (node_data.HasState(ax::mojom::State::kFocusable)) - return false; - - return node_data.IsIgnored(); + return GetData().IsIgnored(); } bool AXVirtualView::HandleAccessibleAction(
diff --git a/ui/views/accessibility/ax_virtual_view.h b/ui/views/accessibility/ax_virtual_view.h index c74273c..105c961b 100644 --- a/ui/views/accessibility/ax_virtual_view.h +++ b/ui/views/accessibility/ax_virtual_view.h
@@ -142,7 +142,7 @@ gfx::Rect GetBoundsRect( const ui::AXCoordinateSystem coordinate_system, const ui::AXClippingBehavior clipping_behavior, - ui::AXOffscreenResult* offscreen_result) const override; + ui::AXOffscreenResult* offscreen_result = nullptr) const override; gfx::NativeViewAccessible HitTestSync( int screen_physical_pixel_x, int screen_physical_pixel_y) const override;
diff --git a/ui/views/accessibility/ax_virtual_view_unittest.cc b/ui/views/accessibility/ax_virtual_view_unittest.cc index 3f1cb20..b48ada53 100644 --- a/ui/views/accessibility/ax_virtual_view_unittest.cc +++ b/ui/views/accessibility/ax_virtual_view_unittest.cc
@@ -626,6 +626,51 @@ EXPECT_EQ(0, virtual_child_4->GetIndexInParent()); } +TEST_F(AXVirtualViewTest, HitTesting) { + ASSERT_EQ(0, virtual_label_->GetChildCount()); + + const gfx::Vector2d offset_from_origin = + button_->GetBoundsInScreen().OffsetFromOrigin(); + + // Test that hit testing is recursive. + AXVirtualView* virtual_child_1 = new AXVirtualView; + virtual_child_1->GetCustomData().relative_bounds.bounds = + gfx::RectF(0, 0, 10, 10); + virtual_label_->AddChildView(base::WrapUnique(virtual_child_1)); + AXVirtualView* virtual_child_2 = new AXVirtualView; + virtual_child_2->GetCustomData().relative_bounds.bounds = + gfx::RectF(5, 5, 5, 5); + virtual_child_1->AddChildView(base::WrapUnique(virtual_child_2)); + gfx::Point point_1 = gfx::Point(2, 2) + offset_from_origin; + EXPECT_EQ(virtual_child_1->GetNativeObject(), + virtual_child_1->HitTestSync(point_1.x(), point_1.y())); + gfx::Point point_2 = gfx::Point(7, 7) + offset_from_origin; + EXPECT_EQ(virtual_child_2->GetNativeObject(), + virtual_label_->HitTestSync(point_2.x(), point_2.y())); + + // Test that hit testing follows the z-order. + AXVirtualView* virtual_child_3 = new AXVirtualView; + virtual_child_3->GetCustomData().relative_bounds.bounds = + gfx::RectF(5, 5, 10, 10); + virtual_label_->AddChildView(base::WrapUnique(virtual_child_3)); + AXVirtualView* virtual_child_4 = new AXVirtualView; + virtual_child_4->GetCustomData().relative_bounds.bounds = + gfx::RectF(10, 10, 10, 10); + virtual_child_3->AddChildView(base::WrapUnique(virtual_child_4)); + EXPECT_EQ(virtual_child_3->GetNativeObject(), + virtual_label_->HitTestSync(point_2.x(), point_2.y())); + gfx::Point point_3 = gfx::Point(12, 12) + offset_from_origin; + EXPECT_EQ(virtual_child_4->GetNativeObject(), + virtual_label_->HitTestSync(point_3.x(), point_3.y())); + + // Test that hit testing skips ignored nodes but not their descendants. + virtual_child_3->GetCustomData().AddState(ax::mojom::State::kIgnored); + EXPECT_EQ(virtual_child_2->GetNativeObject(), + virtual_label_->HitTestSync(point_2.x(), point_2.y())); + EXPECT_EQ(virtual_child_4->GetNativeObject(), + virtual_label_->HitTestSync(point_3.x(), point_3.y())); +} + // Test for GetTargetForNativeAccessibilityEvent(). #if defined(OS_WIN) TEST_F(AXVirtualViewTest, GetTargetForEvents) {
diff --git a/ui/views/controls/table/table_view.cc b/ui/views/controls/table/table_view.cc index 458e247..94eb7a0 100644 --- a/ui/views/controls/table/table_view.cc +++ b/ui/views/controls/table/table_view.cc
@@ -1422,28 +1422,33 @@ } gfx::Rect TableView::CalculateHeaderRowAccessibilityBounds() const { - return AdjustRectForAXRelativeBounds(header_->GetVisibleBounds()); + gfx::Rect header_bounds = header_->GetVisibleBounds(); + gfx::Point header_origin = header_bounds.origin(); + ConvertPointToTarget(header_, this, &header_origin); + header_bounds.set_origin(header_origin); + return header_bounds; } gfx::Rect TableView::CalculateHeaderCellAccessibilityBounds( const int visible_column_index) const { + const gfx::Rect& header_bounds = CalculateHeaderRowAccessibilityBounds(); const VisibleColumn& visible_column = visible_columns_[visible_column_index]; - gfx::Rect header_cell_bounds(visible_column.x, header_->y(), - visible_column.width, header_->height()); - return AdjustRectForAXRelativeBounds(header_cell_bounds); + gfx::Rect header_cell_bounds(visible_column.x, header_bounds.y(), + visible_column.width, header_bounds.height()); + return header_cell_bounds; } gfx::Rect TableView::CalculateTableRowAccessibilityBounds( const int row_index) const { gfx::Rect row_bounds = GetRowBounds(row_index); - return AdjustRectForAXRelativeBounds(row_bounds); + return row_bounds; } gfx::Rect TableView::CalculateTableCellAccessibilityBounds( const int row_index, const int visible_column_index) const { gfx::Rect cell_bounds = GetCellBounds(row_index, visible_column_index); - return AdjustRectForAXRelativeBounds(cell_bounds); + return cell_bounds; } void TableView::UpdateAccessibilityFocus() { @@ -1510,13 +1515,6 @@ return i->get(); } -gfx::Rect TableView::AdjustRectForAXRelativeBounds( - const gfx::Rect& rect) const { - gfx::Rect converted_rect = rect; - View::ConvertRectToScreen(this, &converted_rect); - return converted_rect; -} - DEFINE_ENUM_CONVERTERS(TableTypes, {TableTypes::TEXT_ONLY, base::ASCIIToUTF16("TEXT_ONLY")}, {TableTypes::ICON_AND_TEXT,
diff --git a/ui/views/controls/table/table_view.h b/ui/views/controls/table/table_view.h index 6a5546c7..1a640fd 100644 --- a/ui/views/controls/table/table_view.h +++ b/ui/views/controls/table/table_view.h
@@ -383,11 +383,6 @@ // |visible_column_index| indexes into |visible_columns_|. AXVirtualView* GetVirtualAccessibilityCell(int row, int visible_column_index); - // Returns |rect|, adjusted for use in AXRelativeBounds by translating it into - // screen coordinates. The result must be converted to gfx::RectF when setting - // into AXRelativeBounds. - gfx::Rect AdjustRectForAXRelativeBounds(const gfx::Rect& rect) const; - ui::TableModel* model_ = nullptr; std::vector<ui::TableColumn> columns_;
diff --git a/ui/views/controls/table/table_view_unittest.cc b/ui/views/controls/table/table_view_unittest.cc index fb2a3ec..df538cc5 100644 --- a/ui/views/controls/table/table_view_unittest.cc +++ b/ui/views/controls/table/table_view_unittest.cc
@@ -80,23 +80,33 @@ // Generate the bounds for the header row and cells. auto header_row = std::vector<gfx::Rect>(); - header_row.push_back(table_->CalculateHeaderRowAccessibilityBounds()); + gfx::Rect header_row_bounds = + table_->CalculateHeaderRowAccessibilityBounds(); + View::ConvertRectToScreen(table_, &header_row_bounds); + header_row.push_back(header_row_bounds); for (size_t column_index = 0; column_index < visible_col_count(); column_index++) { - header_row.push_back( - table_->CalculateHeaderCellAccessibilityBounds(column_index)); + gfx::Rect header_cell_bounds = + table_->CalculateHeaderCellAccessibilityBounds(column_index); + View::ConvertRectToScreen(table_, &header_cell_bounds); + header_row.push_back(header_cell_bounds); } expected_bounds.push_back(header_row); // Generate the bounds for the table rows and cells. for (int row_index = 0; row_index < table_->GetRowCount(); row_index++) { auto table_row = std::vector<gfx::Rect>(); - table_row.push_back( - table_->CalculateTableRowAccessibilityBounds(row_index)); + gfx::Rect table_row_bounds = + table_->CalculateTableRowAccessibilityBounds(row_index); + View::ConvertRectToScreen(table_, &table_row_bounds); + table_row.push_back(table_row_bounds); for (size_t column_index = 0; column_index < visible_col_count(); column_index++) { - table_row.push_back(table_->CalculateTableCellAccessibilityBounds( - row_index, column_index)); + gfx::Rect table_cell_bounds = + table_->CalculateTableCellAccessibilityBounds(row_index, + column_index); + View::ConvertRectToScreen(table_, &table_cell_bounds); + table_row.push_back(table_cell_bounds); } expected_bounds.push_back(table_row); }
diff --git a/ui/views/controls/tree/tree_view.cc b/ui/views/controls/tree/tree_view.cc index 7d26bdf..01da559 100644 --- a/ui/views/controls/tree/tree_view.cc +++ b/ui/views/controls/tree/tree_view.cc
@@ -922,7 +922,6 @@ data->AddAction(ax::mojom::Action::kFocus); data->AddAction(ax::mojom::Action::kScrollToMakeVisible); gfx::Rect node_bounds = GetBackgroundBoundsForNode(node); - View::ConvertRectToScreen(this, &node_bounds); data->relative_bounds.bounds = gfx::RectF(node_bounds); } else { data->AddState(ax::mojom::State::kInvisible);
diff --git a/ui/views/corewm/tooltip_aura.cc b/ui/views/corewm/tooltip_aura.cc index a1e74af..c115ea2b 100644 --- a/ui/views/corewm/tooltip_aura.cc +++ b/ui/views/corewm/tooltip_aura.cc
@@ -296,6 +296,8 @@ void TooltipAura::OnWidgetDestroying(views::Widget* widget) { DCHECK_EQ(widget_, widget); + if (widget_) + widget_->RemoveObserver(this); widget_ = nullptr; tooltip_window_ = nullptr; }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java index f6f5a02..557f316 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/DownloadImpl.java
@@ -362,7 +362,7 @@ // Create the NotificationChannel, but only on API 26+ because // the NotificationChannel class is new and not in the support library if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - int importance = NotificationManager.IMPORTANCE_DEFAULT; + int importance = NotificationManager.IMPORTANCE_LOW; NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Downloads", importance); NotificationManager notificationManager =
diff --git a/weblayer/public/java/org/chromium/weblayer/BroadcastReceiver.java b/weblayer/public/java/org/chromium/weblayer/BroadcastReceiver.java index f78ca697..4721e3fa 100644 --- a/weblayer/public/java/org/chromium/weblayer/BroadcastReceiver.java +++ b/weblayer/public/java/org/chromium/weblayer/BroadcastReceiver.java
@@ -13,7 +13,7 @@ /** * Listens to events from WebLayer-spawned notifications. */ -class BroadcastReceiver extends android.content.BroadcastReceiver { +public class BroadcastReceiver extends android.content.BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { try {