diff --git a/DEPS b/DEPS index c553f910f..a617575 100644 --- a/DEPS +++ b/DEPS
@@ -129,11 +129,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': '1f58a8e457baef95ebf081d673859410e6e6c635', + 'skia_revision': '69da7ad49b55a9085ff4e442b5d67ea110ac5566', # 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': 'c6983f4880540c602fe2754ba9dc8329320b95a9', + 'v8_revision': '72592828213b06ab2f4b69f2ed5685c1e43123b1', # 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. @@ -141,11 +141,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ANGLE # and whatever else without interference from each other. - 'angle_revision': 'fb201c5e208dda3fb657ae3c543f0f6059ecb4f0', + 'angle_revision': 'b9a71427efd22870c2fdb40462a74d99f06e609d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': '0e3d328ac338c4c9474f5d967455ff501bd869cb', + 'swiftshader_revision': 'bd3af855ae74d9767eb68adcdd1a66c29dc1d81e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -196,7 +196,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling catapult # and whatever else without interference from each other. - 'catapult_revision': '810aaa1e18466131f6a75b1f631fb5b0dd81f344', + 'catapult_revision': '9057b413d4b19b24786542b710e03cfa62bbb6af', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -805,7 +805,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'fe63720b9960bf520768a169ed0e31c7e834d0a7', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c5403d69e17c0cf99abb9eb10e827515afca499f', 'condition': 'checkout_linux', }, @@ -1343,7 +1343,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '688fbfe33779392aa210d67d4aa12cb012f112c2', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '1c747f5717bcbde029a2d496832ee52388dbda05', + Var('webrtc_git') + '/src.git' + '@' + '59e875ce18bb24aa6d1ec5cdf128d7ef244fa37a', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d',
diff --git a/PRESUBMIT.py b/PRESUBMIT.py index 9e2e1414..f56ef0fb8 100644 --- a/PRESUBMIT.py +++ b/PRESUBMIT.py
@@ -786,7 +786,6 @@ 'build/android/gyp/create_java_binary_script.pydeps', 'build/android/gyp/create_size_info_files.pydeps', 'build/android/gyp/create_stack_script.pydeps', - 'build/android/gyp/create_test_runner_script.pydeps', 'build/android/gyp/create_tool_wrapper.pydeps', 'build/android/gyp/desugar.pydeps', 'build/android/gyp/dexsplitter.pydeps',
diff --git a/ash/ime/ime_engine_factory_registry_unittest.cc b/ash/ime/ime_engine_factory_registry_unittest.cc index 0414b45..c2b9279d 100644 --- a/ash/ime/ime_engine_factory_registry_unittest.cc +++ b/ash/ime/ime_engine_factory_registry_unittest.cc
@@ -26,6 +26,15 @@ } private: + // ime::mojom::ImeEngineClient: + void CommitText(const std::string& text) override {} + void UpdateCompositionText(const ui::CompositionText& composition, + uint32_t cursor_pos, + bool visible) override {} + void DeleteSurroundingText(int32_t offset, uint32_t length) override {} + void SendKeyEvent(std::unique_ptr<ui::Event> key_event) override {} + void Reconnect() override {} + mojo::Binding<ime::mojom::ImeEngineClient> binding_; DISALLOW_COPY_AND_ASSIGN(TestImeEngineClient);
diff --git a/base/values.cc b/base/values.cc index 30b0d76..03acb86 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -407,10 +407,20 @@ return FindKeyOfType(key, Type::LIST); } -bool Value::RemoveKey(StringPiece key) { +Value* Value::SetKey(StringPiece key, Value&& value) { + return SetKeyInternal(key, std::make_unique<Value>(std::move(value))); +} + +Value* Value::SetKey(std::string&& key, Value&& value) { CHECK(is_dict()); - // NOTE: Can't directly return dict_->erase(key) due to MSVC warning C4800. - return dict_.erase(key) != 0; + return dict_ + .insert_or_assign(std::move(key), + std::make_unique<Value>(std::move(value))) + .first->second.get(); +} + +Value* Value::SetKey(const char* key, Value&& value) { + return SetKeyInternal(key, std::make_unique<Value>(std::move(value))); } Value* Value::SetBoolKey(StringPiece key, bool value) { @@ -441,20 +451,20 @@ return SetKeyInternal(key, std::make_unique<Value>(value)); } -Value* Value::SetKey(StringPiece key, Value&& value) { - return SetKeyInternal(key, std::make_unique<Value>(std::move(value))); -} - -Value* Value::SetKey(std::string&& key, Value&& value) { +bool Value::RemoveKey(StringPiece key) { CHECK(is_dict()); - return dict_ - .insert_or_assign(std::move(key), - std::make_unique<Value>(std::move(value))) - .first->second.get(); + return dict_.erase(key) != 0; } -Value* Value::SetKey(const char* key, Value&& value) { - return SetKeyInternal(key, std::make_unique<Value>(std::move(value))); +Optional<Value> Value::ExtractKey(StringPiece key) { + CHECK(is_dict()); + auto found = dict_.find(key); + if (found == dict_.end()) + return nullopt; + + Value value = std::move(*found->second); + dict_.erase(found); + return std::move(value); } Value* Value::FindPath(StringPiece path) { @@ -572,25 +582,29 @@ } bool Value::RemovePath(StringPiece path) { + return ExtractPath(path).has_value(); +} + +Optional<Value> Value::ExtractPath(StringPiece path) { if (!is_dict() || path.empty()) - return false; + return nullopt; // NOTE: PathSplitter is not being used here because recursion is used to // ensure that dictionaries that become empty due to this operation are // removed automatically. size_t pos = path.find('.'); if (pos == path.npos) - return RemoveKey(path); + return ExtractKey(path); auto found = dict_.find(path.substr(0, pos)); if (found == dict_.end() || !found->second->is_dict()) - return false; + return nullopt; - bool removed = found->second->RemovePath(path.substr(pos + 1)); - if (removed && found->second->dict_.empty()) + Optional<Value> extracted = found->second->ExtractPath(path.substr(pos + 1)); + if (extracted && found->second->dict_.empty()) dict_.erase(found); - return removed; + return extracted; } // DEPRECATED METHODS
diff --git a/base/values.h b/base/values.h index 60263b56..3d034cd6 100644 --- a/base/values.h +++ b/base/values.h
@@ -167,7 +167,7 @@ bool is_dict() const { return type() == Type::DICTIONARY; } bool is_list() const { return type() == Type::LIST; } - // These will all fatally assert if the type doesn't match. + // These will all CHECK if the type doesn't match. bool GetBool() const; int GetInt() const; double GetDouble() const; // Implicitly converts from int if necessary. @@ -181,7 +181,7 @@ // a pointer to the element. Otherwise it returns nullptr. // returned. Callers are expected to perform a check against null before using // the pointer. - // Note: This fatally asserts if type() is not Type::DICTIONARY. + // Note: This CHECKs if type() is not Type::DICTIONARY. // // Example: // auto* found = FindKey("foo"); @@ -193,7 +193,7 @@ // different type nullptr is returned. // Callers are expected to perform a check against null before using the // pointer. - // Note: This fatally asserts if type() is not Type::DICTIONARY. + // Note: This CHECKs if type() is not Type::DICTIONARY. // // Example: // auto* found = FindKey("foo", Type::DOUBLE); @@ -226,7 +226,7 @@ // |SetKey| looks up |key| in the underlying dictionary and sets the mapped // value to |value|. If |key| could not be found, a new element is inserted. // A pointer to the modified item is returned. - // Note: This fatally asserts if type() is not Type::DICTIONARY. + // Note: This CHECKs if type() is not Type::DICTIONARY. // Note: Prefer Set<Type>Key() for simple values. // // Example: @@ -251,16 +251,26 @@ Value* SetStringKey(StringPiece key, std::string&& val); Value* SetStringKey(StringPiece key, StringPiece16 val); - // This attemps to remove the value associated with |key|. In case of failure, - // e.g. the key does not exist, |false| is returned and the underlying + // This attempts to remove the value associated with |key|. In case of + // failure, e.g. the key does not exist, false is returned and the underlying // dictionary is not changed. In case of success, |key| is deleted from the - // dictionary and the method returns |true|. - // Note: This fatally asserts if type() is not Type::DICTIONARY. + // dictionary and the method returns true. + // Note: This CHECKs if type() is not Type::DICTIONARY. // // Example: - // bool success = RemoveKey("foo"); + // bool success = dict.RemoveKey("foo"); bool RemoveKey(StringPiece key); + // This attempts to extract the value associated with |key|. In case of + // failure, e.g. the key does not exist, nullopt is returned and the + // underlying dictionary is not changed. In case of success, |key| is deleted + // from the dictionary and the method returns the extracted Value. + // Note: This CHECKs if type() is not Type::DICTIONARY. + // + // Example: + // Optional<Value> maybe_value = dict.ExtractKey("foo"); + Optional<Value> ExtractKey(StringPiece key); + // Searches a hierarchy of dictionary values for a given value. If a path // of dictionaries exist, returns the item at that path. If any of the path // components do not exist or if any but the last path components are not @@ -282,13 +292,12 @@ // as either a std::initializer_list<StringPiece> or a // span<const StringPiece>. The latter is useful to use a // std::vector<std::string> as a parameter but creates huge dynamic - // allocations and should be avoided! Note: If there is only one component in - // the path, use FindKey() instead. + // allocations and should be avoided! + // Note: If there is only one component in the path, use FindKey() instead. + // // Example: // std::vector<StringPiece> components = ... // auto* found = FindPath(components); - // - // Note: If there is only one component in the path, use FindKey() instead. Value* FindPath(std::initializer_list<StringPiece> path); Value* FindPath(span<const StringPiece> path); const Value* FindPath(std::initializer_list<StringPiece> path) const; @@ -355,24 +364,33 @@ // Tries to remove a Value at the given path. // - // If the current value is not a dictionary or any path components does not + // If the current value is not a dictionary or any path component does not // exist, this operation fails, leaves underlying Values untouched and returns // |false|. In case intermediate dictionaries become empty as a result of this // path removal, they will be removed as well. + // Note: If there is only one component in the path, use ExtractKey() instead. // // Example: // bool success = value.RemovePath("foo.bar"); - // - // std::vector<StringPiece> components = ... - // bool success = value.RemovePath(components); - // - // Note: If there is only one component in the path, use RemoveKey() instead. bool RemovePath(StringPiece path); // Deprecated versions bool RemovePath(std::initializer_list<StringPiece> path); bool RemovePath(span<const StringPiece> path); + // Tries to extract a Value at the given path. + // + // If the current value is not a dictionary or any path component does not + // exist, this operation fails, leaves underlying Values untouched and returns + // nullopt. In case intermediate dictionaries become empty as a result of this + // path removal, they will be removed as well. Returns the extracted value on + // success. + // Note: If there is only one component in the path, use ExtractKey() instead. + // + // Example: + // Optional<Value> maybe_value = value.ExtractPath("foo.bar"); + Optional<Value> ExtractPath(StringPiece path); + using dict_iterator_proxy = detail::dict_iterator_proxy; using const_dict_iterator_proxy = detail::const_dict_iterator_proxy; @@ -380,12 +398,12 @@ // dictionary. These are intended for iteration over all items in the // dictionary and are compatible with for-each loops and standard library // algorithms. - // Note: This fatally asserts if type() is not Type::DICTIONARY. + // Note: These CHECK if type() is not Type::DICTIONARY. dict_iterator_proxy DictItems(); const_dict_iterator_proxy DictItems() const; // Returns the size of the dictionary, and if the dictionary is empty. - // Note: This fatally asserts if type() is not Type::DICTIONARY. + // Note: These CHECK if type() is not Type::DICTIONARY. size_t DictSize() const; bool DictEmpty() const; @@ -394,8 +412,7 @@ // passed in dictionary takes precedence and data already present will be // replaced. Values within |dictionary| are deep-copied, so |dictionary| may // be freed any time after this call. - // Note: This fatally asserts if type() or dictionary->type() is not - // Type::DICTIONARY. + // Note: This CHECKs if type() or dictionary->type() is not Type::DICTIONARY. void MergeDictionary(const Value* dictionary); // These methods allow the convenient retrieval of the contents of the Value. @@ -631,18 +648,20 @@ // |out_value|. If |out_value| is NULL, the removed value will be deleted. // This method returns true if |path| is a valid path; otherwise it will // return false and the DictionaryValue object will be unchanged. - // DEPRECATED, use Value::RemovePath(path) instead. + // DEPRECATED, use Value::RemovePath(path) or Value::ExtractPath(path) + // instead. bool Remove(StringPiece path, std::unique_ptr<Value>* out_value); // Like Remove(), but without special treatment of '.'. This allows e.g. URLs // to be used as paths. - // DEPRECATED, use Value::RemoveKey(key) instead. + // DEPRECATED, use Value::RemoveKey(key) or Value::ExtractKey(key) instead. bool RemoveWithoutPathExpansion(StringPiece key, std::unique_ptr<Value>* out_value); // Removes a path, clearing out all dictionaries on |path| that remain empty // after removing the value at |path|. - // DEPRECATED, use Value::RemovePath(path) instead. + // DEPRECATED, use Value::RemovePath(path) or Value::ExtractPath(path) + // instead. bool RemovePath(StringPiece path, std::unique_ptr<Value>* out_value); using Value::RemovePath; // DictionaryValue::RemovePath shadows otherwise.
diff --git a/base/values_unittest.cc b/base/values_unittest.cc index fc71517..884309b 100644 --- a/base/values_unittest.cc +++ b/base/values_unittest.cc
@@ -1076,6 +1076,20 @@ EXPECT_FALSE(root.RemoveKey("one")); } +TEST(ValuesTest, ExtractKey) { + Value root(Value::Type::DICTIONARY); + root.SetKey("one", Value(123)); + + // Extraction of missing key should fail. + EXPECT_EQ(nullopt, root.ExtractKey("two")); + + // Extraction of existing key should succeed. + EXPECT_EQ(Value(123), root.ExtractKey("one")); + + // Second extraction of previously existing key should fail. + EXPECT_EQ(nullopt, root.ExtractKey("one")); +} + TEST(ValuesTest, RemovePath) { Value root(Value::Type::DICTIONARY); root.SetPath("one.two.three", Value(123)); @@ -1090,16 +1104,42 @@ EXPECT_FALSE(root.RemovePath("one.two.three")); // Intermediate empty dictionaries should be cleared. - EXPECT_FALSE(root.FindKey("one")); + EXPECT_EQ(nullptr, root.FindKey("one")); root.SetPath("one.two.three", Value(123)); root.SetPath("one.two.four", Value(124)); EXPECT_TRUE(root.RemovePath("one.two.three")); // Intermediate non-empty dictionaries should be kept. - EXPECT_TRUE(root.FindKey("one")); - EXPECT_TRUE(root.FindPath("one.two")); - EXPECT_TRUE(root.FindPath("one.two.four")); + EXPECT_NE(nullptr, root.FindKey("one")); + EXPECT_NE(nullptr, root.FindPath("one.two")); + EXPECT_NE(nullptr, root.FindPath("one.two.four")); +} + +TEST(ValuesTest, ExtractPath) { + Value root(Value::Type::DICTIONARY); + root.SetPath("one.two.three", Value(123)); + + // Extraction of missing key should fail. + EXPECT_EQ(nullopt, root.ExtractPath("one.two.four")); + + // Extraction of existing key should succeed. + EXPECT_EQ(Value(123), root.ExtractPath("one.two.three")); + + // Second extraction of previously existing key should fail. + EXPECT_EQ(nullopt, root.ExtractPath("one.two.three")); + + // Intermediate empty dictionaries should be cleared. + EXPECT_EQ(nullptr, root.FindKey("one")); + + root.SetPath("one.two.three", Value(123)); + root.SetPath("one.two.four", Value(124)); + + EXPECT_EQ(Value(123), root.ExtractPath("one.two.three")); + // Intermediate non-empty dictionaries should be kept. + EXPECT_NE(nullptr, root.FindKey("one")); + EXPECT_NE(nullptr, root.FindPath("one.two")); + EXPECT_NE(nullptr, root.FindPath("one.two.four")); } TEST(ValuesTest, Basic) {
diff --git a/build/android/gyp/create_test_runner_script.py b/build/android/gyp/create_test_runner_script.py deleted file mode 100755 index bb7c465..0000000 --- a/build/android/gyp/create_test_runner_script.py +++ /dev/null
@@ -1,163 +0,0 @@ -#!/usr/bin/env python -# -# 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. - -"""Creates a script to run an android test using build/android/test_runner.py. -""" - -import argparse -import os -import re -import sys - -from util import build_utils - -SCRIPT_TEMPLATE = """\ -#!/usr/bin/env vpython -# -# This file was generated by build/android/gyp/create_test_runner_script.py - -import os -import sys - -def main(): - script_directory = os.path.dirname(__file__) - - def ResolvePath(path): - \"\"\"Returns a normalized filepath given a path relative to this script. - \"\"\" - return os.path.normpath(os.path.join(script_directory, path)) - - test_runner_path = ResolvePath('{test_runner_path}') - test_runner_args = {test_runner_args} - test_runner_path_args = {test_runner_path_args} - for arg, path in test_runner_path_args: - test_runner_args.extend([arg, ResolvePath(path)]) - - os.execv(test_runner_path, - [test_runner_path] + test_runner_args + sys.argv[1:]) - -if __name__ == '__main__': - sys.exit(main()) -""" - - -def _GenerateAdditionalApksErrorString(incremental_apks): - err_string = ('Apks that are listed as additional_apks for ' - 'another target cannot be incremental. Please add never_incremental to ' - 'the following apks: %s') - return err_string % ', '.join(a for a in incremental_apks) - - -def main(args): - parser = argparse.ArgumentParser() - parser.add_argument('--script-output-path', - help='Output path for executable script.') - parser.add_argument('--test-runner-path', - help='Path to test_runner.py (optional).') - - # We need to intercept any test runner path arguments and make all - # of the paths relative to the output script directory. - group = parser.add_argument_group('Test runner path arguments.') - group.add_argument('--additional-apk', action='append', - dest='additional_apks', default=[]) - group.add_argument('--additional-apk-list') - group.add_argument('--additional-apk-incremental', action='append', - dest='additional_apks_incremental', default=[]) - group.add_argument('--apk-under-test') - group.add_argument('--apk-under-test-incremental-install-json') - group.add_argument('--executable-dist-dir') - group.add_argument('--isolate-file-path') - group.add_argument('--output-directory') - group.add_argument('--runtime-deps-path') - group.add_argument('--test-apk') - group.add_argument('--test-jar') - group.add_argument('--test-apk-incremental-install-json') - group.add_argument('--coverage-dir') - group.add_argument('--android-manifest-path') - group.add_argument('--resource-zips') - group.add_argument('--robolectric-runtime-deps-dir') - args, test_runner_args = parser.parse_known_args( - build_utils.ExpandFileArgs(args)) - - def RelativizePathToScript(path): - """Returns the path relative to the output script directory.""" - return os.path.relpath(path, os.path.dirname(args.script_output_path)) - - test_runner_path = args.test_runner_path or os.path.join( - os.path.dirname(__file__), os.path.pardir, 'test_runner.py') - test_runner_path = RelativizePathToScript(test_runner_path) - - test_runner_path_args = [] - if args.additional_apk_list: - args.additional_apks.extend( - build_utils.ParseGnList(args.additional_apk_list)) - if args.additional_apks: - test_runner_path_args.extend( - ('--additional-apk', RelativizePathToScript(a)) - for a in args.additional_apks) - if args.additional_apks_incremental: - bad_additional_apks = [a for a in args.additional_apks_incremental - if a != 'None'] - if bad_additional_apks: - raise Exception(_GenerateAdditionalApksErrorString(bad_additional_apks)) - if args.apk_under_test: - test_runner_path_args.append( - ('--apk-under-test', RelativizePathToScript(args.apk_under_test))) - if args.apk_under_test_incremental_install_json: - test_runner_path_args.append( - ('--apk-under-test-incremental-install-json', - RelativizePathToScript( - args.apk_under_test_incremental_install_json))) - if args.executable_dist_dir: - test_runner_path_args.append( - ('--executable-dist-dir', - RelativizePathToScript(args.executable_dist_dir))) - if args.isolate_file_path: - test_runner_path_args.append( - ('--isolate-file-path', RelativizePathToScript(args.isolate_file_path))) - if args.output_directory: - test_runner_path_args.append( - ('--output-directory', RelativizePathToScript(args.output_directory))) - if args.runtime_deps_path: - test_runner_path_args.append( - ('--runtime-deps-path', RelativizePathToScript(args.runtime_deps_path))) - if args.test_apk: - test_runner_path_args.append( - ('--test-apk', RelativizePathToScript(args.test_apk))) - if args.test_jar: - test_runner_path_args.append( - ('--test-jar', RelativizePathToScript(args.test_jar))) - if args.test_apk_incremental_install_json: - test_runner_path_args.append( - ('--test-apk-incremental-install-json', - RelativizePathToScript(args.test_apk_incremental_install_json))) - if args.coverage_dir: - test_runner_path_args.append( - ('--coverage-dir', RelativizePathToScript(args.coverage_dir))) - if args.android_manifest_path: - test_runner_path_args.append( - ('--android-manifest-path', - RelativizePathToScript(args.android_manifest_path))) - if args.resource_zips: - test_runner_path_args.extend( - ('--resource-zip', RelativizePathToScript(r)) - for r in build_utils.ParseGnList(args.resource_zips)) - if args.robolectric_runtime_deps_dir: - test_runner_path_args.append( - ('--robolectric-runtime-deps-dir', - RelativizePathToScript(args.robolectric_runtime_deps_dir))) - - with build_utils.AtomicOutput(args.script_output_path) as script: - script.write(SCRIPT_TEMPLATE.format( - test_runner_path=str(test_runner_path), - test_runner_args=str(test_runner_args), - test_runner_path_args=str(test_runner_path_args))) - - os.chmod(args.script_output_path, 0750) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:]))
diff --git a/build/android/gyp/create_test_runner_script.pydeps b/build/android/gyp/create_test_runner_script.pydeps deleted file mode 100644 index 4b8876b..0000000 --- a/build/android/gyp/create_test_runner_script.pydeps +++ /dev/null
@@ -1,7 +0,0 @@ -# Generated by running: -# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/create_test_runner_script.pydeps build/android/gyp/create_test_runner_script.py -../../gn_helpers.py -create_test_runner_script.py -util/__init__.py -util/build_utils.py -util/md5_check.py
diff --git a/build/android/gyp/generate_android_wrapper.py b/build/android/gyp/generate_android_wrapper.py new file mode 100755 index 0000000..f8e1815 --- /dev/null +++ b/build/android/gyp/generate_android_wrapper.py
@@ -0,0 +1,42 @@ +#!/usr/bin/env python +# 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. + +import os +import re +import sys + +from util import build_utils + +sys.path.append( + os.path.abspath( + os.path.join(os.path.dirname(__file__), '..', '..', 'util'))) + +import generate_wrapper + +_WRAPPED_PATH_LIST_RE = re.compile(r'@WrappedPathList\(([^,]+), ([^)]+)\)') + + +def ExpandWrappedPathLists(args): + expanded_args = [] + for arg in args: + m = _WRAPPED_PATH_LIST_RE.match(arg) + if m: + for p in build_utils.ParseGnList(m.group(2)): + expanded_args.extend([m.group(1), '@WrappedPath(%s)' % p]) + else: + expanded_args.append(arg) + return expanded_args + + +def main(raw_args): + parser = generate_wrapper.CreateArgumentParser() + expanded_raw_args = build_utils.ExpandFileArgs(raw_args) + expanded_raw_args = ExpandWrappedPathLists(expanded_raw_args) + args = parser.parse_args(expanded_raw_args) + return generate_wrapper.Wrap(args) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:]))
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py index ad26224..a0ef2ee 100644 --- a/build/android/gyp/util/build_utils.py +++ b/build/android/gyp/util/build_utils.py
@@ -573,9 +573,6 @@ if not match: continue - if match.end() != len(arg): - raise Exception('Unexpected characters after FileArg: ' + arg) - lookup_path = match.group(1).split(':') file_path = lookup_path[0] if not file_path in file_jsons: @@ -589,9 +586,10 @@ # This should match ParseGnList. The output is either a GN-formatted list # or a literal (with no quotes). if isinstance(expansion, list): - new_args[i] = arg[:match.start()] + gn_helpers.ToGNString(expansion) + new_args[i] = (arg[:match.start()] + gn_helpers.ToGNString(expansion) + + arg[match.end():]) else: - new_args[i] = arg[:match.start()] + str(expansion) + new_args[i] = arg[:match.start()] + str(expansion) + arg[match.end():] return new_args
diff --git a/build/android/test_runner.py b/build/android/test_runner.py index 9891d2e..b26bade 100755 --- a/build/android/test_runner.py +++ b/build/android/test_runner.py
@@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env vpython # # Copyright 2013 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index ed85335..afb8ca9a 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -8,6 +8,7 @@ import("//build/config/dcheck_always_on.gni") import("//build/config/python.gni") import("//build/config/sanitizers/sanitizers.gni") +import("//build/util/generate_wrapper.gni") import("//build_overrides/build.gni") assert(is_android) @@ -570,6 +571,18 @@ } } +template("generate_android_wrapper") { + generate_wrapper(target_name) { + forward_variables_from(invoker, "*") + generator_script = "//build/android/gyp/generate_android_wrapper.py" + sources = [ + "//build/android/gyp/util/build_utils.py", + "//build/gn_helpers.py", + "//build/util/generate_wrapper.py", + ] + } +} + # Generates a script in the build bin directory which runs the test # target using the test runner script in build/android/test_runner.py. template("test_runner_script") { @@ -607,7 +620,7 @@ } } - action_with_pydeps(target_name) { + generate_android_wrapper(target_name) { forward_variables_from(invoker, [ "data_deps", @@ -616,11 +629,17 @@ if (!defined(deps)) { deps = [] } + if (!defined(data_deps)) { data_deps = [] } - script = "//build/android/gyp/create_test_runner_script.py" + if (defined(android_test_runner_script)) { + executable = android_test_runner_script + } else { + executable = "//build/android/test_runner.py" + } + testonly = true data_deps += [ "//build/android:test_runner_py", @@ -629,18 +648,20 @@ data = [] - test_runner_args = [ + executable_args = [ _test_type, "--output-directory", - rebase_path(root_build_dir, root_build_dir), + "@WrappedPath(.)", ] if (_runtime_deps) { deps += [ ":$_runtime_deps_target" ] data += [ _runtime_deps_file ] - test_runner_args += [ + _rebased_runtime_deps_file = + rebase_path(_runtime_deps_file, root_build_dir) + executable_args += [ "--runtime-deps-path", - rebase_path(_runtime_deps_file, root_build_dir), + "@WrappedPath(${_rebased_runtime_deps_file})", ] } @@ -658,28 +679,32 @@ assert( defined(invoker.executable_dist_dir), "Must define either apk_target or executable_dist_dir for test_runner_script()") - test_runner_args += [ + _rebased_executable_dist_dir = + rebase_path(invoker.executable_dist_dir, root_build_dir) + executable_args += [ "--executable-dist-dir", - rebase_path(invoker.executable_dist_dir, root_build_dir), + "@WrappedPath(${_rebased_executable_dist_dir})", ] } _device_test = true if (_test_type == "gtest") { assert(defined(invoker.test_suite)) - test_runner_args += [ + executable_args += [ "--suite", invoker.test_suite, ] } else if (_test_type == "instrumentation") { - _test_apk = "@FileArg($_rebased_apk_build_config:deps_info:apk_path)" + _test_apk = "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:apk_path))" if (_incremental_install) { - _test_apk = "@FileArg($_rebased_apk_build_config:deps_info:incremental_apk_path)" + _test_apk = "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:incremental_apk_path))" } - test_runner_args += [ - "--test-apk=$_test_apk", + _rebased_test_jar = rebase_path(invoker.test_jar, root_build_dir) + executable_args += [ + "--test-apk", + _test_apk, "--test-jar", - rebase_path(invoker.test_jar, root_build_dir), + "@WrappedPath(${_rebased_test_jar})", ] if (defined(invoker.apk_under_test)) { deps += [ "${invoker.apk_under_test}$build_config_target_suffix" ] @@ -688,38 +713,44 @@ get_label_info(invoker.apk_under_test, "name") + ".build_config" _rebased_apk_under_test_build_config = rebase_path(_apk_under_test_build_config, root_build_dir) - _apk_under_test = - "@FileArg($_rebased_apk_under_test_build_config:deps_info:apk_path)" + _apk_under_test = "@WrappedPath(@FileArg($_rebased_apk_under_test_build_config:deps_info:apk_path))" if (_incremental_install) { - _apk_under_test = "@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_apk_path)" + _apk_under_test = "@WrappedPath(@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_apk_path))" } - test_runner_args += [ "--apk-under-test=$_apk_under_test" ] + executable_args += [ + "--apk-under-test", + _apk_under_test, + ] } if (defined(invoker.proguard_enabled) && invoker.proguard_enabled) { - test_runner_args += [ "--enable-java-deobfuscation" ] + executable_args += [ "--enable-java-deobfuscation" ] } if (emma_coverage) { # Set a default coverage output directory (can be overridden by user # passing the same flag). - test_runner_args += [ + _rebased_coverage_dir = + rebase_path("$root_out_dir/coverage", root_build_dir) + executable_args += [ "--coverage-dir", - rebase_path("$root_out_dir/coverage", root_build_dir), + "@WrappedPath(${_rebased_coverage_dir})", ] } } else if (_test_type == "junit") { assert(defined(invoker.test_suite)) _device_test = false - test_runner_args += [ + executable_args += [ "--test-suite", invoker.test_suite, ] if (defined(invoker.android_manifest_path)) { - test_runner_args += [ + _rebased_android_manifest_path = + rebase_path(invoker.android_manifest_path, root_build_dir) + executable_args += [ "--android-manifest-path", - rebase_path(invoker.android_manifest_path, root_build_dir), + "@WrappedPath(${_rebased_android_manifest_path})", ] } else if (defined(invoker.package_name)) { - test_runner_args += [ + executable_args += [ "--package-name", invoker.package_name, ] @@ -732,20 +763,19 @@ "${target_gen_dir}/${invoker.test_suite}.build_config" _rebased_build_config = rebase_path("$_junit_binary_build_config", root_build_dir) - test_runner_args += [ - "--resource-zips", - "@FileArg($_rebased_build_config:resources:dependency_zips)", - ] + executable_args += [ "@WrappedPathList(--resource-zip, @FileArg($_rebased_build_config:resources:dependency_zips))" ] - test_runner_args += [ + _rebased_robolectric_runtime_deps_dir = + rebase_path("$root_build_dir/lib.java/third_party/robolectric", + root_build_dir) + executable_args += [ "--robolectric-runtime-deps-dir", - rebase_path("$root_build_dir/lib.java/third_party/robolectric", - root_build_dir), + "@WrappedPath(${_rebased_robolectric_runtime_deps_dir})", ] } else if (_test_type == "linker") { - test_runner_args += [ + executable_args += [ "--test-apk", - "@FileArg($_rebased_apk_build_config:deps_info:apk_path)", + "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:apk_path))", ] } else { assert(false, "Invalid test type: $_test_type.") @@ -757,57 +787,40 @@ _build_config = get_label_info(additional_apk, "target_gen_dir") + "/" + get_label_info(additional_apk, "name") + ".build_config" _rebased_build_config = rebase_path(_build_config, root_build_dir) - test_runner_args += [ + executable_args += [ "--additional-apk", - "@FileArg($_rebased_build_config:deps_info:apk_path)", + "@WrappedPath(@FileArg($_rebased_build_config:deps_info:apk_path))", "--additional-apk-incremental", - "@FileArg($_rebased_build_config:deps_info:incremental_apk_path)", + "@WrappedPath(@FileArg($_rebased_build_config:deps_info:incremental_apk_path))", ] } } if (defined(invoker.shard_timeout)) { - test_runner_args += [ "--shard-timeout=${invoker.shard_timeout}" ] + executable_args += [ "--shard-timeout=${invoker.shard_timeout}" ] } if (_incremental_install) { - test_runner_args += [ + executable_args += [ "--test-apk-incremental-install-json", - "@FileArg($_rebased_apk_build_config:deps_info:incremental_install_json_path)", + "@WrappedPath(@FileArg($_rebased_apk_build_config:deps_info:incremental_install_json_path))", ] if (defined(invoker.apk_under_test)) { - test_runner_args += [ + executable_args += [ "--apk-under-test-incremental-install-json", - "@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_install_json_path)", + "@WrappedPath(@FileArg($_rebased_apk_under_test_build_config:deps_info:incremental_install_json_path))", ] } - test_runner_args += [ "--fast-local-dev" ] + executable_args += [ "--fast-local-dev" ] } if (_device_test && is_asan) { - test_runner_args += [ "--tool=asan" ] + executable_args += [ "--tool=asan" ] } if (defined(invoker.generated_script)) { assert(_test_name != "" || true) # Mark _test_name as used. - generated_script = invoker.generated_script + wrapper_script = invoker.generated_script } else { - generated_script = "$root_build_dir/bin/run_${_test_name}" + wrapper_script = "$root_build_dir/bin/run_${_test_name}" } - outputs = [ - generated_script, - ] - data += [ generated_script ] - - args = [ - "--script-output-path", - rebase_path(generated_script, root_build_dir), - ] - if (defined(android_test_runner_script)) { - args += [ - "--test-runner-path", - android_test_runner_script, - ] - } - - args += test_runner_args } }
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 54d2624..7138f702 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8917075804817341376 \ No newline at end of file +8917022403152524912 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 8c9335d..668df67 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8917084311105425712 \ No newline at end of file +8917018730856666704 \ No newline at end of file
diff --git a/build/util/generate_wrapper.gni b/build/util/generate_wrapper.gni index 51658e2..74d9433 100644 --- a/build/util/generate_wrapper.gni +++ b/build/util/generate_wrapper.gni
@@ -62,6 +62,7 @@ "data", "data_deps", "deps", + "sources", "testonly", ]) script = _generator_script
diff --git a/build/util/generate_wrapper.py b/build/util/generate_wrapper.py index b89f9fe0..5373e1e 100755 --- a/build/util/generate_wrapper.py +++ b/build/util/generate_wrapper.py
@@ -11,21 +11,26 @@ import textwrap +# The bash template passes the python script into vpython via stdin. +# The interpreter doesn't know about the script, so we have bash +# inject the script location. BASH_TEMPLATE = textwrap.dedent( """\ - #!/usr/bin/env bash - python - <<END $@ - _SCRIPT_LOCATION = "${{BASH_SOURCE[0]}}" + #!/usr/bin/env vpython + _SCRIPT_LOCATION = __file__ {script} - END """) +# The batch template reruns the batch script with vpython, with the -x +# flag instructing the interpreter to ignore the first line. The interpreter +# knows about the (batch) script in this case, so it can get the file location +# directly. BATCH_TEMPLATE = textwrap.dedent( """\ @SETLOCAL ENABLEDELAYEDEXPANSION \ - & python -x "%~f0" %* \ - & EXIT /B !ERRORLEVEL! + & vpython.bat -x "%~f0" %* \ + & EXIT /B !ERRORLEVEL! _SCRIPT_LOCATION = __file__ {script} """)
diff --git a/cc/paint/paint_worklet_input.h b/cc/paint/paint_worklet_input.h index 16572914..94e2cfda 100644 --- a/cc/paint/paint_worklet_input.h +++ b/cc/paint/paint_worklet_input.h
@@ -15,6 +15,7 @@ : public base::RefCountedThreadSafe<PaintWorkletInput> { public: virtual gfx::SizeF GetSize() const = 0; + virtual int WorkletId() const = 0; protected: friend class base::RefCountedThreadSafe<PaintWorkletInput>;
diff --git a/cc/test/test_paint_worklet_input.cc b/cc/test/test_paint_worklet_input.cc index 85a8671..2916057 100644 --- a/cc/test/test_paint_worklet_input.cc +++ b/cc/test/test_paint_worklet_input.cc
@@ -10,4 +10,8 @@ return container_size_; } +int TestPaintWorkletInput::WorkletId() const { + return 1u; +} + } // namespace cc
diff --git a/cc/test/test_paint_worklet_input.h b/cc/test/test_paint_worklet_input.h index 1f1510f..8113137c 100644 --- a/cc/test/test_paint_worklet_input.h +++ b/cc/test/test_paint_worklet_input.h
@@ -13,7 +13,9 @@ public: explicit TestPaintWorkletInput(const gfx::SizeF& size) : container_size_(size) {} + gfx::SizeF GetSize() const override; + int WorkletId() const override; protected: ~TestPaintWorkletInput() override = default;
diff --git a/chrome/android/features/autofill_assistant/BUILD.gn b/chrome/android/features/autofill_assistant/BUILD.gn index 29f21e2..059e3f0 100644 --- a/chrome/android/features/autofill_assistant/BUILD.gn +++ b/chrome/android/features/autofill_assistant/BUILD.gn
@@ -35,6 +35,7 @@ "//content/public/android:content_java", "//third_party/android_deps:android_support_v7_appcompat_java", "//third_party/android_deps:com_android_support_design_java", + "//third_party/android_deps:com_android_support_gridlayout_v7_java", "//third_party/android_deps:com_android_support_recyclerview_v7_java", "//third_party/android_deps:com_android_support_support_compat_java", "//third_party/android_deps:com_android_support_support_core_ui_java", @@ -82,6 +83,7 @@ "java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayModel.java", "java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayDrawable.java", "java/src/org/chromium/chrome/browser/autofill_assistant/overlay/AssistantOverlayEventFilter.java", + "java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantChoiceList.java", "java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestCoordinator.java", "java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestDelegate.java", "java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestModel.java",
diff --git a/chrome/android/features/autofill_assistant/java/res/drawable/ic_autofill_assistant_add_circle_24dp.xml b/chrome/android/features/autofill_assistant/java/res/drawable/ic_autofill_assistant_add_circle_24dp.xml new file mode 100644 index 0000000..fef6777 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/res/drawable/ic_autofill_assistant_add_circle_24dp.xml
@@ -0,0 +1,16 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> +<vector + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:width="24dp" + android:height="24dp" + android:viewportWidth="24" + android:viewportHeight="24" + tools:targetApi="21"> + <path + android:fillColor="@color/default_icon_color_blue" + android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM17,13h-4v4h-2v-4L7,13v-2h4L11,7h2v4h4v2z"/> +</vector>
diff --git a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_payment_request.xml b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_payment_request.xml index 31ee93c..05288a9 100644 --- a/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_payment_request.xml +++ b/chrome/android/features/autofill_assistant/java/res/layout/autofill_assistant_payment_request.xml
@@ -4,6 +4,8 @@ found in the LICENSE file. --> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/autofill_assistant_payment_request" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" @@ -17,30 +19,27 @@ android:orientation="vertical" /> <!-- 3rd party terms & conditions. --> - <RadioGroup + <Space android:layout_width="0dp" android:layout_height="8dp"/> + <org.chromium.chrome.browser.autofill_assistant.payment.AssistantChoiceList + android:id="@+id/third_party_terms_list" android:layout_width="match_parent" android:layout_height="wrap_content" - android:orientation="vertical"> - - <!-- Set paddingStart to add padding between radio-button and text. --> - <Space android:layout_width="0dp" android:layout_height="9dp"/> - <android.support.v7.widget.AppCompatRadioButton + app:column_spacing="8dp" + app:row_spacing="8dp"> + <TextView android:id="@+id/terms_checkbox_agree" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="9dp" android:text="@string/autofill_assistant_3rd_party_terms_accept" android:textAppearance="@style/TextAppearance.BlackCaption"/> - <Space android:layout_width="0dp" android:layout_height="5dp"/> - <android.support.v7.widget.AppCompatRadioButton + <TextView android:id="@+id/terms_checkbox_review" android:layout_width="match_parent" android:layout_height="wrap_content" - android:paddingStart="9dp" android:text="@string/autofill_assistant_3rd_party_terms_review" android:textAppearance="@style/TextAppearance.BlackCaption"/> - </RadioGroup> - <Space android:layout_width="0dp" android:layout_height="12dp"/> + </org.chromium.chrome.browser.autofill_assistant.payment.AssistantChoiceList> + <Space android:layout_width="0dp" android:layout_height="10dp"/> <TextView android:id="@+id/payment_request_3rd_party_privacy_notice" android:layout_width="match_parent"
diff --git a/chrome/android/features/autofill_assistant/java/res/values-v17/attrs.xml b/chrome/android/features/autofill_assistant/java/res/values-v17/attrs.xml new file mode 100644 index 0000000..bb4204c --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/res/values-v17/attrs.xml
@@ -0,0 +1,14 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- 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. --> + +<resources> + <declare-styleable name="AssistantChoiceList"> + <attr name="add_button_text" format="string"/> + <attr name="row_spacing" format="dimension"/> + <attr name="column_spacing" format="dimension"/> + + <attr name="layout_edit_button_text" format="string"/> + </declare-styleable> +</resources> \ No newline at end of file
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantChoiceList.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantChoiceList.java new file mode 100644 index 0000000..7297a69b6 --- /dev/null +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantChoiceList.java
@@ -0,0 +1,339 @@ +// 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. + +package org.chromium.chrome.browser.autofill_assistant.payment; + +import android.content.Context; +import android.content.res.TypedArray; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayout; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewDebug; +import android.view.ViewGroup; +import android.widget.RadioButton; +import android.widget.Space; +import android.widget.TextView; + +import org.chromium.base.ApiCompatibilityUtils; +import org.chromium.base.Callback; +import org.chromium.chrome.autofill_assistant.R; +import org.chromium.ui.widget.ChromeImageView; + +import java.util.ArrayList; +import java.util.List; + +/** + * A widget that displays a list of choices in a regular grid. It is similar to a RadioGroup, but + * much more customizable, because it allows arbitrary content views rather than only TextViews. + * + * The layout is as follows: + * [radio-button] | content | [edit-button] + * [radio-button] | content | [edit-button] + * ... + * [add-icon] | [add-button] | + * + * A number of custom view attributes control the layout and look of this widget. + * - Edit-buttons are optional on an item-by-item basis. + * - The add-button at the end of the list is optional. + * - Spacing between rows and columns can be customized. + * - The text for the `add' and `edit' buttons can be customized. + */ +public class AssistantChoiceList extends GridLayout { + /** + * Represents a single choice with a radio button, customizable content and an edit button. + */ + private class Item { + final RadioButton mRadioButton; + final View mContent; + final View mEditButton; + + Item(@Nullable RadioButton radioButton, View content, @Nullable View editButton) { + this.mRadioButton = radioButton; + this.mContent = content; + this.mEditButton = editButton; + } + } + + /** + * |mCanAddItems| is true if the custom view parameter |add_button_text| was specified. + * If true, the list will have an additional 'add' button at the end. + */ + private final boolean mCanAddItems; + /** + * |mAddButton| and |mAddButtonLabel| are guaranteed to be non-null if |mCanAddItems| is true. + */ + private final ChromeImageView mAddButton; + private final TextView mAddButtonLabel; + private final int mRowSpacing; + private final int mColumnSpacing; + private final List<Item> mItems = new ArrayList<>(); + + private Runnable mAddButtonListener; + private Callback<View> mItemSelectedListener; + private Callback<View> mEditButtonListener; + + public AssistantChoiceList(Context context, AttributeSet attrs) { + super(context, attrs); + TypedArray a = context.getTheme().obtainStyledAttributes( + attrs, R.styleable.AssistantChoiceList, 0, 0); + mCanAddItems = a.hasValue(R.styleable.AssistantChoiceList_add_button_text); + String addButtonText = + mCanAddItems ? a.getString(R.styleable.AssistantChoiceList_add_button_text) : null; + mRowSpacing = a.getDimensionPixelSize(R.styleable.AssistantChoiceList_row_spacing, 0); + mColumnSpacing = a.getDimensionPixelSize(R.styleable.AssistantChoiceList_column_spacing, 0); + a.recycle(); + + // One column for the radio buttons, one for the content, one for the edit buttons. + setColumnCount(3); + + if (mCanAddItems) { + mAddButton = createAddButtonIcon(); + mAddButtonLabel = createAddButtonLabel(addButtonText); + + addViewInternal(mAddButton, -1, createRadioButtonLayoutParams()); + GridLayout.LayoutParams lp = createContentLayoutParams(); + lp.columnSpec = GridLayout.spec(UNDEFINED, 2); + addViewInternal(mAddButtonLabel, -1, lp); + + // Set margin to 0 because list is currently empty. + updateAddButtonMargins(0); + } else { + mAddButton = null; + mAddButtonLabel = null; + } + } + + /** + * Children of this container are automatically added as selectable items to the list. + * + * This method is automatically called by layout inflaters and xml files. In code, you usually + * want to call |addItem| directly. + */ + @Override + public void addView(View view, int index, ViewGroup.LayoutParams lp) { + assert index != -1; + String editText = null; + if (lp instanceof AssistantChoiceList.LayoutParams) { + editText = ((LayoutParams) lp).mEditText; + } + + addItem(view, editText); + } + + /** + * Adds an item to the list. Additional widgets to select and edit the item are created as + * necessary. + * @param view The view to add to the list. + * @param editButtonText The text of the edit button to display next to |view|. Can be null to + * indicate that no edit button should be provided. + */ + public void addItem(View view, @Nullable String editButtonText) { + RadioButton radioButton = new RadioButton(getContext()); + // Insert at end, before the `add' button (if any). + int index = mCanAddItems ? indexOfChild(mAddButton) : getChildCount(); + addViewInternal(radioButton, index++, createRadioButtonLayoutParams()); + addViewInternal(view, index++, createContentLayoutParams()); + + TextView editButton = null; + if (editButtonText != null) { + editButton = (TextView) LayoutInflater.from(getContext()) + .inflate(R.layout.autofill_assistant_button_hairline, + /*parent = */ null); + editButton.setText(editButtonText); + editButton.setOnClickListener(unusedView -> { + if (mEditButtonListener != null) { + mEditButtonListener.onResult(view); + } + }); + addViewInternal(editButton, index++, createEditButtonLayoutParams()); + } else { + View spacer = new Space(getContext()); + addViewInternal(spacer, index++, createEditButtonLayoutParams()); + } + + Item item = new Item(radioButton, view, editButton); + radioButton.setOnClickListener(unusedView -> setCheckedItem(item)); + // TODO(crbug.com/806868): Forward event to radiobutton to re-trigger animation. + view.setOnClickListener(unusedView -> setCheckedItem(item)); + mItems.add(item); + + // Need to adjust button margins after first item was inserted. + if (mItems.size() == 1) { + updateAddButtonMargins(mRowSpacing); + } + } + + public void setOnAddButtonClickedListener(Runnable listener) { + mAddButtonListener = listener; + } + + public void setOnEditButtonClickedListener(Callback<View> listener) { + mEditButtonListener = listener; + } + + public void setOnItemSelectedListener(Callback<View> listener) { + mItemSelectedListener = listener; + } + + @Override + public LayoutParams generateLayoutParams(AttributeSet attrs) { + return new AssistantChoiceList.LayoutParams(getContext(), attrs); + } + + @Override + protected LayoutParams generateDefaultLayoutParams() { + return new AssistantChoiceList.LayoutParams(); + } + + @Override + protected LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) { + if (lp instanceof LayoutParams) { + return new LayoutParams((LayoutParams) lp); + } else if (lp instanceof GridLayout.LayoutParams) { + return new LayoutParams((GridLayout.LayoutParams) lp); + } + return new LayoutParams(lp); + } + + // Override to allow type-checking of LayoutParams. + @Override + protected boolean checkLayoutParams(ViewGroup.LayoutParams p) { + return p instanceof AssistantChoiceList.LayoutParams; + } + + /** + * Adds a view to the underlying gridlayout. + * + * This method is used internally to add a view to the actual layout. A single call to |addView| + * will result in multiple calls to |addViewInternal|, because additional widgets are + * automatically generated (e.g., radio-buttons and edit-buttons). + * @param view The view to add to the layout. + * @param index The index at which to insert the view into the layout. Note that this - along + * with the column width specified in |lp| - will determine the column in which the view will + * end up in. + * @param lp Additional layout parameters, see |GridLayout.LayoutParams|. + */ + private void addViewInternal(View view, int index, ViewGroup.LayoutParams lp) { + super.addView(view, index, lp); + } + + private ChromeImageView createAddButtonIcon() { + ChromeImageView addButtonIcon = new ChromeImageView(getContext()); + addButtonIcon.setImageResource(R.drawable.ic_autofill_assistant_add_circle_24dp); + addButtonIcon.setOnClickListener(unusedView -> { + if (mAddButtonListener != null) { + mAddButtonListener.run(); + } + }); + return addButtonIcon; + } + + private TextView createAddButtonLabel(String addButtonText) { + TextView addButtonLabel = new TextView(getContext()); + ApiCompatibilityUtils.setTextAppearance( + addButtonLabel, R.style.TextAppearance_BlueButtonText2); + addButtonLabel.setText(addButtonText); + addButtonLabel.setOnClickListener(unusedView -> { + if (mAddButtonListener != null) { + mAddButtonListener.run(); + } + }); + return addButtonLabel; + } + + private GridLayout.LayoutParams createContentLayoutParams() { + // Set layout params to let content grow to maximum size. + GridLayout.LayoutParams lp = + new GridLayout.LayoutParams(GridLayout.spec(UNDEFINED), GridLayout.spec(1, 1)); + lp.setGravity(Gravity.FILL_HORIZONTAL | Gravity.CENTER_VERTICAL); + lp.width = 0; + lp.topMargin = mItems.isEmpty() ? 0 : mRowSpacing; + return lp; + } + + private GridLayout.LayoutParams createRadioButtonLayoutParams() { + GridLayout.LayoutParams lp = + new GridLayout.LayoutParams(GridLayout.spec(UNDEFINED), GridLayout.spec(0, 1)); + lp.setGravity(Gravity.CENTER); + lp.setMarginEnd(mColumnSpacing); + lp.topMargin = mItems.isEmpty() ? 0 : mRowSpacing; + return lp; + } + + private GridLayout.LayoutParams createEditButtonLayoutParams() { + GridLayout.LayoutParams lp = + new GridLayout.LayoutParams(GridLayout.spec(UNDEFINED), GridLayout.spec(2, 1)); + lp.setGravity(Gravity.CENTER_VERTICAL); + lp.setMarginStart(mColumnSpacing); + lp.topMargin = mItems.isEmpty() ? 0 : mRowSpacing; + return lp; + } + + /** + * Adjusts the margins of the 'add' button. + * + * For empty lists, the margins should be 0. For non-empty lists, the margins should be equal + * to |mRowSpacing|. + */ + private void updateAddButtonMargins(int marginTop) { + if (!mCanAddItems) { + return; + } + + LayoutParams lp = (LayoutParams) mAddButton.getLayoutParams(); + lp.setMargins(lp.leftMargin, marginTop, lp.rightMargin, lp.bottomMargin); + mAddButton.setLayoutParams(lp); + + lp = (LayoutParams) mAddButtonLabel.getLayoutParams(); + lp.setMargins(lp.leftMargin, marginTop, lp.rightMargin, lp.bottomMargin); + mAddButtonLabel.setLayoutParams(lp); + } + + private void setCheckedItem(Item item) { + boolean changed = false; + for (int i = 0; i < mItems.size(); i++) { + RadioButton radioButton = mItems.get(i).mRadioButton; + boolean isItem = mItems.get(i) == item; + changed |= isItem && !radioButton.isChecked(); + radioButton.setChecked(isItem); + } + + if (changed && mItemSelectedListener != null) { + mItemSelectedListener.onResult(item.mContent); + } + } + + /** + * Per-child layout information associated with AssistantChoiceList. + */ + public static class LayoutParams extends GridLayout.LayoutParams { + /** + * Indicates whether an 'edit' button should be added for this item. + */ + @ViewDebug.ExportedProperty(category = "layout") + public String mEditText; + + public LayoutParams(Context c, AttributeSet attrs) { + super(c, attrs); + TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.AssistantChoiceList); + mEditText = a.getString(R.styleable.AssistantChoiceList_layout_edit_button_text); + a.recycle(); + } + + public LayoutParams(ViewGroup.LayoutParams p) { + super(p); + } + + public LayoutParams(GridLayout.LayoutParams p) { + super(p); + } + + private LayoutParams() { + super(); + } + } +}
diff --git a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestUI.java b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestUI.java index 1d8d9905..39966aca 100644 --- a/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestUI.java +++ b/chrome/android/features/autofill_assistant/java/src/org/chromium/chrome/browser/autofill_assistant/payment/AssistantPaymentRequestUI.java
@@ -15,7 +15,6 @@ import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.widget.LinearLayout; -import android.widget.RadioButton; import android.widget.TextView; import org.chromium.chrome.autofill_assistant.R; @@ -120,8 +119,6 @@ private FadingEdgeScrollView mRequestViewContainer; private ViewGroup mRequestView; private LinearLayout mPaymentContainerLayout; - private RadioButton mAcceptThirdPartyConditions; - private RadioButton mReviewThirdPartyConditions; private boolean mRequestShipping; private boolean mRequestContactDetails; @@ -200,17 +197,26 @@ private void prepareRequestView(String origin) { // Set terms & conditions text. - mAcceptThirdPartyConditions = mRequestView.findViewById(R.id.terms_checkbox_agree); - mReviewThirdPartyConditions = mRequestView.findViewById(R.id.terms_checkbox_review); + AssistantChoiceList thirdPartyTermsList = + mRequestView.findViewById(R.id.third_party_terms_list); + TextView acceptThirdPartyConditions = + thirdPartyTermsList.findViewById(R.id.terms_checkbox_agree); + TextView reviewThirdPartyConditions = + thirdPartyTermsList.findViewById(R.id.terms_checkbox_review); StyleSpan boldSpan = new StyleSpan(android.graphics.Typeface.BOLD); - mAcceptThirdPartyConditions.setText(SpanApplier.applySpans( + acceptThirdPartyConditions.setText(SpanApplier.applySpans( mActivity.getString(R.string.autofill_assistant_3rd_party_terms_accept, origin), new SpanApplier.SpanInfo("<b>", "</b>", boldSpan))); - mReviewThirdPartyConditions.setText(SpanApplier.applySpans( + reviewThirdPartyConditions.setText(SpanApplier.applySpans( mActivity.getString(R.string.autofill_assistant_3rd_party_terms_review, origin), new SpanApplier.SpanInfo("<b>", "</b>", boldSpan))); - mAcceptThirdPartyConditions.setOnClickListener(this); - mReviewThirdPartyConditions.setOnClickListener(this); + thirdPartyTermsList.setOnItemSelectedListener((view) -> { + if (view == acceptThirdPartyConditions) { + mClient.onCheckAcceptTermsAndConditions(true); + } else if (view == reviewThirdPartyConditions) { + mClient.onCheckReviewTermsAndConditions(true); + } + }); // Set 3rd party privacy notice text. TextView thirdPartyPrivacyNotice = @@ -430,10 +436,6 @@ expand(mContactDetailsSection); } else if (v == mPaymentMethodSection) { expand(mPaymentMethodSection); - } else if (v == mAcceptThirdPartyConditions) { - mClient.onCheckAcceptTermsAndConditions(mAcceptThirdPartyConditions.isChecked()); - } else if (v == mReviewThirdPartyConditions) { - mClient.onCheckReviewTermsAndConditions(mReviewThirdPartyConditions.isChecked()); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigator.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigator.java index 12a04095..0edd9e6 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigator.java
@@ -6,9 +6,13 @@ import android.support.annotation.Nullable; +import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController; +import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider; import org.chromium.chrome.browser.dependency_injection.ActivityScope; +import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.NavigationHistory; +import org.chromium.content_public.browser.WebContents; import javax.inject.Inject; @@ -26,9 +30,15 @@ @ActivityScope public class CloseButtonNavigator { @Nullable private PageCriteria mLandingPageCriteria; + private final CustomTabActivityTabController mTabController; + private final CustomTabActivityTabProvider mTabProvider; @Inject - public CloseButtonNavigator() {} + public CloseButtonNavigator(CustomTabActivityTabController tabController, + CustomTabActivityTabProvider tabProvider) { + mTabController = tabController; + mTabProvider = tabProvider; + } // TODO(peconn): Replace with Predicate<T> when we can use Java 8 libraries. /** An interface that allows specifying if a URL matches some criteria. */ @@ -44,17 +54,48 @@ mLandingPageCriteria = criteria; } + private boolean isLandingPage(String url) { + return mLandingPageCriteria != null && mLandingPageCriteria.matches(url); + } + /** - * Navigates to the most recent landing page. Returns {@code false} if no criteria for what is - * a landing page has been given or no such page can be found. + * Handles navigation and Tab closures that should occur when the close button is pressed. It + * searches for a landing page in the history of the current Tab and then closes it if none are + * found. This continues until a landing page is found or all Tabs are closed. */ - public boolean navigateOnClose(@Nullable NavigationController controller) { + public void navigateOnClose() { + while (mTabProvider.getTab() != null) { + // See if there's a close button navigation in our current Tab. + NavigationController navigationController = getNavigationController(); + if (navigationController != null && navigateSingleTab(getNavigationController())) { + return; + } + + mTabController.closeTab(); + + // Check whether the close button navigation would have stopped on the newly revealed + // Tab. We don't check this at the start of the loop (or make navigateSingleTab + // consider the current Tab) because in that case if the user started on a landing page, + // we would not navigate at all. (Admittedly though this case would never happen at the + // time of writing since landing pages don't show the close button). + Tab nextTab = mTabProvider.getTab(); + if (nextTab != null && isLandingPage(mTabProvider.getTab().getUrl())) { + return; + } + } + } + + /** + * Navigates to the most recent landing page on the current Tab. Returns {@code false} if no + * criteria for what is a landing page has been given or no such page can be found. + */ + private boolean navigateSingleTab(@Nullable NavigationController controller) { if (mLandingPageCriteria == null || controller == null) return false; NavigationHistory history = controller.getNavigationHistory(); for (int i = history.getCurrentEntryIndex() - 1; i >= 0; i--) { String url = history.getEntryAtIndex(i).getUrl(); - if (!mLandingPageCriteria.matches(url)) continue; + if (!isLandingPage(url)) continue; controller.goToNavigationIndex(i); return true; @@ -62,4 +103,13 @@ return false; } + + @Nullable + private NavigationController getNavigationController() { + Tab tab = mTabProvider.getTab(); + if (tab == null) return null; + WebContents webContents = tab.getWebContents(); + if (webContents == null) return null; + return webContents.getNavigationController(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java index 0258966..f06e69a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java
@@ -38,9 +38,7 @@ import org.chromium.chrome.browser.toolbar.ToolbarManager; import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; import org.chromium.content_public.browser.LoadUrlParams; -import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.UiThreadTaskTraits; -import org.chromium.content_public.browser.WebContents; import org.chromium.ui.base.PageTransition; import java.lang.annotation.Retention; @@ -100,14 +98,14 @@ private boolean mIsFinishing; - private boolean mIsClosingTabOnBack; + private boolean mIsHandlingUserNavigation; private final CustomTabActivityTabProvider.Observer mTabObserver = new CustomTabActivityTabProvider.Observer() { @Override public void onAllTabsClosed() { - finish(mIsClosingTabOnBack ? USER_NAVIGATION : OTHER); + finish(mIsHandlingUserNavigation ? USER_NAVIGATION : OTHER); } }; @@ -205,32 +203,21 @@ private void executeDefaultBackHandling() { if (mToolbarManager.get().back()) return; - // mTabController.closeTab may result in either closing the only tab, or swapping to the - // previous tab. In the first case we need finish to be called with USER_NAVIGATION reason. - mIsClosingTabOnBack = true; + // mTabController.closeTab may result in either closing the only tab (through the back + // button or the close button), or swapping to the previous tab. In the first case we need + // finish to be called with USER_NAVIGATION reason. + mIsHandlingUserNavigation = true; mTabController.closeTab(); - mIsClosingTabOnBack = false; + mIsHandlingUserNavigation = false; } /** * Handles close button navigation. */ public void navigateOnClose() { - NavigationController navigationController = getNavigationController(); - if (navigationController != null - && mCloseButtonNavigator.navigateOnClose(navigationController)) { - return; - } - finish(USER_NAVIGATION); - } - - @Nullable - private NavigationController getNavigationController() { - Tab tab = mTabProvider.getTab(); - if (tab == null) return null; - WebContents webContents = tab.getWebContents(); - if (webContents == null) return null; - return webContents.getNavigationController(); + mIsHandlingUserNavigation = true; + mCloseButtonNavigator.navigateOnClose(); + mIsHandlingUserNavigation = false; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java index 05f9087..f2dd7f4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityTabController.java
@@ -162,7 +162,7 @@ * case links with target="_blank" were followed. See the comment to * {@link CustomTabActivityTabProvider.Observer#onAllTabsClosed}. */ - void closeTab() { + public void closeTab() { mTabFactory.getTabModelSelector().getCurrentModel().closeTab(mTabProvider.getTab(), false, false, false); }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java index cb5e99e1..d86e131 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/customtabs/CustomTabActivityTest.java
@@ -8,6 +8,8 @@ import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.not; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.chromium.base.test.util.Restriction.RESTRICTION_TYPE_NON_LOW_END_DEVICE; import static org.chromium.chrome.browser.customtabs.CustomTabActivityTestRule.LONG_TIMEOUT_MS; @@ -119,6 +121,7 @@ import org.chromium.content_public.browser.LoadUrlParams; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContentsObserver; +import org.chromium.content_public.browser.test.util.ClickUtils; import org.chromium.content_public.browser.test.util.Criteria; import org.chromium.content_public.browser.test.util.CriteriaHelper; import org.chromium.content_public.browser.test.util.DOMUtils; @@ -156,6 +159,8 @@ "/chrome/test/data/geolocation/geolocation_on_load.html"; private static final String SELECT_POPUP_PAGE = "/chrome/test/data/android/select.html"; private static final String FRAGMENT_TEST_PAGE = "/chrome/test/data/android/fragment.html"; + private static final String TARGET_BLANK_TEST_PAGE = + "/chrome/test/data/android/cct_target_blank.html"; private static final String TEST_MENU_TITLE = "testMenuTitle"; private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "chrome"; private static final String WEBLITE_PREFIX = "http://googleweblight.com/i?u="; @@ -399,7 +404,7 @@ final int expectedMenuSize = 12; Menu menu = ContextMenuUtils.openContextMenu( mCustomTabActivityTestRule.getActivity().getActivityTab(), "logo"); - Assert.assertEquals(expectedMenuSize, menu.size()); + assertEquals(expectedMenuSize, menu.size()); Assert.assertNotNull(menu.findItem(R.id.contextmenu_copy_link_address)); Assert.assertNotNull(menu.findItem(R.id.contextmenu_call)); @@ -442,7 +447,7 @@ final int expectedMenuSize = 12; Menu menu = ContextMenuUtils.openContextMenu( mCustomTabActivityTestRule.getActivity().getActivityTab(), "aboutLink"); - Assert.assertEquals(expectedMenuSize, menu.size()); + assertEquals(expectedMenuSize, menu.size()); Assert.assertNotNull(menu.findItem(R.id.contextmenu_copy_link_address)); Assert.assertNotNull(menu.findItem(R.id.contextmenu_call)); @@ -484,7 +489,7 @@ final int expectedMenuSize = 12; Menu menu = ContextMenuUtils.openContextMenu( mCustomTabActivityTestRule.getActivity().getActivityTab(), "email"); - Assert.assertEquals(expectedMenuSize, menu.size()); + assertEquals(expectedMenuSize, menu.size()); Assert.assertNotNull(menu.findItem(R.id.contextmenu_copy_link_address)); Assert.assertNotNull(menu.findItem(R.id.contextmenu_call)); @@ -526,7 +531,7 @@ final int expectedMenuSize = 12; Menu menu = ContextMenuUtils.openContextMenu( mCustomTabActivityTestRule.getActivity().getActivityTab(), "tel"); - Assert.assertEquals(expectedMenuSize, menu.size()); + assertEquals(expectedMenuSize, menu.size()); Assert.assertNotNull(menu.findItem(R.id.contextmenu_copy_link_address)); Assert.assertNotNull(menu.findItem(R.id.contextmenu_call)); @@ -572,8 +577,8 @@ final int expectedMenuSize = numMenuEntries + NUM_CHROME_MENU_ITEMS; Assert.assertNotNull("App menu is not initialized: ", menu); - Assert.assertEquals(expectedMenuSize, getActualMenuSize(menu)); - Assert.assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); + assertEquals(expectedMenuSize, getActualMenuSize(menu)); + assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); Assert.assertNotNull(menu.findItem(R.id.forward_menu_id)); Assert.assertNotNull(menu.findItem(R.id.bookmark_this_page_id)); Assert.assertNotNull(menu.findItem(R.id.offline_page_id)); @@ -605,8 +610,8 @@ final int expectedMenuSize = 0; Assert.assertNotNull("App menu is not initialized: ", menu); - Assert.assertEquals(expectedMenuSize, getActualMenuSize(menu)); - Assert.assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); + assertEquals(expectedMenuSize, getActualMenuSize(menu)); + assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); } /** @@ -627,8 +632,8 @@ final int expectedMenuSize = 2; Assert.assertNotNull("App menu is not initialized: ", menu); - Assert.assertEquals(expectedMenuSize, getActualMenuSize(menu)); - Assert.assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); + assertEquals(expectedMenuSize, getActualMenuSize(menu)); + assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); Assert.assertTrue(menu.findItem(R.id.find_in_page_id).isVisible()); Assert.assertTrue(menu.findItem(R.id.reader_mode_prefs_id).isVisible()); } @@ -651,8 +656,8 @@ final int expectedMenuSize = 3; Assert.assertNotNull("App menu is not initialized: ", menu); - Assert.assertEquals(expectedMenuSize, getActualMenuSize(menu)); - Assert.assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); + assertEquals(expectedMenuSize, getActualMenuSize(menu)); + assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); Assert.assertTrue(menu.findItem(R.id.find_in_page_id).isVisible()); Assert.assertNotNull(menu.findItem(R.id.request_desktop_site_row_menu_id)); @@ -661,7 +666,7 @@ Assert.assertNotNull(icon_row.hasSubMenu()); SubMenu icon_row_menu = icon_row.getSubMenu(); final int expectedIconMenuSize = 4; - Assert.assertEquals(expectedIconMenuSize, getVisibleMenuSize(icon_row_menu)); + assertEquals(expectedIconMenuSize, getVisibleMenuSize(icon_row_menu)); Assert.assertNotNull(icon_row_menu.findItem(R.id.forward_menu_id)); Assert.assertNotNull(icon_row_menu.findItem(R.id.bookmark_this_page_id)); Assert.assertNotNull(icon_row_menu.findItem(R.id.info_menu_id)); @@ -703,8 +708,8 @@ Menu menu = mCustomTabActivityTestRule.getMenu(); final int expectedMenuSize = MAX_MENU_CUSTOM_ITEMS + NUM_CHROME_MENU_ITEMS; Assert.assertNotNull("App menu is not initialized: ", menu); - Assert.assertEquals(expectedMenuSize, getActualMenuSize(menu)); - Assert.assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); + assertEquals(expectedMenuSize, getActualMenuSize(menu)); + assertEquals(expectedMenuSize, getVisibleMenuSize(menu)); } /** @@ -882,7 +887,7 @@ Assert.assertTrue( "A custom tab toolbar is never shown", toolbarView instanceof CustomTabToolbar); CustomTabToolbar toolbar = (CustomTabToolbar) toolbarView; - Assert.assertEquals(expectedColor, toolbar.getBackground().getColor()); + assertEquals(expectedColor, toolbar.getBackground().getColor()); Assert.assertFalse(mCustomTabActivityTestRule.getActivity() .getToolbarManager() .getLocationBarModelForTesting() @@ -890,10 +895,10 @@ // TODO(https://crbug.com/871805): Use helper class to determine whether dark status icons // are supported. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - Assert.assertEquals(expectedColor, + assertEquals(expectedColor, mCustomTabActivityTestRule.getActivity().getWindow().getStatusBarColor()); } else if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) { - Assert.assertEquals(ColorUtils.getDarkenedColorForStatusBar(expectedColor), + assertEquals(ColorUtils.getDarkenedColorForStatusBar(expectedColor), mCustomTabActivityTestRule.getActivity().getWindow().getStatusBarColor()); } } @@ -1008,7 +1013,7 @@ CustomTabsSessionToken token = CustomTabsSessionToken.getSessionTokenFromIntent(intent); Assert.assertTrue(connection.updateVisuals(token, updateVisualsBundle)); - Assert.assertEquals("Bestest testest", actionButton.getContentDescription()); + assertEquals("Bestest testest", actionButton.getContentDescription()); } /** @@ -1041,7 +1046,7 @@ CustomTabToolbar toolbar = (CustomTabToolbar) toolbarView; final ImageButton actionButton = toolbar.getCustomActionButtonForTest(0); Assert.assertNotNull("Action button not found", actionButton); - Assert.assertEquals("Shown", actionButton.getContentDescription()); + assertEquals("Shown", actionButton.getContentDescription()); Assert.assertNull(toolbar.getCustomActionButtonForTest(1)); } @@ -1095,9 +1100,9 @@ Assert.assertTrue("Bottom Bar wrapper is not visible.", bottomBar.getVisibility() == View.VISIBLE && bottomBar.getHeight() > 0 && bottomBar.getWidth() > 0); - Assert.assertEquals("Bottom Bar showing incorrect number of buttons.", numItems, + assertEquals("Bottom Bar showing incorrect number of buttons.", numItems, bottomBar.getChildCount()); - Assert.assertEquals("Bottom bar not showing correct color", barColor, + assertEquals("Bottom bar not showing correct color", barColor, ((ColorDrawable) bottomBar.getBackground()).getColor()); for (int i = 0; i < numItems; i++) { ImageButton button = (ImageButton) bottomBar.getChildAt(i); @@ -1106,7 +1111,7 @@ Assert.assertTrue("Bottom Bar button is not visible.", button.getVisibility() == View.VISIBLE && button.getHeight() > 0 && button.getWidth() > 0); - Assert.assertEquals("Bottom Bar button does not have correct content description", + assertEquals("Bottom Bar button does not have correct content description", Integer.toString(i + 1), button.getContentDescription()); } } @@ -1143,7 +1148,7 @@ @RetryOnFailure public void testLaunchWithSession() throws Exception { CustomTabsSessionToken session = warmUpAndLaunchUrlWithSession(); - Assert.assertEquals(getActivity().getIntentDataProvider().getSession(), session); + assertEquals(getActivity().getIntentDataProvider().getSession(), session); } @Test @@ -1154,7 +1159,7 @@ final Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage); CustomTabsSessionToken session = CustomTabsSessionToken.getSessionTokenFromIntent(intent); warmUpAndLaunchUrlWithSession(intent); - Assert.assertEquals(getActivity().getIntentDataProvider().getSession(), session); + assertEquals(getActivity().getIntentDataProvider().getSession(), session); Assert.assertFalse("CustomTabContentHandler handled intent with wrong session", TestThreadUtils.runOnUiThreadBlockingNoException(() -> { return BrowserSessionContentUtils.handleBrowserServicesIntent( @@ -1204,7 +1209,7 @@ DOMUtils.clickNode(mCustomTabActivityTestRule.getWebContents(), "new_window"); openTabHelper.waitForCallback(0, 1); - Assert.assertEquals( + assertEquals( "A new tab should have been created.", 2, tabSelector.getModel(false).getCount()); } @@ -1217,19 +1222,19 @@ .getApplicationContext(); final Intent intent = CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage2); final CustomTabsSessionToken session = warmUpAndLaunchUrlWithSession(intent); - Assert.assertEquals(getActivity().getIntentDataProvider().getSession(), session); + assertEquals(getActivity().getIntentDataProvider().getSession(), session); CustomTabsConnection connection = CustomTabsConnection.getInstance(); String packageName = context.getPackageName(); final String referrer = IntentHandler.constructValidReferrerForAuthority(packageName).getUrl(); - Assert.assertEquals(referrer, connection.getReferrerForSession(session).getUrl()); + assertEquals(referrer, connection.getReferrerForSession(session).getUrl()); final Tab tab = getActivity().getActivityTab(); final CallbackHelper pageLoadFinishedHelper = new CallbackHelper(); tab.addObserver(new EmptyTabObserver() { @Override public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) { - Assert.assertEquals(referrer, params.getReferrer().getUrl()); + assertEquals(referrer, params.getReferrer().getUrl()); } @Override @@ -1262,14 +1267,14 @@ CustomTabsService.RELATION_USE_AS_ORIGIN)); final CustomTabsSessionToken session = warmUpAndLaunchUrlWithSession(intent); - Assert.assertEquals(getActivity().getIntentDataProvider().getSession(), session); + assertEquals(getActivity().getIntentDataProvider().getSession(), session); final Tab tab = getActivity().getActivityTab(); final CallbackHelper pageLoadFinishedHelper = new CallbackHelper(); tab.addObserver(new EmptyTabObserver() { @Override public void onLoadUrl(Tab tab, LoadUrlParams params, int loadType) { - Assert.assertEquals(referrer, params.getReferrer().getUrl()); + assertEquals(referrer, params.getReferrer().getUrl()); } @Override @@ -1338,7 +1343,7 @@ private static void assertSuffixedHistogramTotalCount(long expected, String histogramPrefix) { for (String suffix : new String[] {".ZoomedIn", ".ZoomedOut"}) { - Assert.assertEquals(expected, + assertEquals(expected, RecordHistogram.getHistogramTotalCountForTesting(histogramPrefix + suffix)); } } @@ -1748,7 +1753,7 @@ messageChannelHelper.waitForCallback(0); String currentMessage = "Prerendering "; // Initial title update during prerender. - Assert.assertEquals( + assertEquals( CustomTabsService.RESULT_SUCCESS, session.postMessage(currentMessage, null)); titleString = currentMessage; } @@ -1771,7 +1776,7 @@ String currentMessage = "and loading "; // Update title again and verify both updates went through with the channel still intact. - Assert.assertEquals( + assertEquals( CustomTabsService.RESULT_SUCCESS, session.postMessage(currentMessage, null)); titleString += currentMessage; @@ -1781,7 +1786,7 @@ String newMessage = "and refreshing"; // Update title again and verify both updates went through with the channel still intact. - Assert.assertEquals( + assertEquals( CustomTabsService.RESULT_SUCCESS, session.postMessage(newMessage, null)); titleString += newMessage; @@ -1819,8 +1824,8 @@ mCustomTabActivityTestRule.getActivity().getActivityTab().canGoForward()); List<HistoryItem> history = getHistory(); - Assert.assertEquals(1, history.size()); - Assert.assertEquals(mTestPage, history.get(0).getUrl()); + assertEquals(1, history.size()); + assertEquals(mTestPage, history.get(0).getUrl()); } /** Tests that calling warmup() is optional without prerendering. */ @@ -1960,7 +1965,7 @@ Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab(); String content = JavaScriptUtils.executeJavaScriptAndWaitForResult( tab.getWebContents(), "document.body.textContent"); - Assert.assertEquals("\"acookie\"", content); + assertEquals("\"acookie\"", content); } /** @@ -2047,7 +2052,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent( CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage)); - Assert.assertEquals(Uri.parse(mTestPage).getHost() + ":" + Uri.parse(mTestPage).getPort(), + assertEquals(Uri.parse(mTestPage).getHost() + ":" + Uri.parse(mTestPage).getPort(), ((EditText) getActivity().findViewById(R.id.url_bar)).getText().toString()); } @@ -2375,7 +2380,7 @@ CustomTabsTestUtils.createMinimalCustomTabIntent( InstrumentationRegistry.getTargetContext(), testUrl)); Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Assert.assertEquals(mTestPage, tab.getUrl()); + assertEquals(mTestPage, tab.getUrl()); } /** @@ -2393,7 +2398,7 @@ CustomTabsTestUtils.createMinimalCustomTabIntent( InstrumentationRegistry.getTargetContext(), testUrl)); Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Assert.assertEquals(testUrl, tab.getUrl()); + assertEquals(testUrl, tab.getUrl()); } /** @@ -2414,7 +2419,7 @@ CustomTabsTestUtils.createMinimalCustomTabIntent( InstrumentationRegistry.getTargetContext(), testUrl)); Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Assert.assertEquals(testUrl, tab.getUrl()); + assertEquals(testUrl, tab.getUrl()); } /** @@ -2433,7 +2438,7 @@ CustomTabsTestUtils.createMinimalCustomTabIntent( InstrumentationRegistry.getTargetContext(), testUrl)); Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Assert.assertEquals(testUrl, tab.getUrl()); + assertEquals(testUrl, tab.getUrl()); } /** @@ -2451,7 +2456,7 @@ CustomTabsTestUtils.createMinimalCustomTabIntent( InstrumentationRegistry.getTargetContext(), testUrl)); Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Assert.assertEquals(testUrl, tab.getUrl()); + assertEquals(testUrl, tab.getUrl()); } /** Maybe prerenders a URL with a referrer, then launch it with another one. */ @@ -2504,9 +2509,9 @@ Assert.assertFalse(tab.canGoForward()); List<HistoryItem> history = getHistory(); - Assert.assertEquals(2, history.size()); - Assert.assertEquals(mTestPage2, history.get(0).getUrl()); - Assert.assertEquals(mTestPage, history.get(1).getUrl()); + assertEquals(2, history.size()); + assertEquals(mTestPage2, history.get(0).getUrl()); + assertEquals(mTestPage, history.get(1).getUrl()); } /** @@ -2527,6 +2532,57 @@ verifyHistoryAfterHiddenTab(false); } + @Test + @SmallTest + public void closeButton_navigatesToLandingPage() throws InterruptedException, TimeoutException { + Context context = InstrumentationRegistry.getInstrumentation() + .getTargetContext() + .getApplicationContext(); + Intent intent = CustomTabsTestUtils + .createMinimalCustomTabIntent(context, mTestServer.getURL(TARGET_BLANK_TEST_PAGE)); + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); + + CustomTabActivity activity = mCustomTabActivityTestRule.getActivity(); + Assert.assertEquals(activity.getCurrentTabModel().getCount(), 1); + + // The link we click will take us to another page. Set the initial page as the landing page. + activity.getComponent().resolveNavigationController().setLandingPageOnCloseCriterion( + url -> url.contains(TARGET_BLANK_TEST_PAGE)); + + DOMUtils.clickNode(activity.getActivityTab().getWebContents(), "target_blank_link"); + CriteriaHelper.pollUiThread(Criteria.equals(2, + () -> activity.getCurrentTabModel().getCount())); + + ClickUtils.clickButton(activity.findViewById(R.id.close_button)); + + CriteriaHelper.pollUiThread(Criteria.equals(1, + () -> activity.getCurrentTabModel().getCount())); + assertFalse(activity.isFinishing()); + } + + @Test + @SmallTest + public void closeButton_closesActivityIfNoLandingPage() + throws InterruptedException, TimeoutException { + Context context = InstrumentationRegistry.getInstrumentation() + .getTargetContext() + .getApplicationContext(); + Intent intent = CustomTabsTestUtils + .createMinimalCustomTabIntent(context, mTestServer.getURL(TARGET_BLANK_TEST_PAGE)); + mCustomTabActivityTestRule.startCustomTabActivityWithIntent(intent); + + CustomTabActivity activity = mCustomTabActivityTestRule.getActivity(); + Assert.assertEquals(activity.getCurrentTabModel().getCount(), 1); + + DOMUtils.clickNode(activity.getActivityTab().getWebContents(), "target_blank_link"); + CriteriaHelper.pollUiThread(Criteria.equals(2, + () -> activity.getCurrentTabModel().getCount())); + + ClickUtils.clickButton(activity.findViewById(R.id.close_button)); + + CriteriaHelper.pollUiThread(activity::isFinishing); + } + private void verifyHistoryAfterHiddenTab(boolean speculationWasAHit) throws Exception { String speculationUrl = mTestPage; String navigationUrl = speculationWasAHit ? mTestPage : mTestPage2; @@ -2548,8 +2604,8 @@ Assert.assertFalse(tab.canGoForward()); List<HistoryItem> history = getHistory(); - Assert.assertEquals(1, history.size()); - Assert.assertEquals(navigationUrl, history.get(0).getUrl()); + assertEquals(1, history.size()); + assertEquals(navigationUrl, history.get(0).getUrl()); } private void mayLaunchUrlWithoutWarmup(boolean useHiddenTab) throws InterruptedException { @@ -2565,7 +2621,7 @@ mCustomTabActivityTestRule.startCustomTabActivityWithIntent( CustomTabsTestUtils.createMinimalCustomTabIntent(context, mTestPage)); Tab tab = mCustomTabActivityTestRule.getActivity().getActivityTab(); - Assert.assertEquals(mTestPage, tab.getUrl()); + assertEquals(mTestPage, tab.getUrl()); } private ChromeActivity reparentAndVerifyTab() throws InterruptedException { @@ -2601,12 +2657,12 @@ && newActivity.getActivityTab().equals(tabToBeReparented); } })); - Assert.assertEquals(newActivity.getWindowAndroid(), tabToBeReparented.getWindowAndroid()); - Assert.assertEquals(newActivity.getWindowAndroid(), + assertEquals(newActivity.getWindowAndroid(), tabToBeReparented.getWindowAndroid()); + assertEquals(newActivity.getWindowAndroid(), tabToBeReparented.getWebContents().getTopLevelNativeWindow()); Assert.assertFalse( tabToBeReparented.getDelegateFactory() instanceof CustomTabDelegateFactory); - Assert.assertEquals("The tab should never be hidden during the reparenting process", 0, + assertEquals("The tab should never be hidden during the reparenting process", 0, tabHiddenHelper.getCallCount()); Assert.assertFalse(tabToBeReparented.isCurrentlyACustomTab()); tabToBeReparented.removeObserver(observer); @@ -2629,7 +2685,7 @@ public void extraCallback(String callbackName, Bundle args) { if (callbackName.equals(CustomTabsConnection.ON_WARMUP_COMPLETED)) return; - Assert.assertEquals(CustomTabsConnection.PAGE_LOAD_METRICS_CALLBACK, callbackName); + assertEquals(CustomTabsConnection.PAGE_LOAD_METRICS_CALLBACK, callbackName); if (-1 != args.getLong(PageLoadMetrics.EFFECTIVE_CONNECTION_TYPE, -1)) { sawNetworkQualityEstimates.set(true); } @@ -2684,7 +2740,7 @@ } catch (AssertionError e) { // Expected. } - Assert.assertEquals(-1L, (long) firstContentfulPaintMs.get()); + assertEquals(-1L, (long) firstContentfulPaintMs.get()); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java index 8329563..c37585a9 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/CloseButtonNavigatorTest.java
@@ -4,8 +4,13 @@ package org.chromium.chrome.browser.customtabs; +import static junit.framework.Assert.assertEquals; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -15,36 +20,76 @@ import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; +import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabController; +import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider; +import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.NavigationController; import org.chromium.content_public.browser.NavigationEntry; import org.chromium.content_public.browser.NavigationHistory; +import org.chromium.content_public.browser.WebContents; + +import java.util.Stack; /** * Tests for {@link CloseButtonNavigator}. */ @RunWith(BlockJUnit4ClassRunner.class) public class CloseButtonNavigatorTest { - @Mock public NavigationController mNavigationController; - private final NavigationHistory mNavigationHistory = new NavigationHistory(); + @Mock public CustomTabActivityTabController mTabController; + @Mock public CustomTabActivityTabProvider mTabProvider; - private final CloseButtonNavigator mCloseButtonNavigator = new CloseButtonNavigator(); + // private final List<Tab> mTabs = new ArrayList<>(); + private final Stack<Tab> mTabs = new Stack<>(); + private CloseButtonNavigator mCloseButtonNavigator; @Before public void setUp() { MockitoAnnotations.initMocks(this); - when(mNavigationController.getNavigationHistory()).thenReturn(mNavigationHistory); + mCloseButtonNavigator = new CloseButtonNavigator(mTabController, mTabProvider); + + // Set up our mTabs to act as the mock tab model: + // - mTabController.closeTab removes the top tab. + // - mTabProvider.getTab returns the top tab. + Mockito.doAnswer((invocation) -> { + mTabs.pop(); + return null; // Annoyingly we have to return something. + }).when(mTabController).closeTab(); + when(mTabProvider.getTab()).thenAnswer(invocation -> { + if (mTabs.empty()) return null; + return mTabs.peek(); + }); } - private void addSitesToHistory(String... urls) { + private Tab createTabWithNavigationHistory(String... urls) { + NavigationHistory history = new NavigationHistory(); + for (String url : urls) { - mNavigationHistory.addEntry(new NavigationEntry(0, url, "", "", "", "", null, 0, 0)); + history.addEntry(new NavigationEntry(0, url, "", "", "", "", null, 0, 0)); } // Point to the most recent entry in history. - mNavigationHistory.setCurrentEntryIndex(mNavigationHistory.getEntryCount() - 1); + history.setCurrentEntryIndex(history.getEntryCount() - 1); + + Tab tab = mock(Tab.class); + WebContents webContents = mock(WebContents.class); + NavigationController navigationController = mock(NavigationController.class); + + when(tab.getUrl()).thenAnswer(invocation -> + history.getEntryAtIndex(history.getCurrentEntryIndex()).getUrl()); + when(tab.getWebContents()).thenReturn(webContents); + when(webContents.getNavigationController()).thenReturn(navigationController); + when(navigationController.getNavigationHistory()).thenReturn(history); + + return tab; + } + + private NavigationController currentTabsNavigationController() { + // The navigation controller will be a mock object created in the above method. + return mTabs.peek().getWebContents().getNavigationController(); } /** Example criteria. */ @@ -53,63 +98,142 @@ } @Test - public void noCriteria() { - addSitesToHistory( + public void noCriteria_singleTab() { + mTabs.push(createTabWithNavigationHistory( "www.blue.com/page1", "www.blue.com/page2" - ); + )); - mCloseButtonNavigator.navigateOnClose(mNavigationController); + mCloseButtonNavigator.navigateOnClose(); - verify(mNavigationController, never()).goToNavigationIndex(anyInt()); + assertTrue(mTabs.empty()); } @Test - public void matchingUrl() { - addSitesToHistory( + public void noCriteria_multipleTabs() { + mTabs.push(createTabWithNavigationHistory( "www.blue.com/page1")); + mTabs.push(createTabWithNavigationHistory( "www.blue.com/page2")); + + mCloseButtonNavigator.navigateOnClose(); + + assertTrue(mTabs.empty()); + } + + @Test + public void noMatchingUrl_singleTab() { + mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed); + mTabs.push(createTabWithNavigationHistory( + "www.blue.com/page1", + "www.blue.com/page2" + )); + + mCloseButtonNavigator.navigateOnClose(); + + assertTrue(mTabs.empty()); + } + + @Test + public void noMatchingUrl_multipleTabs() { + mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed); + mTabs.push(createTabWithNavigationHistory( "www.blue.com/page1")); + mTabs.push(createTabWithNavigationHistory( "www.blue.com/page2")); + + mCloseButtonNavigator.navigateOnClose(); + + assertTrue(mTabs.empty()); + } + + @Test + public void matchingUrl_singleTab() { + mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed); + mTabs.push(createTabWithNavigationHistory( "www.red.com/page1", "www.red.com/page2", "www.blue.com/page1", "www.blue.com/page2" - ); + )); - mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed); - mCloseButtonNavigator.navigateOnClose(mNavigationController); + mCloseButtonNavigator.navigateOnClose(); - verify(mNavigationController).goToNavigationIndex(eq(1)); // www.red.com/page2 - // Verify that it wasn't called with any other index. - verify(mNavigationController).goToNavigationIndex(anyInt()); + assertFalse(mTabs.isEmpty()); + verify(currentTabsNavigationController()).goToNavigationIndex(eq(1)); + // Ensure it was only called with that value. + verify(currentTabsNavigationController()).goToNavigationIndex(anyInt()); } @Test - public void noMatchingUrl() { - addSitesToHistory( + public void matchingUrl_startOfNextTab() { + mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed); + mTabs.push(createTabWithNavigationHistory( + "www.red.com/page1", + "www.red.com/page2" + )); + mTabs.push(createTabWithNavigationHistory( "www.blue.com/page1", "www.blue.com/page2" - ); + )); - mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed); - mCloseButtonNavigator.navigateOnClose(mNavigationController); + mCloseButtonNavigator.navigateOnClose(); - verify(mNavigationController, never()).goToNavigationIndex(anyInt()); + assertEquals(1, mTabs.size()); + verify(currentTabsNavigationController(), never()).goToNavigationIndex(anyInt()); } @Test - public void inMiddleOfHistory() { - addSitesToHistory( + public void matchingUrl_middleOfNextTab() { + mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed); + mTabs.push(createTabWithNavigationHistory( + "www.red.com/page1", + "www.blue.com/page1" + )); + mTabs.push(createTabWithNavigationHistory( + "www.blue.com/page2", + "www.blue.com/page3" + )); + + mCloseButtonNavigator.navigateOnClose(); + + assertEquals(1, mTabs.size()); + verify(currentTabsNavigationController()).goToNavigationIndex(eq(0)); + verify(currentTabsNavigationController()).goToNavigationIndex(anyInt()); + } + + @Test + public void middleOfHistory() { + mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed); + mTabs.push(createTabWithNavigationHistory( "www.red.com/page1", "www.red.com/page2", "www.blue.com/page1", "www.blue.com/page2", "www.red.com/page3" - ); - mNavigationHistory.setCurrentEntryIndex(3); // www.blue.com/page2 + )); + mTabs.peek().getWebContents().getNavigationController().getNavigationHistory() + .setCurrentEntryIndex(3); + + mCloseButtonNavigator.navigateOnClose(); + + assertEquals(1, mTabs.size()); + verify(currentTabsNavigationController()).goToNavigationIndex(eq(1)); + verify(currentTabsNavigationController()).goToNavigationIndex(anyInt()); + } + + @Test + public void navigateFromLandingPage() { mCloseButtonNavigator.setLandingPageCriteria(CloseButtonNavigatorTest::isRed); - mCloseButtonNavigator.navigateOnClose(mNavigationController); + mTabs.push(createTabWithNavigationHistory( + "www.red.com/page1", + "www.red.com/page2", + "www.blue.com/page1", + "www.blue.com/page2", + "www.red.com/page3" + )); - verify(mNavigationController).goToNavigationIndex(eq(1)); // www.red.com/page2 - // Verify that it wasn't called with any other index. - verify(mNavigationController).goToNavigationIndex(anyInt()); + mCloseButtonNavigator.navigateOnClose(); + + assertEquals(1, mTabs.size()); + verify(currentTabsNavigationController()).goToNavigationIndex(eq(1)); + verify(currentTabsNavigationController()).goToNavigationIndex(anyInt()); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationControllerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationControllerTest.java index 272af9ed..4b698d1 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationControllerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationControllerTest.java
@@ -64,20 +64,6 @@ } @Test - public void doesntFinish_IfCloseButtonNavigatorHandlesClose() { - when(env.closeButtonNavigator.navigateOnClose(any())).thenReturn(true); - mNavigationController.navigateOnClose(); - verify(mFinishHandler, never()).onFinish(anyInt()); - } - - @Test - public void closesTab_IfCloseButtonNavigatorDoesntHandleClose() { - when(env.closeButtonNavigator.navigateOnClose(any())).thenReturn(false); - mNavigationController.navigateOnClose(); - verify(mFinishHandler).onFinish(eq(FinishReason.USER_NAVIGATION)); - } - - @Test public void handlesBackNavigation_IfExternalBackHandlerRejectsSynchronously() { mNavigationController.setBackHandler(notHandledRunnable -> false); mNavigationController.navigateOnBack();
diff --git a/chrome/android/profiles/newest.txt b/chrome/android/profiles/newest.txt index cc99f630..e6b4539 100644 --- a/chrome/android/profiles/newest.txt +++ b/chrome/android/profiles/newest.txt
@@ -1 +1 @@ -chromeos-chrome-amd64-75.0.3756.0_rc-r1-merged.afdo.bz2 \ No newline at end of file +chromeos-chrome-amd64-75.0.3757.0_rc-r1-merged.afdo.bz2 \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 9fbda13..d260a8b 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4037,6 +4037,10 @@ FEATURE_VALUE_TYPE(features::kInSessionPasswordChange)}, #endif // OS_CHROMEOS + {"enable-portals", flag_descriptions::kEnablePortalsName, + flag_descriptions::kEnablePortalsDescription, kOsAll, + FEATURE_VALUE_TYPE(blink::features::kPortals)}, + // NOTE: Adding a new flag requires adding a corresponding entry to enum // "LoginCustomFlags" in tools/metrics/histograms/enums.xml. See "Flag // Histograms" in tools/metrics/histograms/README.md (run the
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc index f979d52..d7ef52a 100644 --- a/chrome/browser/apps/guest_view/web_view_browsertest.cc +++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
@@ -2232,7 +2232,13 @@ // This test ensures that closing app window on 'loadcommit' does not crash. // The test launches an app with guest and closes the window on loadcommit. It // then launches the app window again. The process is repeated 3 times. -IN_PROC_BROWSER_TEST_F(WebViewTest, CloseOnLoadcommit) { +// TODO(crbug.com/949923): The test is flaky (crash) on ChromeOS debug and ASan/LSan +#if defined(OS_CHROMEOS) && (!defined(NDEBUG) || defined(ADDRESS_SANITIZER)) +#define MAYBE_CloseOnLoadcommit DEFINE_CloseOnLoadcommit +#else +#define MAYBE_CloseOnLoadcommit CloseOnLoadcommit +#endif +IN_PROC_BROWSER_TEST_F(WebViewTest, MAYBE_CloseOnLoadcommit) { LoadAndLaunchPlatformApp("web_view/close_on_loadcommit", "done-close-on-loadcommit"); }
diff --git a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc b/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc index a389cc6..7506c06 100644 --- a/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc +++ b/chrome/browser/chromeos/child_accounts/event_based_status_reporting_service_unittest.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/macros.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/time/time.h" #include "chrome/browser/chromeos/child_accounts/consumer_status_reporting_service.h" #include "chrome/browser/chromeos/child_accounts/consumer_status_reporting_service_factory.h" @@ -17,6 +18,7 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/browser/supervised_user/supervised_user_constants.h" #include "chrome/browser/ui/app_list/arc/arc_app_test.h" +#include "chrome/common/chrome_features.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/power/fake_power_manager_client.h" #include "chromeos/dbus/system_clock/system_clock_client.h" @@ -89,6 +91,11 @@ void SetUp() override { PowerManagerClient::InitializeFake(); SystemClockClient::InitializeFake(); + + // TODO(agawronska): To enable this we need LoginScreenClient, but it causes + // test crashes on network connection change. + scoped_feature_list_.InitAndDisableFeature(features::kParentAccessCode); + profile_ = std::make_unique<TestingProfile>(); profile_.get()->SetSupervisedUserId(supervised_users::kChildAccountSUID); arc_test_.SetUp(profile()); @@ -169,6 +176,7 @@ test_consumer_status_reporting_service_; TestingScreenTimeController* test_screen_time_controller_; session_manager::SessionManager session_manager_; + base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<EventBasedStatusReportingService> service_; DISALLOW_COPY_AND_ASSIGN(EventBasedStatusReportingServiceTest);
diff --git a/chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service_unittest.cc b/chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service_unittest.cc index fa0ddc4..8cf7e18 100644 --- a/chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service_unittest.cc +++ b/chrome/browser/chromeos/child_accounts/parent_access_code/parent_access_service_unittest.cc
@@ -115,7 +115,7 @@ EXPECT_EQ(failure_count, validation_results_.failure_count); } - // ParentAccessService depends on LoginScreenClient and the1refore requires + // ParentAccessService depends on LoginScreenClient and therefore requires // objects in the following block to be initialized early (order matters). content::TestBrowserThreadBundle thread_bundle_; content::TestServiceManagerContext context_;
diff --git a/chrome/browser/chromeos/input_method/input_method_engine.cc b/chrome/browser/chromeos/input_method/input_method_engine.cc index 38b3fdc..f084489 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine.cc
@@ -133,11 +133,10 @@ private: void OnConnectionLost() { - // After the connection to |ImeEngineFactoryRegistry| is broken, break the - // connection to the client, so that the client can reconnect through Window - // Service. - engine_binding_.Close(); - engine_client_.reset(); + // After the connection to |ImeEngineFactoryRegistry| is broken, notifies + // the client to reconnect through Window Service. + if (engine_client_) + engine_client_->Reconnect(); } InputMethodEngine* engine_; @@ -370,7 +369,8 @@ uint32_t cursor_pos, bool is_visible) { if (mojo_helper_->IsConnected()) { - NOTIMPLEMENTED_LOG_ONCE(); + mojo_helper_->engine_client()->UpdateCompositionText( + composition_text, cursor_pos, is_visible); } else { ui::IMEInputContextHandlerInterface* input_context = ui::IMEBridge::Get()->GetInputContextHandler(); @@ -384,7 +384,7 @@ const std::string& text) { bool committed = false; if (mojo_helper_->IsConnected()) { - NOTIMPLEMENTED_LOG_ONCE(); + mojo_helper_->engine_client()->CommitText(text); } else { ui::IMEInputContextHandlerInterface* input_context = ui::IMEBridge::Get()->GetInputContextHandler(); @@ -407,7 +407,8 @@ int offset, size_t number_of_chars) { if (mojo_helper_->IsConnected()) { - NOTIMPLEMENTED_LOG_ONCE(); + mojo_helper_->engine_client()->DeleteSurroundingText(offset, + number_of_chars); } else { ui::IMEInputContextHandlerInterface* input_context = ui::IMEBridge::Get()->GetInputContextHandler(); @@ -429,7 +430,7 @@ bool sent = false; if (mojo_helper_->IsConnected()) { - NOTIMPLEMENTED_LOG_ONCE(); + mojo_helper_->engine_client()->SendKeyEvent(ui::Event::Clone(*event)); } else { ui::IMEInputContextHandlerInterface* input_context = ui::IMEBridge::Get()->GetInputContextHandler();
diff --git a/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc b/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc index f055275..93088e8 100644 --- a/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc +++ b/chrome/browser/chromeos/input_method/input_method_engine_unittest.cc
@@ -187,8 +187,22 @@ return ptr; } + bool commit_text_called() const { return commit_text_called_; } + private: + // ime::mojom::ImeEngineClient: + void CommitText(const std::string& text) override { + commit_text_called_ = true; + } + void UpdateCompositionText(const ui::CompositionText& composition_text, + uint32_t cursor_pos, + bool visible) override {} + void DeleteSurroundingText(int32_t offset, uint32_t length) override {} + void SendKeyEvent(std::unique_ptr<ui::Event> key_event) override {} + void Reconnect() override {} + mojo::Binding<ime::mojom::ImeEngineClient> binding_; + bool commit_text_called_ = false; DISALLOW_COPY_AND_ASSIGN(TestImeEngineClient); }; @@ -404,6 +418,12 @@ false)); engine_ptr.FlushForTesting(); EXPECT_EQ(ACTIVATE | ONFOCUS, observer_->GetCallsBitmapAndReset()); + + int context = engine_->GetContextIdForTesting(); + std::string error; + engine_->CommitText(context, "input", &error); + engine_->FlushForTesting(); + EXPECT_TRUE(client.commit_text_called()); } } // namespace input_method
diff --git a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc index 5fbf0588..4b02da0b 100644 --- a/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc +++ b/chrome/browser/chromeos/login/enrollment/enrollment_local_policy_server_browsertest.cc
@@ -18,7 +18,11 @@ #include "chrome/browser/chromeos/login/wizard_controller.h" #include "chrome/browser/chromeos/policy/browser_policy_connector_chromeos.h" #include "chrome/browser/policy/test/local_policy_test_server.h" +#include "chromeos/attestation/mock_attestation_flow.h" #include "chromeos/constants/chromeos_switches.h" +#include "chromeos/cryptohome/async_method_caller.h" +#include "chromeos/dbus/cryptohome/fake_cryptohome_client.h" +#include "chromeos/dbus/dbus_thread_manager.h" #include "components/policy/core/common/policy_switches.h" namespace chromeos { @@ -100,6 +104,17 @@ "5"); } + void SetFakeAttestationFlow() { + g_browser_process->platform_part() + ->browser_policy_connector_chromeos() + ->GetDeviceCloudPolicyInitializer() + ->SetAttestationFlowForTesting( + std::make_unique<chromeos::attestation::AttestationFlow>( + cryptohome::AsyncMethodCaller::GetInstance(), + chromeos::FakeCryptohomeClient::Get(), + std::make_unique<chromeos::attestation::FakeServerProxy>())); + } + policy::ServerBackedStateKeysBroker* state_keys_broker() { return g_browser_process->platform_part() ->browser_policy_connector_chromeos() @@ -119,11 +134,7 @@ enrollment_screen()->OnLoginDone(FakeGaiaMixin::kFakeUserEmail, FakeGaiaMixin::kFakeAuthCode); - test::OobeJS() - .CreateWaiter( - "document.getElementsByClassName('oauth-enroll-state-attribute-" - "prompt').length > 0") - ->Wait(); + OobeBaseTest::WaitForEnrollmentSuccess(); // TODO(rsorokin): Interact with attribute prompt step. EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); } @@ -184,6 +195,18 @@ OobeScreenWaiter(OobeScreen::SCREEN_DEVICE_DISABLED).Wait(); } -// TODO(rsorokin): Add test for RESTORE_MODE_REENROLLMENT_ZERO_TOUCH. +// Attestation enrollment. +IN_PROC_BROWSER_TEST_F(AutoEnrollmentLocalPolicyServer, Attestation) { + SetFakeAttestationFlow(); + EXPECT_TRUE(local_policy_mixin_.SetDeviceStateRetrievalResponse( + state_keys_broker(), + enterprise_management::DeviceStateRetrievalResponse:: + RESTORE_MODE_REENROLLMENT_ZERO_TOUCH, + kTestDomain)); + + host()->StartWizard(OobeScreen::SCREEN_AUTO_ENROLLMENT_CHECK); + OobeBaseTest::WaitForEnrollmentSuccess(); + EXPECT_TRUE(StartupUtils::IsDeviceRegistered()); +} } // namespace chromeos
diff --git a/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.cc b/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.cc index 1adf162..481199be 100644 --- a/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.cc +++ b/chrome/browser/chromeos/login/test/local_policy_test_server_mixin.cc
@@ -7,6 +7,7 @@ #include <utility> #include "base/guid.h" +#include "chrome/browser/chromeos/login/test/fake_gaia_mixin.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/policy_builder.h" #include "components/policy/core/common/policy_switches.h" @@ -22,6 +23,9 @@ managed_users.GetList().emplace_back("*"); config.SetKey("managed_users", std::move(managed_users)); + config.SetKey("robot_api_auth_code", + base::Value(FakeGaiaMixin::kFakeAuthCode)); + return config; }
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc index 635e07d..e6ce8211 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc +++ b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.cc
@@ -77,6 +77,11 @@ system_url_loader_factory_for_testing_ = system_url_loader_factory; } +void DeviceCloudPolicyInitializer::SetAttestationFlowForTesting( + std::unique_ptr<chromeos::attestation::AttestationFlow> attestation_flow) { + attestation_flow_ = std::move(attestation_flow); +} + DeviceCloudPolicyInitializer::~DeviceCloudPolicyInitializer() { DCHECK(!is_initialized_); }
diff --git a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.h b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.h index c719b14..cdffabbc 100644 --- a/chrome/browser/chromeos/policy/device_cloud_policy_initializer.h +++ b/chrome/browser/chromeos/policy/device_cloud_policy_initializer.h
@@ -125,6 +125,8 @@ std::unique_ptr<policy::SigningService> signing_service); void SetSystemURLLoaderFactoryForTesting( scoped_refptr<network::SharedURLLoaderFactory> system_url_loader_factory); + void SetAttestationFlowForTesting( + std::unique_ptr<chromeos::attestation::AttestationFlow> attestation_flow); private: // Signing class implementing the policy::SigningService interface to
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc index 1c15b51..c6abbfc0 100644 --- a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc +++ b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.cc
@@ -47,7 +47,12 @@ } // namespace -Adapter::Params::Params() {} +Adapter::Params::Params() = default; + +Adapter::AdapterDecision::AdapterDecision() = default; + +Adapter::AdapterDecision::AdapterDecision(const AdapterDecision& decision) = + default; Adapter::Adapter(Profile* profile, AlsReader* als_reader, @@ -80,7 +85,16 @@ log_als_values_->SaveToBuffer({ConvertToLog(lux), now}); - MaybeAdjustBrightness(now); + const AdapterDecision& decision = CanAdjustBrightness(now); + + if (decision.no_brightness_change_cause) + return; + + DCHECK(decision.brightness_change_cause); + DCHECK(decision.log_als_avg_stddev); + + AdjustBrightness(*decision.brightness_change_cause, + decision.log_als_avg_stddev->avg); } void Adapter::OnAlsReaderInitialized(AlsReader::AlsInitStatus status) { @@ -421,11 +435,22 @@ adapter_status_ = Status::kSuccess; } -base::Optional<Adapter::BrightnessChangeCause> Adapter::CanAdjustBrightness( - const AlsAvgStdDev& log_als_avg_stddev) const { - if (adapter_status_ != Status::kSuccess || - adapter_disabled_by_user_adjustment_) { - return base::nullopt; +Adapter::AdapterDecision Adapter::CanAdjustBrightness(base::TimeTicks now) { + DCHECK_EQ(adapter_status_, Status::kSuccess); + DCHECK(log_als_values_); + DCHECK(!als_init_time_.is_null()); + + AdapterDecision decision; + const base::Optional<AlsAvgStdDev> log_als_avg_stddev = + log_als_values_->AverageAmbientWithStdDev(now); + decision.log_als_avg_stddev = log_als_avg_stddev; + + // User has previously manually changed brightness and it (at least + // temporarily) stopped the adapter from operating. + if (adapter_disabled_by_user_adjustment_) { + decision.no_brightness_change_cause = + NoBrightnessChangeCause::kDisabledByUser; + return decision; } // Do not change brightness if it's set by the policy, but do not completely @@ -434,7 +459,38 @@ ash::prefs::kPowerAcScreenBrightnessPercent) >= 0 || profile_->GetPrefs()->GetInteger( ash::prefs::kPowerBatteryScreenBrightnessPercent) >= 0) { - return base::nullopt; + decision.no_brightness_change_cause = + NoBrightnessChangeCause::kBrightnessSetByPolicy; + return decision; + } + + if (params_.model_curve == ModelCurve::kPersonal && !personal_curve_) { + decision.no_brightness_change_cause = + NoBrightnessChangeCause::kMissingPersonalCurve; + return decision; + } + + // Wait until we've had enough ALS data to calc avg. + if (now - als_init_time_ < params_.auto_brightness_als_horizon) { + decision.no_brightness_change_cause = + NoBrightnessChangeCause::kWaitingForInitialAls; + return decision; + } + + // Check if we've waited long enough from previous brightness change (either + // by user or by model). + if (!latest_brightness_change_time_.is_null() && + now - latest_brightness_change_time_ < + params_.auto_brightness_als_horizon) { + decision.no_brightness_change_cause = + NoBrightnessChangeCause::kWaitingForAvgHorizon; + return decision; + } + + if (!log_als_avg_stddev) { + decision.no_brightness_change_cause = + NoBrightnessChangeCause::kMissingAlsData; + return decision; } if (!average_log_ambient_lux_) { @@ -443,7 +499,9 @@ // 2. brightness was changed by the user but there wasn't any ALS data. This // case should be rare. // In either case, we change brightness as soon as we have brightness. - return BrightnessChangeCause::kInitialAlsReceived; + decision.brightness_change_cause = + BrightnessChangeCause::kInitialAlsReceived; + return decision; } // The following thresholds should have been set last time when brightness was @@ -451,57 +509,41 @@ DCHECK(brightening_threshold_); DCHECK(darkening_threshold_); - if (log_als_avg_stddev.avg > *brightening_threshold_ && - log_als_avg_stddev.stddev <= params_.brightening_log_lux_threshold * - params_.stabilization_threshold) { - return BrightnessChangeCause::kBrightneningThresholdExceeded; + if (log_als_avg_stddev->avg > *brightening_threshold_) { + if (log_als_avg_stddev->stddev <= params_.brightening_log_lux_threshold * + params_.stabilization_threshold) { + decision.brightness_change_cause = + BrightnessChangeCause::kBrightneningThresholdExceeded; + return decision; + } + decision.no_brightness_change_cause = + NoBrightnessChangeCause::kFluctuatingAlsIncrease; + return decision; } - if (log_als_avg_stddev.avg < *darkening_threshold_ && - log_als_avg_stddev.stddev <= params_.darkening_log_lux_threshold * - params_.stabilization_threshold) { - return BrightnessChangeCause::kDarkeningThresholdExceeded; + if (log_als_avg_stddev->avg < *darkening_threshold_) { + if (log_als_avg_stddev->stddev <= + params_.darkening_log_lux_threshold * params_.stabilization_threshold) { + decision.brightness_change_cause = + BrightnessChangeCause::kDarkeningThresholdExceeded; + return decision; + } + decision.no_brightness_change_cause = + NoBrightnessChangeCause::kFluctuatingAlsDecrease; + return decision; } - return base::nullopt; + decision.no_brightness_change_cause = + NoBrightnessChangeCause::kMinimalAlsChange; + return decision; } -void Adapter::MaybeAdjustBrightness(base::TimeTicks now) { - DCHECK_EQ(adapter_status_, Status::kSuccess); - DCHECK(log_als_values_); - DCHECK(!als_init_time_.is_null()); - // Wait until we've had enough ALS data to calc avg. - if (now - als_init_time_ < params_.auto_brightness_als_horizon) - return; - - // Check if we've waited long enough from previous brightness change (either - // by user or by model). - if (!latest_brightness_change_time_.is_null() && - now - latest_brightness_change_time_ < - params_.auto_brightness_als_horizon) - return; - - const base::Optional<AlsAvgStdDev> log_als_avg_stddev = - log_als_values_->AverageAmbientWithStdDev(now); - if (!log_als_avg_stddev) - return; - - const base::Optional<BrightnessChangeCause> brightness_change_cause = - CanAdjustBrightness(*log_als_avg_stddev); - - if (!brightness_change_cause.has_value()) - return; - - const base::Optional<double> brightness = - GetBrightnessBasedOnAmbientLogLux(log_als_avg_stddev->avg); - - // This could occur if curve isn't set up (e.g. when we want to use - // personal only that's not yet available). - if (!brightness) - return; +void Adapter::AdjustBrightness(BrightnessChangeCause cause, + double log_als_avg) { + const double brightness = GetBrightnessBasedOnAmbientLogLux(log_als_avg); power_manager::SetBacklightBrightnessRequest request; - request.set_percent(*brightness); + request.set_percent(brightness); request.set_transition( power_manager::SetBacklightBrightnessRequest_Transition_GRADUAL); request.set_cause(power_manager::SetBacklightBrightnessRequest_Cause_MODEL); @@ -515,27 +557,24 @@ } latest_model_brightness_change_time_ = brightness_change_time; - const BrightnessChangeCause cause = *brightness_change_cause; UMA_HISTOGRAM_ENUMERATION("AutoScreenBrightness.BrightnessChange.Cause", cause); - WriteLogMessages(log_als_avg_stddev->avg, *brightness, cause); + WriteLogMessages(log_als_avg, brightness, cause); model_brightness_change_counter_++; - OnBrightnessChanged(brightness_change_time, *brightness, - log_als_avg_stddev->avg); + OnBrightnessChanged(brightness_change_time, brightness, log_als_avg); } -base::Optional<double> Adapter::GetBrightnessBasedOnAmbientLogLux( +double Adapter::GetBrightnessBasedOnAmbientLogLux( double ambient_log_lux) const { DCHECK_EQ(adapter_status_, Status::kSuccess); switch (params_.model_curve) { case ModelCurve::kGlobal: return global_curve_->Interpolate(ambient_log_lux); case ModelCurve::kPersonal: - if (personal_curve_) - return personal_curve_->Interpolate(ambient_log_lux); - return base::nullopt; // signal brightness shouldn't be changed + DCHECK(personal_curve_); + return personal_curve_->Interpolate(ambient_log_lux); default: // We use the latest curve available. if (personal_curve_)
diff --git a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h index 27470a7..2bedcd42 100644 --- a/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h +++ b/chrome/browser/chromeos/power/auto_screen_brightness/adapter.h
@@ -122,6 +122,46 @@ kMaxValue = kDarkeningThresholdExceeded }; + // These values are persisted to logs. Entries should not be renumbered and + // numeric values should never be reused. + enum class NoBrightnessChangeCause { + kWaitingForInitialAls = 0, + kWaitingForAvgHorizon = 1, + // |log_als_values_| is empty. + kMissingAlsData = 2, + // User manually changed brightness before and it stopped adapter from + // changing brightness. + kDisabledByUser = 3, + kBrightnessSetByPolicy = 4, + // ALS increased beyond the brightening threshold, but ALS data has been + // fluctuating above the stabilization threshold. + kFluctuatingAlsIncrease = 5, + // ALS decreased beyond the darkening threshold, but ALS data has been + // fluctuating above the stabilization threshold. + kFluctuatingAlsDecrease = 6, + // ALS change is within darkening and brightening thresholds. + kMinimalAlsChange = 7, + // Adapter should only use personal curves but none is available. + kMissingPersonalCurve = 8, + kMaxValue = kMissingPersonalCurve + }; + + struct AdapterDecision { + AdapterDecision(); + AdapterDecision(const AdapterDecision& decision); + // If |no_brightness_change_cause| is not nullopt, then brightness + // should not be changed. + // If |brightness_change_cause| is not nullopt, then brightness should be + // changed. In this case |log_als_avg_stddev| should not be nullopt. + // Exactly one of |no_brightness_change_cause| and + // |brightness_change_cause| should be non-nullopt. + // |log_als_avg_stddev| may be set even when brightness should not be + // changed. It is only nullopt if there is no ALS data in the data cache. + base::Optional<NoBrightnessChangeCause> no_brightness_change_cause; + base::Optional<BrightnessChangeCause> brightness_change_cause; + base::Optional<AlsAvgStdDev> log_als_avg_stddev; + }; + Adapter(Profile* profile, AlsReader* als_reader, BrightnessMonitor* brightness_monitor, @@ -203,30 +243,23 @@ // |InitParams|. void UpdateStatus(); - // Returns a BrightnessChangeCause if the adapter can change the brightness. + // Checks whether brightness should be changed. // This is generally the case when the brightness hasn't been manually // set, we've received enough initial ambient light readings, and - // the ambient light has changed beyond thresholds and has stabilized. - // Returns nullopt if it shouldn't change the brightness. - base::Optional<BrightnessChangeCause> CanAdjustBrightness( - const AlsAvgStdDev& log_als_avg_stddev) const; + // the ambient light has changed beyond thresholds and has stabilized, and + // also if personal curve exists (if param says we should only use personal + // curve). + AdapterDecision CanAdjustBrightness(base::TimeTicks now); - // Called when ambient light changes. It only changes screen brightness if - // |CanAdjustBrightness| returns true and a required curve is set up: - // if the required curve is personal but no personal curve is available, then - // brightness won't be changed. - // It will call |OnBrightnessChanged| if brightness is actually changed. - // |now| should be the timestamp when ALS reading comes in, i.e. when - // |OnAmbientLightUpdated| is called. |OnAmbientLightUpdated| is the event - // that triggers the call of |MaybeAdjustBrightness|. - void MaybeAdjustBrightness(base::TimeTicks now); + // Changes the brightness. In addition to asking powerd to + // change brightness, it also calls |OnBrightnessChanged| and writes to logs. + void AdjustBrightness(BrightnessChangeCause cause, double log_als_avg); // Calculates brightness from given |ambient_log_lux| based on either // |global_curve_| or |personal_curve_| (as specified by the experiment - // params). Returns nullopt if a personal curve should be used but it's not - // available. - base::Optional<double> GetBrightnessBasedOnAmbientLogLux( - double ambient_log_lux) const; + // params). It's only safe to call this method when |CanAdjustBrightness| + // returns a |BrightnessChangeCause| in its decision. + double GetBrightnessBasedOnAmbientLogLux(double ambient_log_lux) const; // Called when brightness is changed by the model or user. This function // updates |latest_brightness_change_time_|, |current_brightness_|. If @@ -239,7 +272,7 @@ double new_brightness_percent, base::Optional<double> new_log_als); - // Called by |MaybeAdjustBrightness| when brightness should be changed. + // Called by |AdjustBrightness| when brightness should be changed. void WriteLogMessages(double new_log_als, double new_brightness, BrightnessChangeCause cause) const;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index ca7f4d93..8baab65 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -1522,6 +1522,11 @@ "expiry_milestone": 78 }, { + "name": "enable-portals", + "owners": [ "adithyas", "jbroman", "lfg" ], + "expiry_milestone": 80 + }, + { "name": "enable-previews-android-omnibox-ui", "owners": [ "//components/data_reduction_proxy/OWNERS" ], "expiry_milestone": 76
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 4c26b02..156682f 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -747,6 +747,12 @@ const char kEnableNewDownloadBackendDescription[] = "Enables the new download backend that uses offline content provider"; +const char kEnablePortalsName[] = "Enable Portals."; +const char kEnablePortalsDescription[] = + "Portals are an experimental web platform feature that allows embedding" + " and seamless transitions between pages." + " See https://github.com/WICG/portals and https://wicg.github.io/portals/"; + const char kEnableNotificationScrollBarName[] = "Enable notification list scroll bar"; const char kEnableNotificationScrollBarDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 2c26f27..38e8643 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -512,6 +512,9 @@ extern const char kEnableNewDownloadBackendName[]; extern const char kEnableNewDownloadBackendDescription[]; +extern const char kEnablePortalsName[]; +extern const char kEnablePortalsDescription[]; + extern const char kEnablePictureInPictureName[]; extern const char kEnablePictureInPictureDescription[];
diff --git a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc index cc91963..041cb6d1 100644 --- a/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc +++ b/chrome/browser/page_load_metrics/observers/use_counter_page_load_metrics_observer.cc
@@ -67,6 +67,14 @@ "list. See https://www.chromestatus.com/feature/5706745674465280 for " "more details."); return; + case WebFeature::kDownloadInAdFrameWithoutUserGesture: + rfh->AddMessageToConsole( + blink::mojom::ConsoleMessageLevel::kWarning, + "[Deprecation] Download in ad frame without user activation is " + "deprecated and will be removed in M76, around July 2019. See " + "https://www.chromestatus.com/feature/6311883621531648 for more " + "details."); + return; default: return;
diff --git a/chrome/browser/password_manager/password_manager_browsertest.cc b/chrome/browser/password_manager/password_manager_browsertest.cc index f1392f5f..1dff807 100644 --- a/chrome/browser/password_manager/password_manager_browsertest.cc +++ b/chrome/browser/password_manager/password_manager_browsertest.cc
@@ -1154,7 +1154,8 @@ EXPECT_FALSE(prompt_observer->IsSavePromptShownAutomatically()); } -IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, DeleteFrameBeforeSubmit) { +// TODO(crbug.com/949908) The test is flaky (crashing) on all platforms. +IN_PROC_BROWSER_TEST_F(PasswordManagerBrowserTest, DISABLED_DeleteFrameBeforeSubmit) { NavigateToFile("/password/multi_frames.html"); NavigationObserver observer(WebContents());
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc index 246c16f..dae724cc 100644 --- a/chrome/browser/performance_manager/performance_manager.cc +++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -8,6 +8,7 @@ #include <utility> #include "base/feature_list.h" +#include "base/logging.h" #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/task/post_task.h" @@ -71,12 +72,12 @@ instance->task_runner_->DeleteSoon(FROM_HERE, instance.release()); } -void PerformanceManager::DistributeMeasurementBatch( - std::unique_ptr<ProcessResourceMeasurementBatch> batch) { +void PerformanceManager::CallOnGraph(const base::Location& from_here, + GraphCallback callback) { + DCHECK(!callback.is_null()); task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&PerformanceManager::DistributeMeasurementBatchImpl, - base::Unretained(this), std::move(batch))); + FROM_HERE, base::BindOnce(&PerformanceManager::CallOnGraphImpl, + base::Unretained(this), std::move(callback))); } std::unique_ptr<FrameNodeImpl> PerformanceManager::CreateFrameNode( @@ -186,6 +187,10 @@ connection ? connection->GetConnector()->Clone() : nullptr)); } +void PerformanceManager::CallOnGraphImpl(GraphCallback graph_callback) { + std::move(graph_callback).Run(&graph_); +} + void PerformanceManager::OnStartImpl( std::unique_ptr<service_manager::Connector> connector) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -226,14 +231,6 @@ service_manager::BindSourceInfo()); } -void PerformanceManager::DistributeMeasurementBatchImpl( - std::unique_ptr<ProcessResourceMeasurementBatch> batch) { - SystemNodeImpl* system_node = graph_.FindOrCreateSystemNode(); - DCHECK(system_node); - - system_node->DistributeMeasurementBatch(std::move(batch)); -} - void PerformanceManager::BindWebUIGraphDump( resource_coordinator::mojom::WebUIGraphDumpRequest request, const service_manager::BindSourceInfo& source_info) {
diff --git a/chrome/browser/performance_manager/performance_manager.h b/chrome/browser/performance_manager/performance_manager.h index f2bc634..67ba160 100644 --- a/chrome/browser/performance_manager/performance_manager.h +++ b/chrome/browser/performance_manager/performance_manager.h
@@ -10,6 +10,8 @@ #include <utility> #include <vector> +#include "base/callback.h" +#include "base/location.h" #include "base/sequence_checker.h" #include "base/sequenced_task_runner.h" #include "chrome/browser/performance_manager/graph/graph.h" @@ -28,7 +30,6 @@ namespace performance_manager { class PageNodeImpl; -struct ProcessResourceMeasurementBatch; // The performance manager is a rendezvous point for binding to performance // manager interfaces. @@ -51,17 +52,16 @@ // deletion on its sequence. static void Destroy(std::unique_ptr<PerformanceManager> instance); + // Invokes |graph_callback| on the performance manager's sequence, with the + // graph as a parameter. + using GraphCallback = base::OnceCallback<void(Graph*)>; + void CallOnGraph(const base::Location& from_here, + GraphCallback graph_callback); + // Forwards the binding request to the implementation class. template <typename Interface> void BindInterface(mojo::InterfaceRequest<Interface> request); - // Dispatches a measurement batch to the SystemNode on the performance - // sequence. This is a temporary method to support the RenderProcessProbe, - // which will soon go away as the performance measurement moves to the - // performance sequence. - void DistributeMeasurementBatch( - std::unique_ptr<ProcessResourceMeasurementBatch> batch); - // Creates a new node of the requested type and adds it to the graph. // May be called from any sequence. std::unique_ptr<FrameNodeImpl> CreateFrameNode( @@ -104,10 +104,9 @@ void OnStart(); void OnStartImpl(std::unique_ptr<service_manager::Connector> connector); + void CallOnGraphImpl(GraphCallback graph_callback); void BindInterfaceImpl(const std::string& interface_name, mojo::ScopedMessagePipeHandle message_pipe); - void DistributeMeasurementBatchImpl( - std::unique_ptr<ProcessResourceMeasurementBatch> batch); void BindWebUIGraphDump( resource_coordinator::mojom::WebUIGraphDumpRequest request,
diff --git a/chrome/browser/performance_manager/performance_manager_unittest.cc b/chrome/browser/performance_manager/performance_manager_unittest.cc index d96325e..b20745f 100644 --- a/chrome/browser/performance_manager/performance_manager_unittest.cc +++ b/chrome/browser/performance_manager/performance_manager_unittest.cc
@@ -38,6 +38,8 @@ task_environment_.RunUntilIdle(); } + void RunUntilIdle() { task_environment_.RunUntilIdle(); } + protected: PerformanceManager* performance_manager() { return performance_manager_.get(); @@ -103,8 +105,21 @@ performance_manager()->BatchDeleteNodes(std::move(nodes)); } +TEST_F(PerformanceManagerTest, CallOnGraph) { + // Create a page node for something to target. + std::unique_ptr<PageNodeImpl> page_node = + performance_manager()->CreatePageNode(); + + PerformanceManager::GraphCallback graph_callback = base::BindLambdaForTesting( + [&page_node](Graph* graph) { EXPECT_EQ(page_node->graph(), graph); }); + + performance_manager()->CallOnGraph(FROM_HERE, std::move(graph_callback)); + RunUntilIdle(); + + performance_manager()->DeleteNode(std::move(page_node)); +} + // TODO(siggi): More tests! // - Test the WebUI interface. -// - Test the graph introspector interface. } // namespace performance_manager
diff --git a/chrome/browser/policy/test/policy_testserver.py b/chrome/browser/policy/test/policy_testserver.py index 3b86cd0..5a16814f 100644 --- a/chrome/browser/policy/test/policy_testserver.py +++ b/chrome/browser/policy/test/policy_testserver.py
@@ -308,7 +308,8 @@ if request_type == 'register': response = self.ProcessRegister(rmsg.register_request) elif request_type == 'certificate_based_register': - response = self.ProcessCertBasedRegister(rmsg.register_request) + response = self.ProcessCertBasedRegister( + rmsg.certificate_based_register_request) elif request_type == 'api_authorization': response = self.ProcessApiAuthorization(rmsg.service_api_access_request) elif request_type == 'unregister': @@ -450,8 +451,9 @@ """ # Unwrap the request try: - req = self.UnwrapCertificateBasedDeviceRegistrationData(signed_msg) - except (Error): + req = self.UnwrapCertificateBasedDeviceRegistrationData( + signed_msg.signed_request) + except (IOError): return(400, 'Invalid request') # TODO(drcrash): Check the certificate itself. @@ -505,6 +507,12 @@ """Verifies the signature of |msg| and if it is valid, return the certificate based device registration data. If not, throws an exception. + + Args: + msg: SignedData received from the client. + + Returns: + CertificateBasedDeviceRegistrationData """ # TODO(drcrash): Verify signature. rdata = dm.CertificateBasedDeviceRegistrationData()
diff --git a/chrome/browser/resource_coordinator/render_process_probe.cc b/chrome/browser/resource_coordinator/render_process_probe.cc index 8d3eea04b..76a9b21 100644 --- a/chrome/browser/resource_coordinator/render_process_probe.cc +++ b/chrome/browser/resource_coordinator/render_process_probe.cc
@@ -10,6 +10,7 @@ #include "base/metrics/histogram_macros.h" #include "base/task/post_task.h" #include "build/build_config.h" +#include "chrome/browser/performance_manager/graph/graph.h" #include "chrome/browser/performance_manager/graph/system_node_impl.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" @@ -261,7 +262,22 @@ performance_manager::PerformanceManager::GetInstance(); if (performance_manager && !batch->measurements.empty()) - performance_manager->DistributeMeasurementBatch(std::move(batch)); + performance_manager->CallOnGraph( + FROM_HERE, + base::BindOnce( + &RenderProcessProbeImpl::DistributeMeasurementBatchToSystemNode, + std::move(batch))); +} + +// static +void RenderProcessProbeImpl::DistributeMeasurementBatchToSystemNode( + std::unique_ptr<performance_manager::ProcessResourceMeasurementBatch> batch, + performance_manager::Graph* graph) { + performance_manager::SystemNodeImpl* system_node = + graph->FindOrCreateSystemNode(); + DCHECK(system_node); + + system_node->DistributeMeasurementBatch(std::move(batch)); } } // namespace resource_coordinator
diff --git a/chrome/browser/resource_coordinator/render_process_probe.h b/chrome/browser/resource_coordinator/render_process_probe.h index 64a6114..36eadd2 100644 --- a/chrome/browser/resource_coordinator/render_process_probe.h +++ b/chrome/browser/resource_coordinator/render_process_probe.h
@@ -19,6 +19,7 @@ namespace performance_manager { struct ProcessResourceMeasurementBatch; +class Graph; } // namespace performance_manager namespace resource_coordinator { @@ -105,6 +106,11 @@ std::unique_ptr<performance_manager::ProcessResourceMeasurementBatch> batch); + static void DistributeMeasurementBatchToSystemNode( + std::unique_ptr<performance_manager::ProcessResourceMeasurementBatch> + batch, + performance_manager::Graph* graph); + // A map of currently running render process host IDs to process. // This map is accessed alternatively from the UI thread and the IO thread, // but only one of the two at a time.
diff --git a/chrome/browser/resource_coordinator/tab_metrics_logger_unittest.cc b/chrome/browser/resource_coordinator/tab_metrics_logger_unittest.cc index 5a61622..595b74c 100644 --- a/chrome/browser/resource_coordinator/tab_metrics_logger_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_metrics_logger_unittest.cc
@@ -155,7 +155,13 @@ }; // Tests has_form_entry. -TEST_F(TabMetricsLoggerTest, GetHasFormEntry) { +// TODO(crbug.com/949288): The test is flaky on ChromeOS. +#if defined(OS_CHROMEOS) +#define MAYBE_GetHasFormEntry DISABLED_GetHasFormEntry +#else +#define MAYBE_GetHasFormEntry GetHasFormEntry +#endif +TEST_F(TabMetricsLoggerTest, MAYBE_GetHasFormEntry) { EXPECT_FALSE(CurrentTabFeatures().has_form_entry); content::PageImportanceSignals signal; signal.had_form_interaction = true;
diff --git a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js index 83f5ab6..2180914 100644 --- a/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js +++ b/chrome/browser/resources/settings/printing_page/cups_edit_printer_dialog.js
@@ -204,11 +204,7 @@ * @private */ canSavePrinter_: function() { - return this.printerInfoChanged_ && - (settings.printing.isNameAndAddressValid(this.activePrinter) && - settings.printing.isPPDInfoValid( - this.activePrinter.ppdManufacturer, this.activePrinter.ppdModel, - this.activePrinter.printerPPDPath)); + return this.printerInfoChanged_ && this.isPrinterValid(); }, /** @@ -285,4 +281,15 @@ } this.userPPD_ = settings.printing.getBaseName(path); }, + + /* + * Returns true if the printer has valid name, address, and PPD. + * @return {boolean} + */ + isPrinterValid: function() { + return settings.printing.isNameAndAddressValid(this.activePrinter) && + settings.printing.isPPDInfoValid( + this.activePrinter.ppdManufacturer, this.activePrinter.ppdModel, + this.activePrinter.printerPPDPath); + }, });
diff --git a/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc b/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc index 86b0345..f919b0a2 100644 --- a/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc +++ b/chrome/browser/safe_browsing/download_protection/file_analyzer_unittest.cc
@@ -729,7 +729,8 @@ EXPECT_FALSE(result_.archived_binaries.Get(0).digests().sha256().empty()); } -TEST_F(FileAnalyzerTest, LargeRarSkipsContentInspection) { +// TODO(crbug.com/949399): The test is flaky (fail, timeout) on all platforms. +TEST_F(FileAnalyzerTest, DISABLED_LargeRarSkipsContentInspection) { scoped_refptr<MockBinaryFeatureExtractor> extractor = new testing::StrictMock<MockBinaryFeatureExtractor>(); FileAnalyzer analyzer(extractor);
diff --git a/chrome/browser/search/tools/generate_integrity_header.py b/chrome/browser/search/tools/generate_integrity_header.py index 94ead9d..228aa13 100755 --- a/chrome/browser/search/tools/generate_integrity_header.py +++ b/chrome/browser/search/tools/generate_integrity_header.py
@@ -13,7 +13,7 @@ def ComputeIntegrity(input_path): hasher = hashlib.sha256() - with open(input_path, 'r') as f: + with open(input_path, 'rb') as f: hasher.update(f.read()) return base64.b64encode(hasher.digest()) @@ -32,7 +32,7 @@ define_name = re.sub('\W', '_', input_filename.upper()) define_name = define_name + '_INTEGRITY' - f.write('#define ' + define_name + ' "' + integrity + '"\n') + f.write('#define ' + define_name + ' "' + integrity.decode() + '"\n') f.write('\n')
diff --git a/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc index ba706e5..d3cf2502 100644 --- a/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_wallet_sync_test.cc
@@ -241,16 +241,8 @@ EXPECT_EQ(kLaterTime, server_addresses[0]->use_date()); } -// Disabled due to flakiness: https://crbug.com/947692. -#if defined(THREAD_SANITIZER) -#define MAYBE_UpdateServerAddressMetadataWhileNotSyncing \ - DISABLED_UpdateServerAddressMetadataWhileNotSyncing -#else -#define MAYBE_UpdateServerAddressMetadataWhileNotSyncing \ - UpdateServerAddressMetadataWhileNotSyncing -#endif IN_PROC_BROWSER_TEST_P(TwoClientWalletSyncTest, - MAYBE_UpdateServerAddressMetadataWhileNotSyncing) { + UpdateServerAddressMetadataWhileNotSyncing) { GetFakeServer()->SetWalletData( {CreateSyncWalletAddress(/*name=*/"address-1", /*company=*/"Company-1"), CreateDefaultSyncPaymentsCustomerData()});
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc index 8114750..769eaeb4 100644 --- a/chrome/browser/sync_file_system/drive_backend/sync_engine.cc +++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.cc
@@ -702,13 +702,6 @@ } } -void SyncEngine::OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) { - Reset(); - UpdateServiceState(REMOTE_SERVICE_AUTHENTICATION_REQUIRED, - "Failed to sign in."); -} - void SyncEngine::OnPrimaryAccountSet( const CoreAccountInfo& primary_account_info) { Initialize();
diff --git a/chrome/browser/sync_file_system/drive_backend/sync_engine.h b/chrome/browser/sync_file_system/drive_backend/sync_engine.h index d20e692..2cb3d67 100644 --- a/chrome/browser/sync_file_system/drive_backend/sync_engine.h +++ b/chrome/browser/sync_file_system/drive_backend/sync_engine.h
@@ -151,8 +151,6 @@ const CoreAccountInfo& primary_account_info) override; void OnPrimaryAccountCleared( const CoreAccountInfo& previous_primary_account_info) override; - void OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) override; private: class WorkerObserver;
diff --git a/chrome/browser/ui/cocoa/task_manager_mac.mm b/chrome/browser/ui/cocoa/task_manager_mac.mm index 78740ae..95ba3072 100644 --- a/chrome/browser/ui/cocoa/task_manager_mac.mm +++ b/chrome/browser/ui/cocoa/task_manager_mac.mm
@@ -291,6 +291,7 @@ base::scoped_nsobject<NSTableView> tableView( [[NSTableView alloc] initWithFrame:NSMakeRect(0, 0, 400, 200)]); [tableView setAllowsColumnReordering:NO]; + [tableView setAllowsMultipleSelection:YES]; [tableView setAutosaveTableColumns:NO]; [tableView setColumnAutoresizingStyle:NSTableViewUniformColumnAutoresizingStyle];
diff --git a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view_interactive_uitest.cc b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view_interactive_uitest.cc index 4a9ceaa..35d5852e 100644 --- a/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/tabs/tab_hover_card_bubble_view_interactive_uitest.cc
@@ -70,8 +70,14 @@ #if defined(USE_AURA) // Verify that the hover card is not visible when any key is pressed. +// TODO(crbug.com/947668): The test is flaky on Win10. +#if defined(OS_WIN) +#define MAYBE_HoverCardHidesOnAnyKeyPressInSameWindow DISABLED_HoverCardHidesOnAnyKeyPressInSameWindow +#else +#define MAYBE_HoverCardHidesOnAnyKeyPressInSameWindow HoverCardHidesOnAnyKeyPressInSameWindow +#endif IN_PROC_BROWSER_TEST_F(TabHoverCardBubbleViewInteractiveUiTest, - HoverCardHidesOnAnyKeyPressInSameWindow) { + MAYBE_HoverCardHidesOnAnyKeyPressInSameWindow) { TabStrip* tab_strip = BrowserView::GetBrowserViewForBrowser(browser())->tabstrip(); Tab* tab = tab_strip->tab_at(0);
diff --git a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc index 71a622f..513391509 100644 --- a/chrome/browser/ui/webui/signin/login_ui_test_utils.cc +++ b/chrome/browser/ui/webui/signin/login_ui_test_utils.cc
@@ -54,7 +54,7 @@ } // Blocks and waits until the user signs in. Wait() does not block if a - // GoogleSigninSucceeded or a GoogleSigninFailed has already occurred. + // GoogleSigninSucceeded has already occurred. void Wait() { if (seen_) return; @@ -65,12 +65,6 @@ EXPECT_TRUE(seen_); } - void OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) override { - DVLOG(1) << "Google signin failed."; - QuitLoopRunner(); - } - void OnPrimaryAccountSet( const CoreAccountInfo& primary_account_info) override { DVLOG(1) << "Google signin succeeded.";
diff --git a/chrome/chrome_cleaner/BUILD.gn b/chrome/chrome_cleaner/BUILD.gn index 1b6e3ec..163f6f0 100644 --- a/chrome/chrome_cleaner/BUILD.gn +++ b/chrome/chrome_cleaner/BUILD.gn
@@ -30,8 +30,13 @@ } } -# This library should only be included in executable targets. +# This library should only be included in executable targets. It contains +# definitions used by the unit tests and misc helper binaries. The +# software_reporter_tool and chrome_cleanup_tool binaries will depend on +# specific reporter-only and cleaner-only versions of these definitions. static_library("other_executable_definitions") { + testonly = true + sources = [ "//chrome/chrome_cleaner/logging/other_logging_definitions.cc", "//chrome/chrome_cleaner/settings/other_settings_definitions.cc", @@ -100,4 +105,12 @@ if (is_internal_chrome_cleaner_build) { deps += [ "//chrome_cleaner_internal:unittest_sources" ] } + + # TODO(crbug.com/949669): Add an integration test of the top-level + # executables. For now, just add a dependency on them to make sure they + # build. + data_deps = [ + "//chrome/chrome_cleaner/executables:chrome_cleanup_tool", + "//chrome/chrome_cleaner/executables:software_reporter_tool", + ] }
diff --git a/chrome/chrome_cleaner/components/BUILD.gn b/chrome/chrome_cleaner/components/BUILD.gn index 7c2d40e..c3acdda 100644 --- a/chrome/chrome_cleaner/components/BUILD.gn +++ b/chrome/chrome_cleaner/components/BUILD.gn
@@ -63,6 +63,7 @@ "//chrome/chrome_cleaner/constants:uws_id", "//chrome/chrome_cleaner/http:mock_http_agent_factory", "//chrome/chrome_cleaner/logging:cleaner_logging", + "//chrome/chrome_cleaner/logging:common", "//chrome/chrome_cleaner/logging/proto:chrome_cleaner_report_proto", "//chrome/chrome_cleaner/os:cleaner_os", "//chrome/chrome_cleaner/os:common_os",
diff --git a/chrome/chrome_cleaner/components/recovery_component.cc b/chrome/chrome_cleaner/components/recovery_component.cc index c263223..d08987f 100644 --- a/chrome/chrome_cleaner/components/recovery_component.cc +++ b/chrome/chrome_cleaner/components/recovery_component.cc
@@ -45,7 +45,8 @@ 0x19, 0x7a, 0x71, 0x4b, 0x0a, 0x7c, 0x80, 0x1c, 0xf6, 0x29, 0x7c, 0x0a, 0x5f, 0xea, 0x67, 0xb7}; -// Name of the executable file as well as the command line arg to use for Foil. +// Name of the executable file as well as the command line arg to use when run +// from the Chrome Cleanup tool. const wchar_t kChromeRecoveryExe[] = L"ChromeRecovery.exe"; const char kChromeRecoveryArg[] = "/installsource swreporter";
diff --git a/chrome/chrome_cleaner/constants/BUILD.gn b/chrome/chrome_cleaner/constants/BUILD.gn index 811ac40b..1fa6b1c 100644 --- a/chrome/chrome_cleaner/constants/BUILD.gn +++ b/chrome/chrome_cleaner/constants/BUILD.gn
@@ -35,6 +35,30 @@ output = "$target_gen_dir/software_reporter_tool_branding.h" } +process_version("chrome_cleaner_version_resource") { + template_file = "chrome_cleaner.rc.version" + + sources = [ + "chrome_cleanup_tool_exe.ver", + cleaner_branding_path, + version_path, + ] + + output = "$target_gen_dir/chrome_cleaner.rc" +} + +process_version("reporter_version_resource") { + template_file = "chrome_cleaner.rc.version" + + sources = [ + "software_reporter_tool_exe.ver", + reporter_branding_path, + version_path, + ] + + output = "$target_gen_dir/chrome_reporter.rc" +} + source_set("common_strings") { sources = [ "chrome_cleaner_switches.cc",
diff --git a/chrome/chrome_cleaner/constants/chrome_cleaner.rc.version b/chrome/chrome_cleaner/constants/chrome_cleaner.rc.version new file mode 100644 index 0000000..322d86d --- /dev/null +++ b/chrome/chrome_cleaner/constants/chrome_cleaner.rc.version
@@ -0,0 +1,46 @@ +// 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. + +#include <verrsrc.h> + +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION @MAJOR@,@MINOR@,@BUILD@ + PRODUCTVERSION @MAJOR@,@MINOR@,@BUILD@ + FILEFLAGSMASK 0x17L +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "@COMPANY_FULLNAME@" + VALUE "FileDescription", "@PRODUCT_FULLNAME@" + VALUE "FileVersion", "@MAJOR@.@MINOR@.@BUILD@" + VALUE "InternalName", "@INTERNAL_NAME@" + VALUE "LegalCopyright", "@COPYRIGHT@" + VALUE "OriginalFilename", "@ORIGINAL_FILENAME@" + VALUE "ProductName", "@PRODUCT_FULLNAME@" + VALUE "ProductVersion", "@MAJOR@.@MINOR@.@BUILD@" + VALUE "CompanyShortName", "@COMPANY_SHORTNAME@" + VALUE "ProductShortName", "@PRODUCT_SHORTNAME@" + VALUE "Official Build", "@OFFICIAL_BUILD@" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END
diff --git a/chrome/chrome_cleaner/constants/chrome_cleanup_tool_exe.ver b/chrome/chrome_cleaner/constants/chrome_cleanup_tool_exe.ver new file mode 100644 index 0000000..747882bb --- /dev/null +++ b/chrome/chrome_cleaner/constants/chrome_cleanup_tool_exe.ver
@@ -0,0 +1,2 @@ +INTERNAL_NAME=chrome_cleanup_tool_exe +ORIGINAL_FILENAME=chrome_cleanup.exe
diff --git a/chrome/chrome_cleaner/constants/software_reporter_tool_exe.ver b/chrome/chrome_cleaner/constants/software_reporter_tool_exe.ver new file mode 100644 index 0000000..0d3600f5 --- /dev/null +++ b/chrome/chrome_cleaner/constants/software_reporter_tool_exe.ver
@@ -0,0 +1,2 @@ +INTERNAL_NAME=software_reporter_tool_exe +ORIGINAL_FILENAME=software_reporter_tool.exe
diff --git a/chrome/chrome_cleaner/engines/DEPS b/chrome/chrome_cleaner/engines/DEPS new file mode 100644 index 0000000..ef8ad28 --- /dev/null +++ b/chrome/chrome_cleaner/engines/DEPS
@@ -0,0 +1,3 @@ +include_rules = [ + "+mojo/public", +]
diff --git a/chrome/chrome_cleaner/engines/controllers/BUILD.gn b/chrome/chrome_cleaner/engines/controllers/BUILD.gn index 871823a6..3b3d031 100644 --- a/chrome/chrome_cleaner/engines/controllers/BUILD.gn +++ b/chrome/chrome_cleaner/engines/controllers/BUILD.gn
@@ -46,6 +46,7 @@ deps = [ ":engine_cleaner_lib", + ":facade_interface_header", "//base:base", "//chrome/chrome_cleaner/cleaner:cleaner_headers", "//chrome/chrome_cleaner/components:components", @@ -89,6 +90,18 @@ ] } +source_set("facade_interface_header") { + sources = [ + "engine_facade_interface.h", + ] + + deps = [ + "//base", + "//chrome/chrome_cleaner/cleaner:cleaner_headers", + "//chrome/chrome_cleaner/scanner:scanner_api", + ] +} + source_set("engine_cleaner_lib") { sources = [ "elevating_facade.cc", @@ -97,13 +110,13 @@ "engine_cleaner.h", "engine_facade.cc", "engine_facade.h", - "engine_facade_interface.h", "uwe_engine_cleaner_wrapper.cc", "uwe_engine_cleaner_wrapper.h", ] deps = [ ":common", + ":facade_interface_header", "//base", "//chrome/chrome_cleaner/chrome_utils:extensions_util_lib", "//chrome/chrome_cleaner/chrome_utils:force_installed_extension", @@ -172,6 +185,7 @@ "//chrome/chrome_cleaner/logging/proto:removal_status_proto", "//chrome/chrome_cleaner/os:cleaner_os", "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/os:file_remover_api", "//chrome/chrome_cleaner/parsers/broker:parser_sandbox_broker", "//chrome/chrome_cleaner/parsers/json_parser:json_parser", "//chrome/chrome_cleaner/parsers/shortcut_parser/broker:fake_shortcut_parser",
diff --git a/chrome/chrome_cleaner/executables/BUILD.gn b/chrome/chrome_cleaner/executables/BUILD.gn new file mode 100644 index 0000000..9400ae2 --- /dev/null +++ b/chrome/chrome_cleaner/executables/BUILD.gn
@@ -0,0 +1,152 @@ +# 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. + +import("//chrome/chrome_cleaner/chrome_cleaner_args.gni") + +group("engine_definitions") { + if (is_internal_chrome_cleaner_build) { + deps = [ + "//chrome/chrome_cleaner_internal:engine_definitions", + ] + } else { + deps = [ + "//chrome/chrome_cleaner/engines/common:dummy_engine_resources", + "//chrome/chrome_cleaner/settings:dummy_engine_settings", + ] + } +} + +group("engine_target_factory") { + if (is_internal_chrome_cleaner_build) { + deps = [ + "//chrome/chrome_cleaner_internal:engine_target_factory", + ] + } else { + deps = [ + "//chrome/chrome_cleaner/engines/target:dummy_engine_delegate_factory", + ] + } +} + +source_set("shutdown_sequence") { + sources = [ + "shutdown_sequence.cc", + "shutdown_sequence.h", + ] + + deps = [ + "//base:base", + "//chrome/chrome_cleaner/engines/broker:common", + "//chrome/chrome_cleaner/engines/controllers:facade_interface_header", + "//chrome/chrome_cleaner/ipc:mojo_task_runner", + ] +} + +# The Chrome Cleanup tool is distributed as two executables: +# software_reporter_tool only scans the user's system and returns a status code +# to Chrome, while chrome_cleanup_tool is invoked to remove UwS. This template +# holds the definitions they share. +template("chrome_cleaner_executable") { + executable(target_name) { + sources = invoker.sources + + # Default entrypoint is main, console app. Change it to wWinMain, windowed. + configs -= [ "//build/config/win:console" ] + configs += [ "//build/config/win:windowed" ] + if (defined(invoker.configs)) { + configs += invoker.configs + } + + libs = [ + "crypt32.lib", + "mstask.lib", + "ntdll.lib", + "taskschd.lib", + "wintrust.lib", + ] + if (defined(invoker.libs)) { + libs += invoker.libs + } + + deps = [ + ":engine_definitions", + ":engine_target_factory", + ":shutdown_sequence", + "//base:base", + "//build/win:default_exe_manifest", + "//chrome/chrome_cleaner/constants:common_strings", + "//chrome/chrome_cleaner/constants:version_header", + "//chrome/chrome_cleaner/crash:crashpad_lib", + "//chrome/chrome_cleaner/engines/broker:common", + "//chrome/chrome_cleaner/engines/broker:interface_log_service", + "//chrome/chrome_cleaner/engines/common:resources_header", + "//chrome/chrome_cleaner/engines/target:common", + "//chrome/chrome_cleaner/engines/target:engine_delegate_factory_header", + "//chrome/chrome_cleaner/ipc:mojo_task_runner", + "//chrome/chrome_cleaner/ipc:sandbox", + "//chrome/chrome_cleaner/logging:common", + "//chrome/chrome_cleaner/logging:logging_definitions", + "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/parsers/broker:parser_sandbox_broker", + "//chrome/chrome_cleaner/parsers/shortcut_parser/broker:sandboxed_shortcut_parser", + "//chrome/chrome_cleaner/parsers/target:parser_sandbox_target", + "//chrome/chrome_cleaner/settings:default_matching_options", + "//chrome/chrome_cleaner/settings:engine_settings_header", + "//chrome/chrome_cleaner/settings:matching_options", + "//chrome/chrome_cleaner/settings:settings", + "//chrome/chrome_cleaner/settings:settings_types", + "//sandbox/win:sandbox", + ] + if (defined(invoker.deps)) { + deps += invoker.deps + } + } +} + +chrome_cleaner_executable("chrome_cleanup_tool") { + sources = [ + "chrome_cleaner_main.cc", + ] + + libs = [ "comctl32.lib" ] + + deps = [ + "//chrome/chrome_cleaner/cleaner:cleaner_headers", + "//chrome/chrome_cleaner/components", + "//chrome/chrome_cleaner/constants:chrome_cleaner_version_resource", + "//chrome/chrome_cleaner/constants:chrome_cleanup_tool_branding_header", + "//chrome/chrome_cleaner/engines/controllers:engine_cleaner_lib", + "//chrome/chrome_cleaner/engines/controllers:facade_interface_header", + "//chrome/chrome_cleaner/engines/controllers:main_controller", + "//chrome/chrome_cleaner/ipc:chrome_prompt_ipc", + "//chrome/chrome_cleaner/logging:cleaner_logging", + "//chrome/chrome_cleaner/logging:cleaner_logging_definitions", + "//chrome/chrome_cleaner/os:cleaner_os", + "//chrome/chrome_cleaner/parsers/json_parser", + "//chrome/chrome_cleaner/scanner:force_installed_extension_scanner", + "//chrome/chrome_cleaner/scanner:force_installed_extension_scanner_api", + "//chrome/chrome_cleaner/settings:cleaner_settings_definitions", + "//chrome/chrome_cleaner/zip_archiver/target:common", + ] +} + +chrome_cleaner_executable("software_reporter_tool") { + sources = [ + "chrome_reporter_main.cc", + ] + + deps = [ + "//chrome/chrome_cleaner/constants:reporter_version_resource", + "//chrome/chrome_cleaner/constants:software_reporter_tool_branding_header", + "//chrome/chrome_cleaner/engines/broker:disabled_cleaner_sandbox_interface", + "//chrome/chrome_cleaner/engines/controllers:scanner_controller", + "//chrome/chrome_cleaner/logging:noop_logging", + "//chrome/chrome_cleaner/logging:reporter_logging", + "//chrome/chrome_cleaner/logging:reporter_logging_definitions", + "//chrome/chrome_cleaner/logging/proto:reporter_logs_proto", + "//chrome/chrome_cleaner/parsers/shortcut_parser/broker:shortcut_parser_api", + "//chrome/chrome_cleaner/scanner:reporter_scanner", + "//chrome/chrome_cleaner/settings:reporter_settings_definitions", + ] +}
diff --git a/chrome/chrome_cleaner/executables/chrome_cleaner_main.cc b/chrome/chrome_cleaner/executables/chrome_cleaner_main.cc new file mode 100644 index 0000000..178ec89 --- /dev/null +++ b/chrome/chrome_cleaner/executables/chrome_cleaner_main.cc
@@ -0,0 +1,628 @@ +// 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. + +#include <windows.h> + +#include <commctrl.h> +#include <psapi.h> + +#include <memory> +#include <set> +#include <utility> + +#include "base/at_exit.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/files/file_util.h" +#include "base/logging.h" +#include "base/macros.h" +#include "base/memory/ref_counted.h" +#include "base/message_loop/message_loop.h" +#include "base/run_loop.h" +#include "base/sequenced_task_runner.h" +#include "base/strings/utf_string_conversions.h" +#include "base/task/task_scheduler/task_scheduler.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" +#include "base/version.h" +#include "base/win/scoped_com_initializer.h" +#include "chrome/chrome_cleaner/components/recovery_component.h" +#include "chrome/chrome_cleaner/components/system_report_component.h" +#include "chrome/chrome_cleaner/components/system_restore_point_component.h" +#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" +#include "chrome/chrome_cleaner/constants/chrome_cleanup_tool_branding.h" +#include "chrome/chrome_cleaner/constants/version.h" +#include "chrome/chrome_cleaner/crash/crash_client.h" +#include "chrome/chrome_cleaner/crash/crash_reporter.h" +#include "chrome/chrome_cleaner/engines/broker/interface_log_service.h" +#include "chrome/chrome_cleaner/engines/broker/sandbox_setup.h" +#include "chrome/chrome_cleaner/engines/common/engine_resources.h" +#include "chrome/chrome_cleaner/engines/controllers/elevating_facade.h" +#include "chrome/chrome_cleaner/engines/controllers/engine_facade.h" +#include "chrome/chrome_cleaner/engines/controllers/engine_facade_interface.h" +#include "chrome/chrome_cleaner/engines/controllers/main_controller.h" +#include "chrome/chrome_cleaner/engines/target/engine_delegate.h" +#include "chrome/chrome_cleaner/engines/target/engine_delegate_factory.h" +#include "chrome/chrome_cleaner/engines/target/sandbox_setup.h" +#include "chrome/chrome_cleaner/executables/shutdown_sequence.h" +#include "chrome/chrome_cleaner/ipc/chrome_prompt_ipc.h" +#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" +#include "chrome/chrome_cleaner/ipc/sandbox.h" +#include "chrome/chrome_cleaner/logging/logging_service_api.h" +#include "chrome/chrome_cleaner/logging/pending_logs_service.h" +#include "chrome/chrome_cleaner/logging/registry_logger.h" +#include "chrome/chrome_cleaner/logging/scoped_logging.h" +#include "chrome/chrome_cleaner/os/disk_util.h" +#include "chrome/chrome_cleaner/os/early_exit.h" +#include "chrome/chrome_cleaner/os/file_path_sanitization.h" +#include "chrome/chrome_cleaner/os/initializer.h" +#include "chrome/chrome_cleaner/os/post_reboot_registration.h" +#include "chrome/chrome_cleaner/os/pre_fetched_paths.h" +#include "chrome/chrome_cleaner/os/rebooter.h" +#include "chrome/chrome_cleaner/os/secure_dll_loading.h" +#include "chrome/chrome_cleaner/os/system_util.h" +#include "chrome/chrome_cleaner/os/system_util_cleaner.h" +#include "chrome/chrome_cleaner/os/task_scheduler.h" +#include "chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.h" +#include "chrome/chrome_cleaner/parsers/json_parser/json_parser_api.h" +#include "chrome/chrome_cleaner/parsers/json_parser/sandboxed_json_parser.h" +#include "chrome/chrome_cleaner/parsers/shortcut_parser/broker/sandboxed_shortcut_parser.h" +#include "chrome/chrome_cleaner/parsers/target/sandbox_setup.h" +#include "chrome/chrome_cleaner/scanner/force_installed_extension_scanner_impl.h" +#include "chrome/chrome_cleaner/settings/engine_settings.h" +#include "chrome/chrome_cleaner/settings/matching_options.h" +#include "chrome/chrome_cleaner/settings/settings.h" +#include "chrome/chrome_cleaner/settings/settings_types.h" +#include "chrome/chrome_cleaner/zip_archiver/target/sandbox_setup.h" +#include "components/chrome_cleaner/public/constants/constants.h" +#include "components/chrome_cleaner/public/constants/result_codes.h" +#include "sandbox/win/src/sandbox_factory.h" + +namespace { + +using chrome_cleaner::ExecutionMode; + +// The number of milliseconds to sleep to delay the self-deletion. +const uint32_t kSelfDeleteDelayMs = 1000; + +const wchar_t kElevatedLogFileSuffix[] = L"-elevated"; + +// A callback for the logs service to call us back when it's done with logs +// upload. |success| is the result of the upload, and |succeeded|, when not +// null, is set with the |success| value. +void LogsUploadCallback(bool* succeeded, + base::OnceClosure quit_closure, + bool success) { + if (succeeded) + *succeeded = success; + // Use a task instead of a direct call to QuitWhenIdle, in case we are called + // synchronously because of an upload error, and the message loop is not + // running yet. + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, + std::move(quit_closure)); +} + +void AddComponents(chrome_cleaner::MainController* main_controller, + base::CommandLine* command_line, + chrome_cleaner::JsonParserAPI* json_parser, + chrome_cleaner::SandboxedShortcutParser* shortcut_parser) { +#if defined(CHROME_CLEANER_OFFICIAL_BUILD) + // Ensure that the system restore point component runs first. + main_controller->AddComponent( + std::make_unique<chrome_cleaner::SystemRestorePointComponent>( + PRODUCT_FULLNAME_STRING)); +#endif + + if (chrome_cleaner::RecoveryComponent::IsAvailable()) + main_controller->AddComponent( + std::make_unique<chrome_cleaner::RecoveryComponent>()); + + main_controller->AddComponent( + std::make_unique<chrome_cleaner::SystemReportComponent>(json_parser, + shortcut_parser)); +} + +void SendLogsToSafeBrowsing(chrome_cleaner::ResultCode exit_code, + chrome_cleaner::RegistryLogger* registry_logger) { + chrome_cleaner::LoggingServiceAPI* logging_service = + chrome_cleaner::LoggingServiceAPI::GetInstance(); + logging_service->SetExitCode(exit_code); + base::RunLoop run_loop; + logging_service->SendLogsToSafeBrowsing( + base::BindRepeating(&LogsUploadCallback, nullptr, + run_loop.QuitWhenIdleClosure()), + registry_logger); + run_loop.Run(); +} + +chrome_cleaner::ResultCode RelaunchElevated( + chrome_cleaner::RegistryLogger* registry_logger) { + // If this is being done after we tried to relaunch elevated, there is a + // problem. We unfortunately can't report it since the user didn't get a + // chance to opt out of logs upload. + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(chrome_cleaner::kElevatedSwitch)) { + LOG(ERROR) << "Failed to restart elevated."; + return chrome_cleaner::RESULT_CODE_FAILED_TO_ELEVATE; + } + + command_line->AppendSwitch(chrome_cleaner::kElevatedSwitch); + base::Process elevated_process = + chrome_cleaner::LaunchElevatedProcessWithAssociatedWindow( + *command_line, + /*hwnd=*/nullptr); + if (elevated_process.IsValid()) { + LOG(INFO) << "Successfully re-launched elevated."; + } else { + LOG(ERROR) << "Failed to re-launch elevated."; + chrome_cleaner::Settings* settings = + chrome_cleaner::Settings::GetInstance(); + if (chrome_cleaner::Rebooter::IsPostReboot()) { + chrome_cleaner::ResultCode exit_code = + chrome_cleaner::RESULT_CODE_POST_REBOOT_ELEVATION_DENIED; + if (settings->logs_upload_allowed()) + SendLogsToSafeBrowsing(exit_code, registry_logger); + return exit_code; + } + // In legacy mode, we can't upload logs to Safe Browsing if this is not + // a post-reboot run. We log a distinct exit code to indicate in UMA that + // elevation was declined or the user doesn't have admin rights. + return chrome_cleaner::RESULT_CODE_ELEVATION_PROMPT_DECLINED; + } + return chrome_cleaner::RESULT_CODE_SUCCESS; +} + +// Run the chrome Cleaner to scan and clean. +chrome_cleaner::ResultCode RunChromeCleaner( + base::CommandLine* command_line, + chrome_cleaner::RebooterAPI* rebooter, + chrome_cleaner::RegistryLogger* registry_logger, + chrome_cleaner::ChromePromptIPC* chrome_prompt_ipc, + chrome_cleaner::ShutdownSequence shutdown_sequence) { + if (command_line->HasSwitch(chrome_cleaner::kCrashSwitch)) { + int* crash_me = nullptr; + *crash_me = 42; + } + + INITCOMMONCONTROLSEX common_control_info = {sizeof(INITCOMMONCONTROLSEX), + ICC_LINK_CLASS}; + if (!InitCommonControlsEx(&common_control_info)) + return chrome_cleaner::RESULT_CODE_FAILED; + + // There is a circular dependency: MainController depends on EngineFacade; + // EngineFacade might instantiate a sandbox but the sandbox connection error + // handler invokes a method of MainController. + // + // To break this circle, create MainController first and get the error + // handler with MainController::GetSandboxConnectionErrorCallback. Then + // create the EngineFacade with the error handler, and set it on the + // MainController. It's important that the connection error handler is + // available when the EngineFacade is created, otherwise there's a race + // condition where a sandbox target process can be spawned without an error + // handler, so any disconnection before MainController is created wouldn't be + // handled. + + chrome_cleaner::MainController main_controller(rebooter, registry_logger, + chrome_prompt_ipc); + chrome_cleaner::SandboxConnectionErrorCallback connection_error_callback = + main_controller.GetSandboxConnectionErrorCallback(); + + // Initialize a null UniqueParserPtr to be set by SpawnParserSandbox. + chrome_cleaner::UniqueParserPtr parser_ptr( + nullptr, base::OnTaskRunnerDeleter(nullptr)); + chrome_cleaner::ResultCode init_result = chrome_cleaner::SpawnParserSandbox( + shutdown_sequence.mojo_task_runner, connection_error_callback, + &parser_ptr); + if (init_result != chrome_cleaner::RESULT_CODE_SUCCESS) { + return init_result; + } + std::unique_ptr<chrome_cleaner::SandboxedJsonParser> json_parser = + std::make_unique<chrome_cleaner::SandboxedJsonParser>( + shutdown_sequence.mojo_task_runner.get(), parser_ptr.get()); + std::unique_ptr<chrome_cleaner::SandboxedShortcutParser> shortcut_parser = + std::make_unique<chrome_cleaner::SandboxedShortcutParser>( + shutdown_sequence.mojo_task_runner.get(), parser_ptr.get()); + + chrome_cleaner::Settings* settings = chrome_cleaner::Settings::GetInstance(); + if (!chrome_cleaner::IsSupportedEngine(settings->engine())) { + LOG(FATAL) << "Unsupported engine " << settings->engine(); + return chrome_cleaner::RESULT_CODE_FAILED; + } + + chrome_cleaner::InitializePUPDataWithCatalog(settings->engine()); + + std::unique_ptr<chrome_cleaner::InterfaceLogService> interface_log_service = + chrome_cleaner::InterfaceLogService::Create( + command_line->GetSwitchValueNative( + chrome_cleaner::kLogInterfaceCallsToSwitch), + CHROME_CLEANER_VERSION_STRING); + + chrome_cleaner::ResultCode engine_result; + std::tie(engine_result, shutdown_sequence.engine_client) = SpawnEngineSandbox( + settings->engine(), registry_logger, shutdown_sequence.mojo_task_runner, + connection_error_callback, std::move(interface_log_service)); + if (engine_result != chrome_cleaner::RESULT_CODE_SUCCESS) + return engine_result; + + shutdown_sequence + .engine_facade = std::make_unique<chrome_cleaner::EngineFacade>( + shutdown_sequence.engine_client, json_parser.get(), + main_controller.main_dialog(), + std::make_unique<chrome_cleaner::ForceInstalledExtensionScannerImpl>(), + chrome_prompt_ipc); + + if (settings->execution_mode() == ExecutionMode::kScanning) { + shutdown_sequence.engine_facade = + std::make_unique<chrome_cleaner::ElevatingFacade>( + std::move(shutdown_sequence.engine_facade)); + } + main_controller.SetEngineFacade(shutdown_sequence.engine_facade.get()); + + // Ensure profile reset, recovery and other components run only once by + // running them only in the cleaning mode. + if (settings->execution_mode() != ExecutionMode::kScanning) { + AddComponents(&main_controller, command_line, json_parser.get(), + shortcut_parser.get()); + } + + command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(chrome_cleaner::kLoadEmptyDLLSwitch)) { + chrome_cleaner::testing::LoadEmptyDLL(); + } + chrome_cleaner::NotifyInitializationDoneForTesting(); + + if (chrome_cleaner::Rebooter::IsPostReboot()) { + // When running post reboot, confirm whether the job was done successfully + // or not. + return main_controller.ValidateCleanup(); + } + + return main_controller.ScanAndClean(); +} + +// Return false when a self delete should NOT not be attempted. +bool CanSelfDelete(chrome_cleaner::ResultCode exit_code) { + if (exit_code == chrome_cleaner::RESULT_CODE_PENDING_REBOOT || + exit_code == chrome_cleaner::RESULT_CODE_CANCELED || + exit_code == chrome_cleaner::RESULT_CODE_CLEANUP_PROMPT_DENIED) { + return false; + } + std::unique_ptr<chrome_cleaner::TaskScheduler> task_scheduler( + chrome_cleaner::TaskScheduler::CreateInstance()); + return !task_scheduler->IsTaskRegistered( + chrome_cleaner::PendingLogsService::LogsUploadRetryTaskName( + PRODUCT_SHORTNAME_STRING) + .c_str()); +} + +chrome_cleaner::ResultCode ReturnWithResultCode( + chrome_cleaner::ResultCode result_code, + const base::FilePath& exe_path, + chrome_cleaner::RegistryLogger* registry_logger, + chrome_cleaner::RebooterAPI* rebooter) { + DCHECK_NE(chrome_cleaner::RESULT_CODE_INVALID, result_code); + + registry_logger->WriteExitCode(result_code); + registry_logger->WriteEndTime(); + + bool self_delete = CanSelfDelete(result_code); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); +#if defined(CHROME_CLEANER_OFFICIAL_BUILD) + self_delete = self_delete && + !command_line->HasSwitch(chrome_cleaner::kNoSelfDeleteSwitch); +#else + self_delete = self_delete && + command_line->HasSwitch(chrome_cleaner::kForceSelfDeleteSwitch); +#endif + + if (self_delete) { + LOG(INFO) << "Self-deleting."; + + if (!chrome_cleaner::DeleteFileFromTempProcess(exe_path, kSelfDeleteDelayMs, + nullptr)) { + PLOG(ERROR) << "Failed to self-DeleteFileFromTempProcess."; + } + + // Embedded libraries may have been extracted. Try to delete them and ignore + // errors. + base::FilePath exe_dir = exe_path.DirName(); + std::set<base::string16> embedded_libraries = + chrome_cleaner::GetLibrariesToLoad( + chrome_cleaner::Settings::GetInstance()->engine()); + for (const auto& library : embedded_libraries) { + chrome_cleaner::DeleteFileFromTempProcess(exe_dir.Append(library), + kSelfDeleteDelayMs, nullptr); + } + } + + if (result_code == chrome_cleaner::RESULT_CODE_SUCCESS || + result_code == chrome_cleaner::RESULT_CODE_POST_REBOOT_SUCCESS) { + registry_logger->RecordCompletedCleanup(); + } + + LOG(INFO) << "Exiting with code: " << result_code; + chrome_cleaner::TaskScheduler::Terminate(); + + return result_code; +} + +} // namespace + +int APIENTRY wWinMain(HINSTANCE, HINSTANCE, wchar_t*, int) { + // This must be executed as soon as possible to reduce the number of dlls that + // the code might try to load before we can lock things down. + chrome_cleaner::EnableSecureDllLoading(); + + base::AtExitManager at_exit; + + // This must be done BEFORE constructing ScopedLogging, which call InitLogging + // to set the name of the log file, which needs to read from the command line. + bool success = base::CommandLine::Init(0, nullptr); + DCHECK(success); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + + // The list of post-reboot switches has grown so long that RunOnce no longer + // works, as there is a limit of 260 characters on RunOnce values. Switches + // are stored in a separate registry key. + if (command_line->HasSwitch( + chrome_cleaner::kPostRebootSwitchesInOtherRegistryKeySwitch)) { + base::CommandLine tmp_cmd(command_line->GetProgram()); + chrome_cleaner::PostRebootRegistration post_reboot( + PRODUCT_SHORTNAME_STRING); + if (!post_reboot.ReadRunOncePostRebootCommandLine( + command_line->GetSwitchValueASCII(chrome_cleaner::kCleanupIdSwitch), + &tmp_cmd)) { + LOG(DFATAL) + << "Could not read post-reboot switches from the registry key"; + // This shouldn't be an attack vector by UwS: the TaskScheduler should + // run the cleaner if the RunOnce attempt failed. + return chrome_cleaner::RESULT_CODE_FAILED; + } + + // Overwrites the current process' command line. Future calls to + // base::CommandLine::ForCurrentProcess will return the mutated |tmp_cmd| + // instead of the original command line. + // Note that this mutation is not thread safe. + *command_line = tmp_cmd; + } + + chrome_cleaner::ShutdownSequence shutdown_sequence; + + chrome_cleaner::RegistryLogger registry_logger( + chrome_cleaner::RegistryLogger::Mode::REMOVER); + if (!chrome_cleaner::InitializeOSUtils()) { + return ReturnWithResultCode( + chrome_cleaner::RESULT_CODE_INITIALIZATION_ERROR, base::FilePath(), + ®istry_logger, nullptr); + } + + const char* crash_reporter_switch = chrome_cleaner::kCrashHandlerSwitch; + if (command_line->HasSwitch(crash_reporter_switch) && + !command_line->HasSwitch(chrome_cleaner::kUploadLogFileSwitch)) { + // If this process should run as the crash reporter, run that then return + // immediately, as this process is not meant to be the cleaner itself. + return CrashReporterMain(); + } + + // GetTargetServices() returns non-null if this is the sandbox target, and + // null otherwise. + sandbox::TargetServices* sandbox_target_services = + sandbox::SandboxFactory::GetTargetServices(); + const bool is_sandbox_target = (sandbox_target_services != nullptr); + + base::string16 log_suffix = + command_line->HasSwitch(chrome_cleaner::kElevatedSwitch) + ? kElevatedLogFileSuffix + : L""; + log_suffix += is_sandbox_target ? chrome_cleaner::kSandboxLogFileSuffix : L""; + + // This has to be created after CrashReporterMain() above, as + // CrashReporterMain creates its own ScopedLogging to upload logs. + + chrome_cleaner::ScopedLogging scoped_logging(log_suffix); + + // Only start the crash reporter for the main process, the sandboxed process + // will use the same crash reporter. + if (is_sandbox_target) { + const base::string16 ipc_pipe_name = command_line->GetSwitchValueNative( + chrome_cleaner::kUseCrashHandlerWithIdSwitch); + CHECK(!ipc_pipe_name.empty()); + UseCrashReporter(ipc_pipe_name); + } else { + StartCrashReporter(CHROME_CLEANER_VERSION_UTF8_STRING); + } + + const chrome_cleaner::Settings* settings = + chrome_cleaner::Settings::GetInstance(); + + // Process priority modification has to be done before threads are created + // because they inherit process' priority. + if (settings->execution_mode() == ExecutionMode::kScanning) { + chrome_cleaner::SetBackgroundMode(); + } else { + if (!SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS)) + PLOG(ERROR) << "Can't SetPriorityClass to NORMAL_PRIORITY_CLASS"; + } + + base::TaskScheduler::CreateAndStartWithDefaultParams("chrome cleanup tool"); + + chrome_cleaner::SandboxType sandbox_type = + is_sandbox_target ? chrome_cleaner::SandboxProcessType() + : chrome_cleaner::SandboxType::kNonSandboxed; + + if (!chrome_cleaner::CrashClient::GetInstance()->InitializeCrashReporting( + chrome_cleaner::CrashClient::Mode::CLEANER, sandbox_type)) { + LOG(INFO) << "Crash reporting is not available."; + } else { + VLOG(1) << "Crash reporting initialized."; + } + + if (is_sandbox_target) { + switch (sandbox_type) { + case chrome_cleaner::SandboxType::kParser: + return chrome_cleaner::RunParserSandboxTarget(*command_line, + sandbox_target_services); + case chrome_cleaner::SandboxType::kZipArchiver: + return chrome_cleaner::RunZipArchiverSandboxTarget( + *command_line, sandbox_target_services); + case chrome_cleaner::SandboxType::kEngine: + return RunEngineSandboxTarget( + chrome_cleaner::CreateEngineDelegate(settings->engine()), + *command_line, sandbox_target_services); + default: + NOTREACHED() << "Unknown sandbox type " + << static_cast<int>(sandbox_type); + } + } + + // Make sure we don't run two instances of the cleaner simultaneously + // post-reboot. + if (chrome_cleaner::Rebooter::IsPostReboot() && + chrome_cleaner::HasAdminRights()) { + // The system closes the handle automatically when the process terminates, + // and the event object is destroyed when its last handle has been closed. + HANDLE event = ::CreateEvent(nullptr, FALSE, FALSE, L"chrome_cleanup_tool"); + if (event && ::GetLastError() == ERROR_ALREADY_EXISTS) + return chrome_cleaner::RESULT_CODE_ALREADY_RUNNING; + } + + // Setup Cleaner registry values. + registry_logger.ClearExitCode(); + registry_logger.ClearEndTime(); + registry_logger.WriteVersion(); + registry_logger.WriteStartTime(); + + // CoInitialize into the MTA since we desire to use the System Restore Point + // API which requires we be in the MTA. Also needed for the task scheduler. + base::win::ScopedCOMInitializer scoped_com_initializer( + base::win::ScopedCOMInitializer::kMTA); + bool succeeded = chrome_cleaner::InitializeCOMSecurity(); + PLOG_IF(ERROR, !succeeded) << "InitializeCOMSecurity() failed"; + DCHECK(succeeded); + succeeded = chrome_cleaner::TaskScheduler::Initialize(); + LOG_IF(ERROR, !succeeded) << "TaskScheduler::Initialize() failed"; + DCHECK(succeeded); + + LOG(INFO) << "Command line arguments: " + << chrome_cleaner::SanitizeCommandLine(*command_line); + + // Make sure that users won't be bothered again to confirm they want to run + // the cleaner, especially post-reboot. + base::FilePath executable_path = + chrome_cleaner::PreFetchedPaths::GetInstance()->GetExecutablePath(); + if (chrome_cleaner::HasZoneIdentifier(executable_path) && + !chrome_cleaner::OverwriteZoneIdentifier(executable_path)) { + LOG(ERROR) << "Failed to remove zone identifier."; + } + + // Many pieces of code below need a message loop to have been instantiated + // before them. + base::MessageLoopForUI ui_message_loop; + + // The rebooter must be at the outermost scope so it can be called to reboot + // before exiting, when appropriate. + std::unique_ptr<chrome_cleaner::RebooterAPI> rebooter; + + if (command_line->HasSwitch(chrome_cleaner::kUploadLogFileSwitch)) { + // Bail out of logs upload if upload is disabled. + if (!settings->logs_upload_allowed()) { + // Also get rid of all pending logs upload. Use a set to stop if we see + // the same file name twice and make sure we don't go through some sort + // of circular loop. Otherwise, we could spin forever if + // GetNextLogFilePath returns the same file and never gets to return an + // empty one. This might leave some log file behind, in very rare error + // cases, but it's better than an infinite loop. + std::set<base::string16> log_files; + while (true) { + base::FilePath log_file; + registry_logger.GetNextLogFilePath(&log_file); + if (log_file.empty() || !log_files.insert(log_file.value()).second) + break; + chrome_cleaner::PendingLogsService::ClearPendingLogFile( + PRODUCT_SHORTNAME_STRING, log_file, ®istry_logger); + } + + return ReturnWithResultCode( + chrome_cleaner::RESULT_CODE_EMPTY_CLIENT_ID_UPLOAD_ATTEMPT, + executable_path, ®istry_logger, nullptr); + } + + succeeded = false; + chrome_cleaner::PendingLogsService pending_logs_service; + base::RunLoop run_loop; + pending_logs_service.RetryNextPendingLogsUpload( + PRODUCT_SHORTNAME_STRING, + base::BindOnce(&LogsUploadCallback, &succeeded, + run_loop.QuitWhenIdleClosure()), + ®istry_logger); + run_loop.Run(); + registry_logger.AppendLogUploadResult(succeeded); + + return ReturnWithResultCode( + succeeded ? chrome_cleaner::RESULT_CODE_UPLOADED_PENDING_LOGS + : chrome_cleaner::RESULT_CODE_FAILED_TO_UPLOAD_LOGS, + executable_path, ®istry_logger, nullptr); + } + + rebooter.reset(new chrome_cleaner::Rebooter(PRODUCT_SHORTNAME_STRING)); + + shutdown_sequence.mojo_task_runner = chrome_cleaner::MojoTaskRunner::Create(); + + // Only create the IPC if both the Mojo pipe token and the parent pipe handle + // have been sent by Chrome. If either switch is not present, it will not be + // connected to the parent process. + chrome_cleaner::ChromePromptIPC* chrome_prompt_ipc = nullptr; + if (settings->execution_mode() == ExecutionMode::kScanning) { + // Scanning mode is only used by Chrome and all necessary mojo pipe flags + // must have been passed on the command line. + if (settings->chrome_mojo_pipe_token().empty() || + !settings->has_parent_pipe_handle()) { + return ReturnWithResultCode( + chrome_cleaner::RESULT_CODE_INVALID_IPC_SWITCHES, executable_path, + ®istry_logger, rebooter.get()); + } + + const std::string chrome_mojo_pipe_token = + settings->chrome_mojo_pipe_token(); + // This pointer is leaked, in order to simplify this object's lifetime. + chrome_prompt_ipc = new chrome_cleaner::ChromePromptIPC( + chrome_mojo_pipe_token, shutdown_sequence.mojo_task_runner); + } else if (!settings->chrome_mojo_pipe_token().empty() || + settings->has_parent_pipe_handle()) { + return ReturnWithResultCode( + chrome_cleaner::RESULT_CODE_EXPECTED_SCANNING_EXECUTION_MODE, + executable_path, ®istry_logger, rebooter.get()); + } + + if (settings->execution_mode() == ExecutionMode::kNone) { + ::MessageBox(NULL, + L"Manually running this program is no longer supported. " + L"Please visit " + L"https://support.google.com/chrome/?p=chrome_cleanup_tool " + L"for more information.", + L"Error", MB_OK | MB_ICONERROR | MB_TOPMOST); + return chrome_cleaner::RESULT_CODE_MANUAL_EXECUTION_BY_USER; + } + + // If immediate elevation is not required, the process will restart elevated + // after the user accepts to run cleanup. + if (settings->execution_mode() != ExecutionMode::kScanning && + !chrome_cleaner::HasAdminRights()) { + chrome_cleaner::ResultCode result_code = RelaunchElevated(®istry_logger); + // If we failed to launch the elevated process, this process should call + // ReturnWithResultCode to ensure all the properly post-run registry values + // are written, and that all required cleanup is executed. If the elevated + // process was created it will handle this. + if (result_code != chrome_cleaner::RESULT_CODE_SUCCESS) { + return ReturnWithResultCode(result_code, executable_path, + ®istry_logger, rebooter.get()); + } + return result_code; + } + + return ReturnWithResultCode( + RunChromeCleaner(command_line, rebooter.get(), ®istry_logger, + chrome_prompt_ipc, std::move(shutdown_sequence)), + executable_path, ®istry_logger, rebooter.get()); +}
diff --git a/chrome/chrome_cleaner/executables/chrome_reporter_main.cc b/chrome/chrome_cleaner/executables/chrome_reporter_main.cc new file mode 100644 index 0000000..4c189e0 --- /dev/null +++ b/chrome/chrome_cleaner/executables/chrome_reporter_main.cc
@@ -0,0 +1,317 @@ +// 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. + +#include <windows.h> + +#include <psapi.h> + +#include <memory> +#include <string> +#include <utility> + +#include "base/at_exit.h" +#include "base/bind.h" +#include "base/bind_helpers.h" +#include "base/command_line.h" +#include "base/files/file_path.h" +#include "base/logging.h" +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" +#include "base/message_loop/message_loop.h" +#include "base/sequenced_task_runner.h" +#include "base/strings/string16.h" +#include "base/strings/string_util.h" +#include "base/task/task_scheduler/task_scheduler.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/win/registry.h" +#include "base/win/scoped_com_initializer.h" +#include "base/win/windows_version.h" +#include "chrome/chrome_cleaner/constants/chrome_cleaner_switches.h" +#include "chrome/chrome_cleaner/constants/software_reporter_tool_branding.h" +#include "chrome/chrome_cleaner/constants/version.h" +#include "chrome/chrome_cleaner/crash/crash_client.h" +#include "chrome/chrome_cleaner/crash/crash_reporter.h" +#include "chrome/chrome_cleaner/engines/broker/engine_client.h" +#include "chrome/chrome_cleaner/engines/broker/interface_log_service.h" +#include "chrome/chrome_cleaner/engines/broker/sandbox_setup.h" +#include "chrome/chrome_cleaner/engines/common/engine_resources.h" +#include "chrome/chrome_cleaner/engines/controllers/scanner_controller_impl.h" +#include "chrome/chrome_cleaner/engines/target/engine_delegate.h" +#include "chrome/chrome_cleaner/engines/target/engine_delegate_factory.h" +#include "chrome/chrome_cleaner/engines/target/sandbox_setup.h" +#include "chrome/chrome_cleaner/executables/shutdown_sequence.h" +#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" +#include "chrome/chrome_cleaner/ipc/sandbox.h" +#include "chrome/chrome_cleaner/logging/logging_service_api.h" +#include "chrome/chrome_cleaner/logging/registry_logger.h" +#include "chrome/chrome_cleaner/logging/scoped_logging.h" +#include "chrome/chrome_cleaner/os/disk_util.h" +#include "chrome/chrome_cleaner/os/early_exit.h" +#include "chrome/chrome_cleaner/os/file_path_sanitization.h" +#include "chrome/chrome_cleaner/os/initializer.h" +#include "chrome/chrome_cleaner/os/secure_dll_loading.h" +#include "chrome/chrome_cleaner/os/system_util.h" +#include "chrome/chrome_cleaner/os/task_scheduler.h" +#include "chrome/chrome_cleaner/parsers/broker/sandbox_setup_hooks.h" +#include "chrome/chrome_cleaner/parsers/shortcut_parser/broker/sandboxed_shortcut_parser.h" +#include "chrome/chrome_cleaner/parsers/shortcut_parser/broker/shortcut_parser_api.h" +#include "chrome/chrome_cleaner/parsers/target/sandbox_setup.h" +#include "chrome/chrome_cleaner/scanner/scanner_controller.h" +#include "chrome/chrome_cleaner/settings/default_matching_options.h" +#include "chrome/chrome_cleaner/settings/engine_settings.h" +#include "chrome/chrome_cleaner/settings/matching_options.h" +#include "chrome/chrome_cleaner/settings/settings.h" +#include "chrome/chrome_cleaner/settings/settings_types.h" +#include "components/chrome_cleaner/public/constants/result_codes.h" +#include "sandbox/win/src/sandbox_factory.h" + +using chrome_cleaner::MojoTaskRunner; + +namespace { + +void WriteExitMetrics(chrome_cleaner::ResultCode result_code, + chrome_cleaner::RegistryLogger* registry_logger) { + registry_logger->WriteExitCode(result_code); + registry_logger->WriteEndTime(); + + PROCESS_MEMORY_COUNTERS pmc; + // TODO(joenotcharles): Log the total memory consumption instead of just the + // main process'. + if (::GetProcessMemoryInfo(::GetCurrentProcess(), &pmc, sizeof(pmc))) { + registry_logger->WriteMemoryUsage(pmc.PeakWorkingSetSize / 1024); + } +} + +chrome_cleaner::ResultCode FinalizeWithResultCode( + chrome_cleaner::ResultCode result_code, + chrome_cleaner::RegistryLogger* registry_logger) { + chrome_cleaner::TaskScheduler::Terminate(); + LOG(INFO) << "Exiting with code: " << result_code; + + WriteExitMetrics(result_code, registry_logger); + return result_code; +} + +void TerminateOnSandboxConnectionError( + const base::WeakPtr<chrome_cleaner::RegistryLogger>& registry_logger, + const chrome_cleaner::SandboxType sandbox_type) { + // If |registry_logger| has been deleted, the process is dying anyway, so no + // action is needed. + if (!registry_logger) + return; + + chrome_cleaner::ResultCode result_code = + chrome_cleaner::GetResultCodeForSandboxConnectionError(sandbox_type); + WriteExitMetrics(result_code, registry_logger.get()); + chrome_cleaner::EarlyExit(result_code); +} + +void CallTerminateOnSandboxConnectionError( + scoped_refptr<base::SequencedTaskRunner> task_runner, + const base::WeakPtr<chrome_cleaner::RegistryLogger>& registry_logger, + const chrome_cleaner::SandboxType sandbox_type) { + // Weakptr has to be dereferenced on its factory thread. + task_runner->PostTask(FROM_HERE, + base::BindOnce(TerminateOnSandboxConnectionError, + registry_logger, sandbox_type)); +} + +} // namespace + +int APIENTRY wWinMain(HINSTANCE, HINSTANCE, wchar_t*, int) { + // This must be executed as soon as possible to reduce the number of dlls that + // the code might try to load before we can lock things down. + chrome_cleaner::EnableSecureDllLoading(); + + base::AtExitManager at_exit; + + // This must be done BEFORE constructing ScopedLogging, which calls + // InitLogging to set the name of the log file, which needs to read + // from the command line. + bool success = base::CommandLine::Init(0, nullptr); + DCHECK(success); + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + + // If this process should run as the crash reporter, run that then return + // immediately, as this process is not meant to be the reporter itself. + if (command_line->HasSwitch(chrome_cleaner::kCrashHandlerSwitch)) + return CrashReporterMain(); + + // GetTargetServices() returns non-null if this is the sandbox target, and + // null otherwise. + sandbox::TargetServices* sandbox_target_services = + sandbox::SandboxFactory::GetTargetServices(); + const bool is_sandbox_target = (sandbox_target_services != nullptr); + chrome_cleaner::ScopedLogging scoped_logging( + is_sandbox_target ? chrome_cleaner::kSandboxLogFileSuffix : nullptr); + + // If there is a command line argument to add a registry suffix, set + // the value for the registry_logger. + const std::string registry_suffix = + command_line->GetSwitchValueASCII(chrome_cleaner::kRegistrySuffixSwitch); + + chrome_cleaner::RegistryLogger registry_logger( + chrome_cleaner::RegistryLogger::Mode::REPORTER, registry_suffix); + + // Weak pointer for connection error callback which may outlive the main. It + // will be destroyed at the end of main before registry_logger. + base::WeakPtrFactory<chrome_cleaner::RegistryLogger> + registry_logger_weak_factory(®istry_logger); + + chrome_cleaner::ShutdownSequence shutdown_sequence; + + if (!chrome_cleaner::InitializeOSUtils()) { + return FinalizeWithResultCode( + chrome_cleaner::RESULT_CODE_INITIALIZATION_ERROR, ®istry_logger); + } + + // Start the crash handler only for the reporter process. The sandbox process + // will use the handler process that was started by the reporter. + if (command_line->HasSwitch(chrome_cleaner::kUseCrashHandlerWithIdSwitch)) { + DCHECK(is_sandbox_target); + const base::string16 ipc_pipe_name = command_line->GetSwitchValueNative( + chrome_cleaner::kUseCrashHandlerWithIdSwitch); + CHECK(!ipc_pipe_name.empty()); + UseCrashReporter(ipc_pipe_name); + } else if (!is_sandbox_target) { + // Start the crash reporter only if this is not the sandbox target. This is + // the case for tests, where the |kUseCrashHandlerWithIdSwitch| switch is + // not passed (and we don't want a crash reporter process to be started). + StartCrashReporter(CHROME_CLEANER_VERSION_UTF8_STRING); + } + + LOG(INFO) << "Command line arguments: " + << chrome_cleaner::SanitizeCommandLine(*command_line); + + const chrome_cleaner::CrashClient::Mode crash_client_mode = + chrome_cleaner::CrashClient::Mode::REPORTER; + + chrome_cleaner::SandboxType sandbox_type = + is_sandbox_target ? chrome_cleaner::SandboxProcessType() + : chrome_cleaner::SandboxType::kNonSandboxed; + + if (!chrome_cleaner::CrashClient::GetInstance()->InitializeCrashReporting( + crash_client_mode, sandbox_type)) { + LOG(INFO) << "Crash reporting is not available."; + } else { + LOG(INFO) << "Crash reporting initialized."; + } + + // Make sure not to take too much of the machines's resources. + chrome_cleaner::SetBackgroundMode(); + + const chrome_cleaner::Settings* settings = + chrome_cleaner::Settings::GetInstance(); + + if (is_sandbox_target) { + switch (sandbox_type) { + case chrome_cleaner::SandboxType::kEngine: + return RunEngineSandboxTarget( + chrome_cleaner::CreateEngineDelegate(settings->engine()), + *command_line, sandbox_target_services); + case chrome_cleaner::SandboxType::kParser: + return chrome_cleaner::RunParserSandboxTarget(*command_line, + sandbox_target_services); + default: + NOTREACHED() << "Unknown sandbox type " + << static_cast<int>(sandbox_type); + } + } + + registry_logger.ClearScanTimes(); + registry_logger.ClearExitCode(); + registry_logger.WriteStartTime(); + + if (!settings->scan_switches_correct()) { + return FinalizeWithResultCode( + chrome_cleaner::RESULT_CODE_INVALID_SCANNING_SWITCHES, + ®istry_logger); + } + + // Many pieces of code below need a message loop to have been instantiated + // before them. + base::TaskScheduler::CreateAndStartWithDefaultParams("software reporter"); + base::MessageLoopForUI ui_message_loop; + + shutdown_sequence.mojo_task_runner = MojoTaskRunner::Create(); + + if (!chrome_cleaner::IsSupportedEngine(settings->engine())) { + LOG(FATAL) << "Unsupported engine " << settings->engine(); + return FinalizeWithResultCode(chrome_cleaner::RESULT_CODE_FAILED, + ®istry_logger); + } + + chrome_cleaner::InitializePUPDataWithCatalog(settings->engine()); + + base::string16 interface_log_file; + if (command_line->HasSwitch(chrome_cleaner::kLogInterfaceCallsToSwitch)) { + interface_log_file = command_line->GetSwitchValueNative( + chrome_cleaner::kLogInterfaceCallsToSwitch); + base::FilePath passed_name(interface_log_file); + std::vector<base::string16> components; + passed_name.GetComponents(&components); + if (components.size() != 1) { + LOG(ERROR) << "Invalid file name passed for logging!"; + return FinalizeWithResultCode(chrome_cleaner::RESULT_CODE_FAILED, + ®istry_logger); + } + } + + auto sandbox_connection_error_callback = + base::BindRepeating(CallTerminateOnSandboxConnectionError, + base::SequencedTaskRunnerHandle::Get(), + registry_logger_weak_factory.GetWeakPtr()); + + std::unique_ptr<chrome_cleaner::InterfaceLogService> interface_log_service = + chrome_cleaner::InterfaceLogService::Create( + interface_log_file, CHROME_CLEANER_VERSION_STRING); + + chrome_cleaner::ResultCode engine_result_code; + std::tie(engine_result_code, shutdown_sequence.engine_client) = + chrome_cleaner::SpawnEngineSandbox(settings->engine(), ®istry_logger, + shutdown_sequence.mojo_task_runner, + sandbox_connection_error_callback, + std::move(interface_log_service)); + if (engine_result_code != chrome_cleaner::RESULT_CODE_SUCCESS) + return FinalizeWithResultCode(engine_result_code, ®istry_logger); + + // CoInitialize into the MTA since we desire to use the task scheduler. + base::win::ScopedCOMInitializer scoped_com_initializer( + base::win::ScopedCOMInitializer::kMTA); + bool succeeded = chrome_cleaner::TaskScheduler::Initialize(); + DCHECK(succeeded) << "TaskScheduler::Initialize() failed"; + + // Initialize the sandbox for the shortcut parser. + chrome_cleaner::UniqueParserPtr parser_ptr( + nullptr, base::OnTaskRunnerDeleter(nullptr)); + chrome_cleaner::ResultCode parser_result_code = + chrome_cleaner::SpawnParserSandbox( + shutdown_sequence.mojo_task_runner.get(), + sandbox_connection_error_callback, &parser_ptr); + if (parser_result_code != chrome_cleaner::RESULT_CODE_SUCCESS) + return FinalizeWithResultCode(parser_result_code, ®istry_logger); + std::unique_ptr<chrome_cleaner::ShortcutParserAPI> shortcut_parser = + std::make_unique<chrome_cleaner::SandboxedShortcutParser>( + shutdown_sequence.mojo_task_runner.get(), parser_ptr.get()); + + std::unique_ptr<chrome_cleaner::ScannerController> scanner_controller = + std::make_unique<chrome_cleaner::ScannerControllerImpl>( + shutdown_sequence.engine_client.get(), ®istry_logger, + base::SequencedTaskRunnerHandle::Get(), shortcut_parser.get()); + + if (command_line->HasSwitch(chrome_cleaner::kCrashSwitch)) { + int* crash_me = nullptr; + *crash_me = 42; + } + + if (command_line->HasSwitch(chrome_cleaner::kLoadEmptyDLLSwitch)) { + chrome_cleaner::testing::LoadEmptyDLL(); + } + chrome_cleaner::NotifyInitializationDoneForTesting(); + + auto result_code = + static_cast<chrome_cleaner::ResultCode>(scanner_controller->ScanOnly()); + return FinalizeWithResultCode(result_code, ®istry_logger); +}
diff --git a/chrome/chrome_cleaner/executables/shutdown_sequence.cc b/chrome/chrome_cleaner/executables/shutdown_sequence.cc new file mode 100644 index 0000000..5d50ca29 --- /dev/null +++ b/chrome/chrome_cleaner/executables/shutdown_sequence.cc
@@ -0,0 +1,36 @@ +// 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. + +#include "chrome/chrome_cleaner/executables/shutdown_sequence.h" +#include "base/task/task_scheduler/task_scheduler.h" + +#include "base/task/task_scheduler/task_scheduler.h" + +namespace chrome_cleaner { + +ShutdownSequence::ShutdownSequence() = default; + +ShutdownSequence::ShutdownSequence(ShutdownSequence&& other) + : engine_client(std::move(other.engine_client)), + mojo_task_runner(std::move(other.mojo_task_runner)), + engine_facade(std::move(other.engine_facade)) {} + +ShutdownSequence::~ShutdownSequence() { + if (!mojo_task_runner) + return; + + auto* task_scheduler = base::TaskScheduler::GetInstance(); + if (task_scheduler) + task_scheduler->Shutdown(); + + // Objects that post messages to themselves with base::Unretained must be + // destroyed after TaskScheduler::Shutdown, otherwise some tasks might be + // still referencing recently destroyed objects. + + engine_facade.reset(); + engine_client.reset(); + mojo_task_runner.reset(); +} + +} // namespace chrome_cleaner
diff --git a/chrome/chrome_cleaner/executables/shutdown_sequence.h b/chrome/chrome_cleaner/executables/shutdown_sequence.h new file mode 100644 index 0000000..abd909d --- /dev/null +++ b/chrome/chrome_cleaner/executables/shutdown_sequence.h
@@ -0,0 +1,30 @@ +// 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. + +#ifndef CHROME_CHROME_CLEANER_EXECUTABLES_SHUTDOWN_SEQUENCE_H_ +#define CHROME_CHROME_CLEANER_EXECUTABLES_SHUTDOWN_SEQUENCE_H_ + +#include "base/memory/scoped_refptr.h" +#include "chrome/chrome_cleaner/engines/broker/engine_client.h" +#include "chrome/chrome_cleaner/engines/controllers/engine_facade_interface.h" +#include "chrome/chrome_cleaner/ipc/mojo_task_runner.h" + +namespace chrome_cleaner { + +// Helper to ensure correct order of destruction of mojo-related objects during +// the shutdown sequence. For it to work correctly, there must not be any other +// references to the object's fields. +struct ShutdownSequence { + ShutdownSequence(); + ShutdownSequence(ShutdownSequence&& other); + ~ShutdownSequence(); + + scoped_refptr<EngineClient> engine_client; + scoped_refptr<MojoTaskRunner> mojo_task_runner; + std::unique_ptr<EngineFacadeInterface> engine_facade; +}; + +} // namespace chrome_cleaner + +#endif // CHROME_CHROME_CLEANER_EXECUTABLES_SHUTDOWN_SEQUENCE_H_
diff --git a/chrome/chrome_cleaner/logging/BUILD.gn b/chrome/chrome_cleaner/logging/BUILD.gn index 454278f0..d9048ba 100644 --- a/chrome/chrome_cleaner/logging/BUILD.gn +++ b/chrome/chrome_cleaner/logging/BUILD.gn
@@ -69,6 +69,46 @@ ] } +# Logging definitions that must only by linked into the cleaner executable. +# This is separate from cleaner_logging, which is also linked with unit tests. +source_set("cleaner_logging_definitions") { + sources = [ + "cleaner_logging_definitions.cc", + ] + + deps = [ + ":cleaner_logging", + ":logging_definitions", + ] +} + +# Logging definitions that must only by linked into the reporter executable. +# This is separate from reporter_logging, which is also linked with unit tests. +source_set("reporter_logging_definitions") { + sources = [ + "reporter_logging_definitions.cc", + ] + + deps = [ + ":logging_definitions", + ":noop_logging", + ":reporter_logging", + "//chrome/chrome_cleaner/settings:settings", + ] +} + +# Logging definitions that are linked into all other executables. +source_set("other_logging_definitions") { + sources = [ + "other_logging_definitions.cc", + ] + + deps = [ + ":logging_definitions", + ":noop_logging", + ] +} + source_set("api_keys_header") { sources = [ "api_keys.h", @@ -110,6 +150,7 @@ deps = [ ":api_keys", ":api_keys_header", + ":common", "//base", "//chrome/chrome_cleaner/chrome_utils:chrome_util_lib", "//chrome/chrome_cleaner/constants:chrome_cleanup_tool_branding_header", @@ -125,10 +166,6 @@ "//chrome/chrome_cleaner/strings", "//components/chrome_cleaner/public/constants:constants", ] - - public_deps = [ - ":common", - ] } static_library("reporter_logging") { @@ -140,6 +177,7 @@ deps = [ ":api_keys", ":api_keys_header", + ":common", "//base", "//chrome/chrome_cleaner/chrome_utils:chrome_util_lib", "//chrome/chrome_cleaner/constants:common_strings", @@ -152,10 +190,6 @@ "//chrome/chrome_cleaner/settings:settings", "//components/chrome_cleaner/public/constants:constants", ] - - public_deps = [ - ":common", - ] } static_library("noop_logging") { @@ -234,6 +268,7 @@ "//chrome/chrome_cleaner/constants:version_header", "//chrome/chrome_cleaner/http:http", "//chrome/chrome_cleaner/http:mock_http_agent_factory", + "//chrome/chrome_cleaner/logging:common", "//chrome/chrome_cleaner/logging:scoped_timed_task_logger", "//chrome/chrome_cleaner/logging/proto:chrome_cleaner_report_proto", "//chrome/chrome_cleaner/logging/proto:removal_status_proto",
diff --git a/chrome/chrome_cleaner/os/BUILD.gn b/chrome/chrome_cleaner/os/BUILD.gn index c9073ae..c3d68acc 100644 --- a/chrome/chrome_cleaner/os/BUILD.gn +++ b/chrome/chrome_cleaner/os/BUILD.gn
@@ -101,6 +101,7 @@ deps = [ ":common_os", + ":file_remover_api", "//base:base", "//chrome/chrome_cleaner/constants:common_strings", "//chrome/chrome_cleaner/constants:quarantine_constants", @@ -114,7 +115,6 @@ ] public_deps = [ - ":file_remover_api", "//chrome/chrome_cleaner/logging/proto:removal_status_proto", ] }
diff --git a/chrome/chrome_cleaner/scanner/BUILD.gn b/chrome/chrome_cleaner/scanner/BUILD.gn index ca7d40f3..5337205 100644 --- a/chrome/chrome_cleaner/scanner/BUILD.gn +++ b/chrome/chrome_cleaner/scanner/BUILD.gn
@@ -22,14 +22,11 @@ "//base:base", "//chrome/chrome_cleaner/constants:common_strings", "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/pup_data:pup_data_base", "//chrome/chrome_cleaner/scanner:signature_matcher_api", "//chrome/chrome_cleaner/settings:settings", "//chrome/chrome_cleaner/strings", ] - - public_deps = [ - "//chrome/chrome_cleaner/pup_data:pup_data_base", - ] } source_set("signature_matcher") {
diff --git a/chrome/chrome_cleaner/scanner/force_installed_extension_scanner_impl.cc b/chrome/chrome_cleaner/scanner/force_installed_extension_scanner_impl.cc index 0b4aa8a9..10b20c2a 100644 --- a/chrome/chrome_cleaner/scanner/force_installed_extension_scanner_impl.cc +++ b/chrome/chrome_cleaner/scanner/force_installed_extension_scanner_impl.cc
@@ -26,6 +26,11 @@ std::unique_ptr<UwEMatchers> ForceInstalledExtensionScannerImpl::CreateUwEMatchersFromResource( int resource_id) { + if (!resource_id) { + // Use empty matchers. + LOG(WARNING) << "No UwE matchers set"; + return std::make_unique<chrome_cleaner::UwEMatchers>(); + } base::StringPiece serialized_matcher_pb; if (!chrome_cleaner::LoadResourceOfKind(resource_id, L"TEXT", &serialized_matcher_pb)) { @@ -33,9 +38,9 @@ << resource_id; return nullptr; } - chrome_cleaner::UwEMatchers matcher; - matcher.ParseFromString(serialized_matcher_pb.as_string()); - return std::make_unique<chrome_cleaner::UwEMatchers>(matcher); + auto uwe_matchers = std::make_unique<chrome_cleaner::UwEMatchers>(); + uwe_matchers->ParseFromString(serialized_matcher_pb.as_string()); + return uwe_matchers; } std::vector<ForceInstalledExtension>
diff --git a/chrome/chrome_cleaner/settings/BUILD.gn b/chrome/chrome_cleaner/settings/BUILD.gn index 7db4c30..eb21429 100644 --- a/chrome/chrome_cleaner/settings/BUILD.gn +++ b/chrome/chrome_cleaner/settings/BUILD.gn
@@ -56,6 +56,39 @@ ] } +# Settings definitions that must only by linked into the cleaner executable. +source_set("cleaner_settings_definitions") { + sources = [ + "cleaner_settings_definitions.cc", + ] + + deps = [ + ":settings_definitions", + ] +} + +# Settings definitions that must only by linked into the reporter executable. +source_set("reporter_settings_definitions") { + sources = [ + "reporter_settings_definitions.cc", + ] + + deps = [ + ":settings_definitions", + ] +} + +# Settings definitions that are linked into all other executables. +source_set("other_settings_definitions") { + sources = [ + "other_settings_definitions.cc", + ] + + deps = [ + ":settings_definitions", + ] +} + source_set("matching_options") { sources = [ "matching_options.cc",
diff --git a/chrome/chrome_cleaner/test/BUILD.gn b/chrome/chrome_cleaner/test/BUILD.gn index cbe5f9f..d5216c5 100644 --- a/chrome/chrome_cleaner/test/BUILD.gn +++ b/chrome/chrome_cleaner/test/BUILD.gn
@@ -183,6 +183,7 @@ "//chrome/chrome_cleaner/constants:common_strings", "//chrome/chrome_cleaner/os:cleaner_os", "//chrome/chrome_cleaner/os:common_os", + "//chrome/chrome_cleaner/os:file_remover_api", "//chrome/chrome_cleaner/pup_data:pup_data_base", "//chrome/chrome_cleaner/scanner:matcher_util", "//chrome/chrome_cleaner/scanner:signature_matcher_api",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 8b269df6..43b7382 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -474,7 +474,7 @@ // Enables usage of Parent Access Code to authorize certain actions on child // user device. const base::Feature kParentAccessCode{"ParentAccessCode", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; #endif // Delegate permissions to cross-origin iframes when the feature has been
diff --git a/chrome/test/data/android/cct_target_blank.html b/chrome/test/data/android/cct_target_blank.html new file mode 100644 index 0000000..e5a69eb --- /dev/null +++ b/chrome/test/data/android/cct_target_blank.html
@@ -0,0 +1,8 @@ +<html> + </head><title>CCT Target Blank Test Page</title></head> + <body> + <!-- Unlike popup_on_click.html, this leads to a different page which is vital to test + Chrome Custom Tab's navigate on close feature. --> + <a id="target_blank_link" href="google.html" target="_blank">Click Here</a> + </body> +</html>
diff --git a/chrome/test/data/webrtc/peerconnection_getstats.js b/chrome/test/data/webrtc/peerconnection_getstats.js index 68bcd3a..5805968 100644 --- a/chrome/test/data/webrtc/peerconnection_getstats.js +++ b/chrome/test/data/webrtc/peerconnection_getstats.js
@@ -9,35 +9,160 @@ * exposed to the web) RTCStats-derived dictionaries described below. * @private */ -var gStatsWhitelist = new Map(); +let gStatsWhitelist = new Map(); /** - * RTCRTPStreamStats + * RTCRtpStreamStats * https://w3c.github.io/webrtc-stats/#streamstats-dict* * @private */ -var kRTCRTPStreamStats = new RTCStats_(null, { +let kRTCRtpStreamStats = new RTCStats(null, { ssrc: 'number', - associateStatsId: 'string', - isRemote: 'boolean', - mediaType: 'string', + isRemote: 'boolean', // Obsolete, type reveals if "remote-" or not. kind: 'string', - trackId: 'string', + mediaType: 'string', // Obsolete, replaced by |kind|. transportId: 'string', codecId: 'string', +}); + +/** + * RTCReceivedRtpStreamStats + * https://w3c.github.io/webrtc-stats/#dom-rtcreceivedrtpstreamstats + * @private + */ +let kRTCReceivedRtpStreamStats = new RTCStats(kRTCRtpStreamStats, { + packetsReceived: 'number', + packetsLost: 'number', + jitter: 'number', + packetsDiscarded: 'number', + packetsRepaired: 'number', + burstPacketsLost: 'number', + burstPacketsDiscarded: 'number', + burstLossCount: 'number', + burstDiscardCount: 'number', + burstLossRate: 'number', + burstDiscardRate: 'number', + gapLossRate: 'number', + gapDiscardRate: 'number', +}); + +/* + * RTCInboundRTPStreamStats + * https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict* + * @private + */ +let kRTCInboundRtpStreamStats = new RTCStats(kRTCReceivedRtpStreamStats, { + trackId: 'string', + receiverId: 'string', + remoteId: 'string', + framesDecoded: 'number', + qpSum: 'number', + lastPacketReceivedTimestamp: 'number', + averageRtcpInterval: 'number', + fecPacketsReceived: 'number', + fecPacketsDiscarded: 'number', + bytesReceived: 'number', + packetsFailedDecryption: 'number', + packetsDuplicated: 'number', + perDscpPacketsReceived: 'object', + nackCount: 'number', firCount: 'number', pliCount: 'number', - nackCount: 'number', sliCount: 'number', - qpSum: 'number', + fractionLost: 'number', // Obsolete, moved to RTCRemoteInboundRtpStreamStats. }); +gStatsWhitelist.set('inbound-rtp', kRTCInboundRtpStreamStats); + +/* + * RTCRemoteInboundRtpStreamStats + * https://w3c.github.io/webrtc-stats/#remoteinboundrtpstats-dict* + * @private + */ +let kRTCRemoteInboundRtpStreamStats = + new RTCStats(kRTCReceivedRtpStreamStats, { + localId: 'string', + roundTripTime: 'number', + fractionLost: 'number', +}); +// TODO(hbos): Add this to the whitelist when it has been implemented. Adding it +// before then will tag it as missing. +// gStatsWhitelist.set('remote-inbound-rtp', kRTCRemoteInboundRtpStreamStats); + +/** + * RTCSentRtpStreamStats + * https://w3c.github.io/webrtc-stats/#dom-rtcsentrtpstreamstats + * @private + */ +let kRTCSentRtpStreamStats = new RTCStats(kRTCRtpStreamStats, { + packetsSent: 'number', + packetsDiscardedOnSend: 'number', + fecPacketsSent: 'number', + bytesSent: 'number', + bytesDiscardedOnSend: 'number', +}); + +/* + * RTCOutboundRtpStreamStats + * https://w3c.github.io/webrtc-stats/#outboundrtpstats-dict* + * @private + */ +let kRTCOutboundRtpStreamStats = new RTCStats(kRTCSentRtpStreamStats, { + trackId: 'string', + senderId: 'string', + remoteId: 'string', + lastPacketSentTimestamp: 'number', + retransmittedPacketsSent: 'number', + retransmittedBytesSent: 'number', + targetBitrate: 'number', + totalEncodedBytesTarget: 'number', + framesEncoded: 'number', + qpSum: 'number', + totalEncodeTime: 'number', + averageRtcpInterval: 'number', + qualityLimitationReason: 'string', + qualityLimitationDurations: 'object', + perDscpPacketsSent: 'object', + nackCount: 'number', + firCount: 'number', + pliCount: 'number', + sliCount: 'number', +}); +gStatsWhitelist.set('outbound-rtp', kRTCOutboundRtpStreamStats); + +/* + * RTCRemoteOutboundRtpStreamStats + * https://w3c.github.io/webrtc-stats/#dom-rtcremoteoutboundrtpstreamstats + * @private + */ +let kRTCRemoteOutboundRtpStreamStats = new RTCStats(kRTCSentRtpStreamStats, { + localId: 'string', + remoteTimestamp: 'number', +}); +// TODO(hbos): Add this to the whitelist when it has been implemented. Adding it +// before then will tag it as missing. +// gStatsWhitelist.set('remote-outbound-rtp', kRTCRemoteOutboundRtpStreamStats); + +/* + * RTCRtpContributingSourceStats + * https://w3c.github.io/webrtc-stats/#dom-rtcrtpcontributingsourcestats + * @private + */ +let kRTCRtpContributingSourceStats = new RTCStats(null, { + contributorSsrc: 'number', + inboundRtpStreamId: 'string', + packetsContributedTo: 'number', + audioLevel: 'number', +}); +// TODO(hbos): Add this to the whitelist when it has been implemented. Adding it +// before then will tag it as missing. +// gStatsWhitelist.set('csrc', kRTCRtpContributingSourceStats); /* * RTCCodecStats * https://w3c.github.io/webrtc-stats/#codec-dict* * @private */ -var kRTCCodecStats = new RTCStats_(null, { +let kRTCCodecStats = new RTCStats(null, { payloadType: 'number', mimeType: 'string', // TODO(hbos): As soon as |codec| has been renamed |mimeType| in the webrtc @@ -51,50 +176,11 @@ gStatsWhitelist.set('codec', kRTCCodecStats); /* - * RTCInboundRTPStreamStats - * https://w3c.github.io/webrtc-stats/#inboundrtpstats-dict* - * @private - */ -var kRTCInboundRTPStreamStats = new RTCStats_(kRTCRTPStreamStats, { - packetsReceived: 'number', - bytesReceived: 'number', - packetsLost: 'number', - jitter: 'number', - fractionLost: 'number', - packetsDiscarded: 'number', - packetsRepaired: 'number', - burstPacketsLost: 'number', - burstPacketsDiscarded: 'number', - burstLossCount: 'number', - burstDiscardCount: 'number', - burstLossRate: 'number', - burstDiscardRate: 'number', - gapLossRate: 'number', - gapDiscardRate: 'number', - framesDecoded: 'number', -}); -gStatsWhitelist.set('inbound-rtp', kRTCInboundRTPStreamStats); - -/* - * RTCOutboundRTPStreamStats - * https://w3c.github.io/webrtc-stats/#outboundrtpstats-dict* - * @private - */ -var kRTCOutboundRTPStreamStats = new RTCStats_(kRTCRTPStreamStats, { - packetsSent: 'number', - bytesSent: 'number', - targetBitrate: 'number', - roundTripTime: 'number', - framesEncoded: 'number', -}); -gStatsWhitelist.set('outbound-rtp', kRTCOutboundRTPStreamStats); - -/* * RTCPeerConnectionStats * https://w3c.github.io/webrtc-stats/#pcstats-dict* * @private */ -var kRTCPeerConnectionStats = new RTCStats_(null, { +let kRTCPeerConnectionStats = new RTCStats(null, { dataChannelsOpened: 'number', dataChannelsClosed: 'number', dataChannelsRequested: 'number', @@ -107,7 +193,7 @@ * https://w3c.github.io/webrtc-stats/#msstats-dict* * @private */ -var kRTCMediaStreamStats = new RTCStats_(null, { +let kRTCMediaStreamStats = new RTCStats(null, { streamIdentifier: 'string', trackIds: 'sequence_string', }); @@ -118,7 +204,7 @@ * https://w3c.github.io/webrtc-stats/#mststats-dict* * @private */ -var kRTCMediaStreamTrackStats = new RTCStats_(null, { +let kRTCMediaStreamTrackStats = new RTCStats(null, { trackIdentifier: 'string', remoteSource: 'boolean', ended: 'boolean', @@ -158,7 +244,7 @@ * https://w3c.github.io/webrtc-stats/#dcstats-dict* * @private */ -var kRTCDataChannelStats = new RTCStats_(null, { +let kRTCDataChannelStats = new RTCStats(null, { label: 'string', protocol: 'string', datachannelid: 'number', @@ -175,7 +261,7 @@ * https://w3c.github.io/webrtc-stats/#transportstats-dict* * @private */ -var kRTCTransportStats = new RTCStats_(null, { +let kRTCTransportStats = new RTCStats(null, { bytesSent: 'number', bytesReceived: 'number', rtcpTransportStatsId: 'string', @@ -191,7 +277,7 @@ * https://w3c.github.io/webrtc-stats/#icecandidate-dict* * @private */ -var kRTCIceCandidateStats = new RTCStats_(null, { +let kRTCIceCandidateStats = new RTCStats(null, { transportId: 'string', isRemote: 'boolean', networkType: 'string', @@ -212,7 +298,7 @@ * https://w3c.github.io/webrtc-stats/#candidatepair-dict* * @private */ -var kRTCIceCandidatePairStats = new RTCStats_(null, { +let kRTCIceCandidatePairStats = new RTCStats(null, { transportId: 'string', localCandidateId: 'string', remoteCandidateId: 'string', @@ -245,7 +331,7 @@ * https://w3c.github.io/webrtc-stats/#certificatestats-dict* * @private */ -var kRTCCertificateStats = new RTCStats_(null, { +let kRTCCertificateStats = new RTCStats(null, { fingerprint: 'string', fingerprintAlgorithm: 'string', base64Certificate: 'string', @@ -351,7 +437,7 @@ // Internals. /** @private */ -function RTCStats_(parent, membersObject) { +function RTCStats(parent, membersObject) { if (parent != null) Object.assign(this, parent); Object.assign(this, membersObject); @@ -387,7 +473,8 @@ continue; } if (!whitelistedStats.hasOwnProperty(propertyName)) { - throw failTest('stats.' + propertyName + ' is not a whitelisted ' + + throw failTest( + stats.type + '.' + propertyName + ' is not a whitelisted ' + 'member: ' + stats[propertyName]); } if (whitelistedStats[propertyName] === 'any')
diff --git a/components/arc/ime/arc_ime_service.cc b/components/arc/ime/arc_ime_service.cc index 18a58f4..54ba67f 100644 --- a/components/arc/ime/arc_ime_service.cc +++ b/components/arc/ime/arc_ime_service.cc
@@ -340,8 +340,6 @@ // Overridden from keyboard::KeyboardControllerObserver void ArcImeService::OnKeyboardAppearanceChanged( const keyboard::KeyboardStateDescriptor& state) { - if (!focused_arc_window_) - return; gfx::Rect new_bounds = state.occluded_bounds; // Multiply by the scale factor. To convert from DIP to physical pixels. // The default scale factor is always used in Android side regardless of
diff --git a/components/autofill/core/browser/address_email_form_label_formatter.cc b/components/autofill/core/browser/address_email_form_label_formatter.cc index 9e831633..486cf7e 100644 --- a/components/autofill/core/browser/address_email_form_label_formatter.cc +++ b/components/autofill/core/browser/address_email_form_label_formatter.cc
@@ -18,8 +18,8 @@ AddressEmailFormLabelFormatter::~AddressEmailFormLabelFormatter() {} // Note that the order--name, address, and email--in which parts of the label -// are added ensures that the label is formatted correctly for |group| and for -// this kind of formatter. +// are added ensures that the label is formatted correctly for |focused_group| +// and for this kind of formatter. base::string16 AddressEmailFormLabelFormatter::GetLabelForProfile( const AutofillProfile& profile, FieldTypeGroup focused_group) const {
diff --git a/components/autofill/core/browser/address_phone_form_label_formatter.cc b/components/autofill/core/browser/address_phone_form_label_formatter.cc index 80438e4..63b0d785 100644 --- a/components/autofill/core/browser/address_phone_form_label_formatter.cc +++ b/components/autofill/core/browser/address_phone_form_label_formatter.cc
@@ -17,22 +17,21 @@ AddressPhoneFormLabelFormatter::~AddressPhoneFormLabelFormatter() {} -// Note that the order--phone, name, and address--in which parts of the label -// are added ensures that the label is formatted correctly for the focused -// group. +// Note that the order--name, phone, and address--in which parts of the label +// are added ensures that the label is formatted correctly for |focused_group| +// and for this kind of formatter. base::string16 AddressPhoneFormLabelFormatter::GetLabelForProfile( const AutofillProfile& profile, FieldTypeGroup focused_group) const { std::vector<base::string16> label_parts; + if (focused_group != NAME) { + AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts); + } if (focused_group != PHONE_HOME) { AddLabelPartIfNotEmpty(GetLabelPhone(profile, app_locale()), &label_parts); } - if (focused_group != NAME) { - AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts); - } - if (focused_group != ADDRESS_HOME) { AddLabelPartIfNotEmpty( GetLabelAddress(form_has_street_address_, profile, app_locale(),
diff --git a/components/autofill/core/browser/address_phone_form_label_formatter_unittest.cc b/components/autofill/core/browser/address_phone_form_label_formatter_unittest.cc index bb5f64c..e8bfaec 100644 --- a/components/autofill/core/browser/address_phone_form_label_formatter_unittest.cc +++ b/components/autofill/core/browser/address_phone_form_label_formatter_unittest.cc
@@ -99,7 +99,7 @@ EXPECT_THAT( formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2, &profile3, &profile4}), - ElementsAre(FormatExpectedLabel("(617) 730-2000", "John F Kennedy"), + ElementsAre(FormatExpectedLabel("John F Kennedy", "(617) 730-2000"), base::ASCIIToUTF16("Jackie Kennedy"), base::ASCIIToUTF16("(617) 523-2338"), base::string16())); } @@ -187,8 +187,8 @@ EXPECT_THAT( formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2}), - ElementsAre(FormatExpectedLabel("(11) 2648-0254", "Tarsila do Amaral"), - FormatExpectedLabel("(21) 98765-0000", "Artur Avila"))); + ElementsAre(FormatExpectedLabel("Tarsila do Amaral", "(11) 2648-0254"), + FormatExpectedLabel("Artur Avila", "(21) 98765-0000"))); } TEST(AddressPhoneFormLabelFormatterTest,
diff --git a/components/autofill/core/browser/autofill_profile.cc b/components/autofill/core/browser/autofill_profile.cc index 2d3c17c4..3acbc8c 100644 --- a/components/autofill/core/browser/autofill_profile.cc +++ b/components/autofill/core/browser/autofill_profile.cc
@@ -948,7 +948,6 @@ int validity_value = 0; size_t field_type_shift = 0; for (ServerFieldType supported_type : kSupportedTypesByClientForValidation) { - DCHECK(GetValidityState(supported_type, CLIENT) != UNSUPPORTED); validity_value |= GetValidityState(supported_type, CLIENT) << field_type_shift; field_type_shift += kValidityBitsPerType;
diff --git a/components/autofill/core/browser/autofill_profile_validation_util.cc b/components/autofill/core/browser/autofill_profile_validation_util.cc index 45f0530..8adf74309 100644 --- a/components/autofill/core/browser/autofill_profile_validation_util.cc +++ b/components/autofill/core/browser/autofill_profile_validation_util.cc
@@ -41,14 +41,15 @@ using ::i18n::addressinput::MISSING_REQUIRED_FIELD; using ::i18n::addressinput::UNEXPECTED_FIELD; using ::i18n::addressinput::UNKNOWN_VALUE; +using ::i18n::addressinput::UNSUPPORTED_FIELD; using ::i18n::phonenumbers::PhoneNumberUtil; const AddressField kFields[] = {COUNTRY, ADMIN_AREA, LOCALITY, DEPENDENT_LOCALITY, POSTAL_CODE}; -const AddressProblem kProblems[] = {UNEXPECTED_FIELD, MISSING_REQUIRED_FIELD, - UNKNOWN_VALUE, INVALID_FORMAT, - MISMATCHING_VALUE}; +const AddressProblem kProblems[] = {UNEXPECTED_FIELD, MISSING_REQUIRED_FIELD, + UNKNOWN_VALUE, INVALID_FORMAT, + MISMATCHING_VALUE, UNSUPPORTED_FIELD}; // If the |address_field| is valid, set the validity state of the // |address_field| in the |profile| to the |state| and return true. @@ -269,9 +270,25 @@ AddressValidator::Status status = address_validator->ValidateAddress(address, GetFilter(), &problems); - for (auto problem : problems) - SetValidityStateForAddressField(profile, problem.first, - AutofillDataModel::INVALID); + // The address fields for which validation is not supported by the metadata + // will be marked as UNSUPPORTED_FIELDs. These fields should be treated like + // VALID fields to stay consistent. INVALID_FORMATs, MISMATCHING_VALUEs or + // UNKNOWN_VALUEs are INVALID. MISSING_REQUIRED_FIELD would be marked as EMPTY + // along other empty fields. UNEXPECTED_FIELD would mean that there is also no + // metadata for validation, therefore, they are also UNSUPPORTED_FIELDs, and + // thus they would be treated as VALID fields. + for (auto problem : problems) { + if (problem.second == UNSUPPORTED_FIELD) { + SetValidityStateForAddressField(profile, problem.first, + AutofillDataModel::VALID); + + } else if (problem.second == INVALID_FORMAT || + problem.second == MISMATCHING_VALUE || + problem.second == UNKNOWN_VALUE) { + SetValidityStateForAddressField(profile, problem.first, + AutofillDataModel::INVALID); + } + } SetEmptyValidityIfEmpty(profile);
diff --git a/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc b/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc index 4b36d54..59a29b7 100644 --- a/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc +++ b/components/autofill/core/browser/autofill_profile_validation_util_unittest.cc
@@ -197,7 +197,7 @@ // The city can't be validated, because we don't know the state, in the strict // validation this is considered as invalid. EXPECT_EQ( - AutofillDataModel::INVALID, + AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, @@ -221,7 +221,7 @@ // The city can't be validated, because we don't know the state, in the strict // validation this is considered as invalid. EXPECT_EQ( - AutofillDataModel::INVALID, + AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); EXPECT_EQ(AutofillDataModel::EMPTY, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, @@ -903,6 +903,12 @@ AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( + AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, + AutofillDataModel::CLIENT)); + EXPECT_EQ( AutofillDataModel::INVALID, profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); EXPECT_EQ(AutofillDataModel::VALID, @@ -926,6 +932,12 @@ profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, + AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); EXPECT_EQ(AutofillDataModel::INVALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, @@ -948,6 +960,12 @@ profile.GetValidityState(ADDRESS_HOME_STATE, AutofillDataModel::CLIENT)); EXPECT_EQ( AutofillDataModel::VALID, + profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); + EXPECT_EQ(AutofillDataModel::EMPTY, + profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, + AutofillDataModel::CLIENT)); + EXPECT_EQ( + AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_ZIP, AutofillDataModel::CLIENT)); EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(PHONE_HOME_WHOLE_NUMBER, @@ -1020,11 +1038,11 @@ // We can't validate city, because state is not valid, in the strict // validation this is considered as invalid. EXPECT_EQ( - AutofillDataModel::INVALID, + AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_CITY, AutofillDataModel::CLIENT)); // The dependent locality is not a Canadian field, so it's considered as // invalid. - EXPECT_EQ(AutofillDataModel::INVALID, + EXPECT_EQ(AutofillDataModel::VALID, profile.GetValidityState(ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::CLIENT)); EXPECT_EQ(AutofillDataModel::UNSUPPORTED,
diff --git a/components/autofill/core/browser/autofill_profile_validator_unittest.cc b/components/autofill/core/browser/autofill_profile_validator_unittest.cc index 5278b8b..34203afe 100644 --- a/components/autofill/core/browser/autofill_profile_validator_unittest.cc +++ b/components/autofill/core/browser/autofill_profile_validator_unittest.cc
@@ -122,11 +122,14 @@ EXPECT_EQ(false, AreRulesLoadedForRegion(country_code)); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, - {EMAIL_ADDRESS, AutofillDataModel::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -222,11 +225,14 @@ base::UTF8ToUTF16("Invalid Phone")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID}, - {EMAIL_ADDRESS, AutofillDataModel::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -238,11 +244,14 @@ profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, - {EMAIL_ADDRESS, AutofillDataModel::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -256,11 +265,14 @@ profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY}, - {EMAIL_ADDRESS, AutofillDataModel::VALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::EMPTY}, + {EMAIL_ADDRESS, AutofillDataModel::VALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -274,11 +286,14 @@ profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("Invalid Zip")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, - {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -292,11 +307,14 @@ profile.SetRawInfo(ADDRESS_HOME_ZIP, base::UTF8ToUTF16("Invalid Zip")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, - {EMAIL_ADDRESS, AutofillDataModel::EMPTY}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::INVALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::EMPTY}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -310,11 +328,14 @@ profile.SetRawInfo(ADDRESS_HOME_ZIP, base::string16()); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, - {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::EMPTY}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -329,11 +350,14 @@ base::UTF8ToUTF16("Invalid Phone")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID}, - {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -345,11 +369,14 @@ profile.SetRawInfo(EMAIL_ADDRESS, base::ASCIIToUTF16("Invalid Email")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, - {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::VALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::VALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_)); @@ -365,11 +392,14 @@ profile.SetRawInfo(ADDRESS_HOME_STATE, base::UTF8ToUTF16("Invalid State")); // Set up the test expectations. - expected_validity_ = {{ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, - {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, - {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, - {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID}, - {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; + expected_validity_ = { + {ADDRESS_HOME_COUNTRY, AutofillDataModel::VALID}, + {ADDRESS_HOME_STATE, AutofillDataModel::INVALID}, + {ADDRESS_HOME_CITY, AutofillDataModel::VALID}, + {ADDRESS_HOME_DEPENDENT_LOCALITY, AutofillDataModel::EMPTY}, + {ADDRESS_HOME_ZIP, AutofillDataModel::VALID}, + {PHONE_HOME_WHOLE_NUMBER, AutofillDataModel::INVALID}, + {EMAIL_ADDRESS, AutofillDataModel::INVALID}}; // Start the validator. validator_->StartProfileValidation(&profile, std::move(onvalidated_cb_));
diff --git a/components/autofill/core/browser/contact_form_label_formatter.cc b/components/autofill/core/browser/contact_form_label_formatter.cc index 9c81ab0e..05a7a0e 100644 --- a/components/autofill/core/browser/contact_form_label_formatter.cc +++ b/components/autofill/core/browser/contact_form_label_formatter.cc
@@ -18,21 +18,21 @@ ContactFormLabelFormatter::~ContactFormLabelFormatter() {} -// Note that the order--phone, name, and email--in which parts of the label -// are added ensures that the label is formatted correctly for |focused_group|. +// Note that the order--name, phone, and email--in which parts of the label +// are possibly added ensures that the label is formatted correctly for +// |focused_group| and for this kind of formatter. base::string16 ContactFormLabelFormatter::GetLabelForProfile( const AutofillProfile& profile, FieldTypeGroup focused_group) const { std::vector<base::string16> label_parts; + if (focused_group != NAME) { + AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts); + } if (focused_group != PHONE_HOME) { AddLabelPartIfNotEmpty(MaybeGetPhone(profile), &label_parts); } - if (focused_group != NAME) { - AddLabelPartIfNotEmpty(GetLabelName(profile, app_locale()), &label_parts); - } - if (focused_group != EMAIL) { AddLabelPartIfNotEmpty(MaybeGetEmail(profile), &label_parts); }
diff --git a/components/autofill/core/browser/contact_form_label_formatter_unittest.cc b/components/autofill/core/browser/contact_form_label_formatter_unittest.cc index dc95f6f..67add44d 100644 --- a/components/autofill/core/browser/contact_form_label_formatter_unittest.cc +++ b/components/autofill/core/browser/contact_form_label_formatter_unittest.cc
@@ -97,9 +97,9 @@ EXPECT_THAT( formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2, &profile3, &profile4}), - ElementsAre(FormatExpectedLabel("(617) 730-2000", "John F Kennedy"), + ElementsAre(FormatExpectedLabel("John F Kennedy", "(617) 730-2000"), base::ASCIIToUTF16("Jackie Kennedy"), - FormatExpectedLabel("(617) 523-2338", "Paul Revere"), + FormatExpectedLabel("Paul Revere", "(617) 523-2338"), base::string16())); } @@ -181,8 +181,8 @@ EXPECT_THAT( formatter->GetLabels(std::vector<AutofillProfile*>{&profile1, &profile2}), - ElementsAre(FormatExpectedLabel("(11) 2648-0254", "Tarsila do Amaral"), - FormatExpectedLabel("(21) 98765-0000", "Artur Avila"))); + ElementsAre(FormatExpectedLabel("Tarsila do Amaral", "(11) 2648-0254"), + FormatExpectedLabel("Artur Avila", "(21) 98765-0000"))); } TEST(ContactFormLabelFormatterTest, GetLabelsForBRProfilesAndFocusedPhone) {
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc index 414ae10..e362a13 100644 --- a/components/autofill/core/browser/personal_data_manager_unittest.cc +++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -6987,7 +6987,7 @@ EXPECT_EQ( AutofillDataModel::VALID, profiles[0]->GetValidityState(ADDRESS_HOME_ZIP, AutofillProfile::CLIENT)); - EXPECT_EQ(AutofillDataModel::INVALID, + EXPECT_EQ(AutofillDataModel::VALID, profiles[0]->GetValidityState(ADDRESS_HOME_CITY, AutofillProfile::CLIENT)); EXPECT_EQ(AutofillDataModel::EMPTY,
diff --git a/components/autofill_assistant/browser/BUILD.gn b/components/autofill_assistant/browser/BUILD.gn index 128949e..469e1db8 100644 --- a/components/autofill_assistant/browser/BUILD.gn +++ b/components/autofill_assistant/browser/BUILD.gn
@@ -170,6 +170,7 @@ "script_executor_unittest.cc", "script_precondition_unittest.cc", "script_tracker_unittest.cc", + "selector_unittest.cc", "string_conversions_util_unittest.cc", ]
diff --git a/components/autofill_assistant/browser/actions/prompt_action.cc b/components/autofill_assistant/browser/actions/prompt_action.cc index d94464f4..d9f769f 100644 --- a/components/autofill_assistant/browser/actions/prompt_action.cc +++ b/components/autofill_assistant/browser/actions/prompt_action.cc
@@ -33,7 +33,7 @@ void PromptAction::InternalProcessAction(ActionDelegate* delegate, ProcessActionCallback callback) { if (proto_.prompt().choices_size() == 0) { - UpdateProcessedAction(OTHER_ACTION_STATUS); + UpdateProcessedAction(INVALID_ACTION); std::move(callback).Run(std::move(processed_action_proto_)); return; }
diff --git a/components/autofill_assistant/browser/actions/prompt_action_unittest.cc b/components/autofill_assistant/browser/actions/prompt_action_unittest.cc index abe2649..2d8368b 100644 --- a/components/autofill_assistant/browser/actions/prompt_action_unittest.cc +++ b/components/autofill_assistant/browser/actions/prompt_action_unittest.cc
@@ -68,8 +68,9 @@ }; TEST_F(PromptActionTest, ChoicesMissing) { - EXPECT_CALL(callback_, Run(Pointee(Property(&ProcessedActionProto::status, - OTHER_ACTION_STATUS)))); + EXPECT_CALL( + callback_, + Run(Pointee(Property(&ProcessedActionProto::status, INVALID_ACTION)))); PromptAction action(proto_); action.ProcessAction(&mock_action_delegate_, callback_.Get()); }
diff --git a/components/autofill_assistant/browser/actions/show_details_action.cc b/components/autofill_assistant/browser/actions/show_details_action.cc index 3839729..1f9ff6a8 100644 --- a/components/autofill_assistant/browser/actions/show_details_action.cc +++ b/components/autofill_assistant/browser/actions/show_details_action.cc
@@ -56,7 +56,7 @@ if (!details_valid) { DVLOG(1) << "Failed to fill the details"; - UpdateProcessedAction(OTHER_ACTION_STATUS); + UpdateProcessedAction(INVALID_ACTION); } else { delegate->SetDetails(std::move(details)); UpdateProcessedAction(ACTION_APPLIED);
diff --git a/components/autofill_assistant/browser/client_status.cc b/components/autofill_assistant/browser/client_status.cc index 9c5c67b..70c40695 100644 --- a/components/autofill_assistant/browser/client_status.cc +++ b/components/autofill_assistant/browser/client_status.cc
@@ -15,12 +15,25 @@ void ClientStatus::FillProto(ProcessedActionProto* proto) const { proto->set_status(status_); - // TODO(b/129387787): Fill extra debugging information collected in the - // ClientStatus. + if (has_unexpected_error_info_) + proto->mutable_unexpected_error_info()->MergeFrom(unexpected_error_info_); } std::ostream& operator<<(std::ostream& out, const ClientStatus& status) { - return out << status.status_; + out << status.status_; +#ifndef NDEBUG + if (status.has_unexpected_error_info_) { + out << status.unexpected_error_info_.source_file() << ":" + << status.unexpected_error_info_.source_line_number(); + if (!status.unexpected_error_info_.js_exception_classname().empty()) { + out << " JS error " + << status.unexpected_error_info_.js_exception_classname() << " at " + << status.unexpected_error_info_.js_exception_line_number() << ":" + << status.unexpected_error_info_.js_exception_column_number(); + } + } +#endif + return out; } const ClientStatus& OkClientStatus() { @@ -87,6 +100,14 @@ out << "ELEMENT_UNSTABLE"; break; + case ProcessedActionStatusProto::OPTION_VALUE_NOT_FOUND: + out << "OPTION_VALUE_NOT_FOUND"; + break; + + case ProcessedActionStatusProto::UNEXPECTED_JS_ERROR: + out << "UNEXPECTED_JS_ERROR"; + break; + // Intentionally no default case to make compilation fail if a new value // was added to the enum but not to this list. }
diff --git a/components/autofill_assistant/browser/client_status.h b/components/autofill_assistant/browser/client_status.h index 7964001c..5f74d776 100644 --- a/components/autofill_assistant/browser/client_status.h +++ b/components/autofill_assistant/browser/client_status.h
@@ -30,14 +30,26 @@ // Modifies the corresponding proto status. void set_proto_status(ProcessedActionStatusProto status) { status_ = status; } + // Returns a mutable version of unexpected error info, creates one if + // necessary. + UnexpectedErrorInfoProto* mutable_unexpected_error_info() { + has_unexpected_error_info_ = true; + return &unexpected_error_info_; + } + + // Returns the unexpected error infos associated with this status. + const UnexpectedErrorInfoProto& unexpected_error_info() const { + return unexpected_error_info_; + } + // The output operator, for logging. friend std::ostream& operator<<(std::ostream& out, const ClientStatus& status); private: ProcessedActionStatusProto status_; - // TODO(b/129387787): Add more information, to be reported to - // ProcessedActionProto + bool has_unexpected_error_info_ = false; + UnexpectedErrorInfoProto unexpected_error_info_; }; // An OK status.
diff --git a/components/autofill_assistant/browser/selector.cc b/components/autofill_assistant/browser/selector.cc index 2b2ada2..b60f5d3e3 100644 --- a/components/autofill_assistant/browser/selector.cc +++ b/components/autofill_assistant/browser/selector.cc
@@ -14,6 +14,7 @@ for (const auto& selector : element.selectors()) { selectors.emplace_back(selector); } + inner_text_pattern = element.inner_text_pattern(); pseudo_type = element.pseudo_type(); } @@ -29,13 +30,24 @@ Selector& Selector::operator=(Selector&& other) = default; bool Selector::operator<(const Selector& other) const { - return this->selectors < other.selectors || - (this->selectors == other.selectors && - this->pseudo_type < other.pseudo_type); + if (selectors < other.selectors) + return true; + + if (selectors != other.selectors) + return false; + + if (inner_text_pattern < other.inner_text_pattern) + return true; + + if (inner_text_pattern != other.inner_text_pattern) + return false; + + return pseudo_type < other.pseudo_type; } bool Selector::operator==(const Selector& other) const { return this->selectors == other.selectors && + this->inner_text_pattern == other.inner_text_pattern && this->pseudo_type == other.pseudo_type; } @@ -109,6 +121,11 @@ return out; #else out << "elements=[" << base::JoinString(selector.selectors, ",") << "]"; + if (!selector.inner_text_pattern.empty()) { + out << " innerText =~ /"; + out << selector.inner_text_pattern; + out << "/"; + } if (selector.pseudo_type != PseudoType::UNDEFINED) { out << "::" << selector.pseudo_type; }
diff --git a/components/autofill_assistant/browser/selector.h b/components/autofill_assistant/browser/selector.h index 686d0d9..835b232 100644 --- a/components/autofill_assistant/browser/selector.h +++ b/components/autofill_assistant/browser/selector.h
@@ -21,6 +21,10 @@ // document. std::vector<std::string> selectors; + // If non-empty, this must be a regular expression that matches the inner text + // of the element(s) matching selectors. + std::string inner_text_pattern; + // An optional pseudo type. This pseudo type is associated to the final // element matched by |selectors|, which means that we currently don't handle // matching an element inside a pseudo element. @@ -46,6 +50,12 @@ // Checks whether this selector is empty. bool empty() const; + + // Convenience function to set inner_text_pattern in a fluent style. + Selector& MatchingInnerText(const std::string& pattern) { + inner_text_pattern = pattern; + return *this; + } }; } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/selector_unittest.cc b/components/autofill_assistant/browser/selector_unittest.cc new file mode 100644 index 0000000..94a4346 --- /dev/null +++ b/components/autofill_assistant/browser/selector_unittest.cc
@@ -0,0 +1,49 @@ +// 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. + +#include "components/autofill_assistant/browser/selector.h" + +#include "base/macros.h" +#include "components/autofill_assistant/browser/service.pb.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace autofill_assistant { +namespace { + +TEST(SelectorTest, FromProto) { + ElementReferenceProto proto; + proto.add_selectors("a"); + proto.add_selectors("b"); + proto.set_inner_text_pattern("c"); + proto.set_pseudo_type(PseudoType::BEFORE); + + Selector selector(proto); + EXPECT_THAT(selector.selectors, testing::ElementsAre("a", "b")); + EXPECT_EQ("c", selector.inner_text_pattern); + EXPECT_EQ(PseudoType::BEFORE, selector.pseudo_type); +} + +TEST(SelectorTest, Comparison) { + EXPECT_FALSE(Selector({"a"}) == Selector({"b"})); + EXPECT_LT(Selector({"a"}), Selector({"b"})); + EXPECT_TRUE(Selector({"a"}) == Selector({"a"})); + + EXPECT_FALSE(Selector({"a"}, PseudoType::BEFORE) == + Selector({"a"}, PseudoType::AFTER)); + EXPECT_LT(Selector({"a"}, PseudoType::BEFORE), + Selector({"a"}, PseudoType::AFTER)); + EXPECT_LT(Selector({"a"}, PseudoType::BEFORE), Selector({"b"})); + EXPECT_TRUE(Selector({"a"}, PseudoType::BEFORE) == + Selector({"a"}, PseudoType::BEFORE)); + + EXPECT_FALSE(Selector({"a"}).MatchingInnerText("a") == + Selector({"a"}).MatchingInnerText("b")); + EXPECT_LT(Selector({"a"}).MatchingInnerText("a"), + Selector({"a"}).MatchingInnerText("b")); + EXPECT_TRUE(Selector({"a"}).MatchingInnerText("a") == + Selector({"a"}).MatchingInnerText("a")); +} + +} // namespace +} // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto index d76bee5..587db658 100644 --- a/components/autofill_assistant/browser/service.proto +++ b/components/autofill_assistant/browser/service.proto
@@ -351,6 +351,44 @@ // Should be set as a result of SetFormFieldValueAction. SetFormFieldValueProto.Result set_form_field_value_result = 17; } + + // More information included for unexpected errors. + // + // Only set for action whose status are OTHER_ACTION_STATUS or + // UNEXPECTED_JS_ERROR. + optional UnexpectedErrorInfoProto unexpected_error_info = 18; +} + +// Extra debugging information included in case of unexpected errors. +// +// Presence of this element is usually the sign of a bug in the client code and +// is always the sign that the client code needs to be updated: such issues +// should be either fixed or reported as proper, expected error with a useful +// status code. +message UnexpectedErrorInfoProto { + // Source file, within the client code, where an unexpected error was detected + // and reported. + // + // Only filled for unexpected errors OTHER_ACTION_STATUS and + // UNEXPECTED_JS_ERROR. + // + // This and source_line are only meaningful for the exact version reported in + // the client context. + optional string source_file = 1; + + // Line number, within the client's source file, where the error was detected. + optional int32 source_line_number = 2; + + // JavaScript exception class name, if reporting a JavaScript error. + optional string js_exception_classname = 3; + + // JavaScript exception line number, within the js snippet that was sent to + // devtools runtime by the client, if reporting a JavaScript error. + optional int32 js_exception_line_number = 4; + + // JavaScript exception column number, within the js snippet that was sent to + // devtools runtime by the client, if reporting a JavaScript error. + optional int32 js_exception_column_number = 5; } enum ProcessedActionStatusProto { @@ -363,6 +401,12 @@ ACTION_APPLIED = 2; // The action failed (generic error). + // + // This usually means that the client needs to be fixed: either the error + // should be assigned a more specific error code, or a bug in the client code + // needs to be fixed. + // + // ProcessedActionProto.UnexpectedErrorInfoProto contains more details. OTHER_ACTION_STATUS = 3; // The action failed to get payment information. @@ -418,6 +462,16 @@ // Failed to get a stable position for the element, usually to click on it. ELEMENT_UNSTABLE = 14; + + // The value passed to the select option action does not exist in the element. + // This is usually a scripting error. + OPTION_VALUE_NOT_FOUND = 15; + + // The client got an unexpected error from a JavaScript snippet executed + // through devtools. This means that there's a bug in the client code. + // + // ProcessedActionProto.UnexpectedErrorInfoProto contains more details. + UNEXPECTED_JS_ERROR = 16; } // The pseudo type values come from @@ -450,9 +504,17 @@ // elements (i.e. resolve to more than one element on the page). repeated string selectors = 2; + // If non-empty, only take into accounts the elements matched by selector + // whose inner text matches the given JavaScript regex. This does a search, + // not a full match. Add ^ and $ as necessary. + // + // This is used to filter the elements matching the last selector, before + // trying to get the pseudo_type, if any was set. + optional string inner_text_pattern = 4; + // An optional pseudo type. This pseudo type is associated to the final - // element matched by |selector|, which means that we currently don't handle - // matching an element inside a pseudo element. + // element matched, which means that we currently don't handle matching an + // element inside a pseudo element. optional PseudoType pseudo_type = 3; }
diff --git a/components/autofill_assistant/browser/web_controller.cc b/components/autofill_assistant/browser/web_controller.cc index d8f76aff..acc4d4e 100644 --- a/components/autofill_assistant/browser/web_controller.cc +++ b/components/autofill_assistant/browser/web_controller.cc
@@ -157,12 +157,18 @@ // Javascript code to query a visible elements for a selector, either the first // (non-strict) or a single (strict) visible element.q -const char* const kQuerySelectorVisible = - R"(function (selector, strict) { +const char* const kQuerySelectorWithConditions = + R"(function (selector, strict, visible, inner_text_re) { var found = this.querySelectorAll(selector); var found_index = -1; + var re = inner_text_re ? RegExp(inner_text_re) : undefined; + var match = function(e) { + if (visible && e.getClientRects().length == 0) return false; + if (re && !re.test(e.innerText)) return false; + return true; + }; for (let i = 0; i < found.length; i++) { - if (found[i].getClientRects().length > 0) { + if (match(found[i])) { if (found_index != -1) return undefined; found_index = i; if (!strict) break; @@ -231,6 +237,38 @@ } return false; } + +// Builds a ClientStatus appropriate for an unexpected error. +// +// This should only be used in situations where getting an error cannot be +// anything but a bug in the client. +ClientStatus UnexpectedErrorStatus(const std::string& file, int line) { + ClientStatus status(OTHER_ACTION_STATUS); + auto* info = status.mutable_unexpected_error_info(); + info->set_source_file(file); + info->set_source_line_number(line); + return status; +} + +// Builds a ClientStatus appropriate for a JavaScript error. +ClientStatus JavaScriptErrorStatus(const std::string& file, + int line, + const runtime::ExceptionDetails* exception) { + ClientStatus status(UNEXPECTED_JS_ERROR); + auto* info = status.mutable_unexpected_error_info(); + info->set_source_file(file); + info->set_source_line_number(line); + if (exception) { + if (exception->HasException() && + exception->GetException()->HasClassName()) { + info->set_js_exception_classname( + exception->GetException()->GetClassName()); + } + info->set_js_exception_line_number(exception->GetLineNumber()); + info->set_js_exception_column_number(exception->GetColumnNumber()); + } + return status; +} } // namespace class WebController::Worker { @@ -507,7 +545,7 @@ element_result_->object_id = ""; if (!result || !result->GetResult() || !result->GetResult()->HasObjectId()) { DVLOG(1) << __func__ << " Failed to get document root element."; - SendResult(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + SendResult(UnexpectedErrorStatus(__FILE__, __LINE__)); return; } @@ -532,11 +570,24 @@ runtime::CallArgument::Builder() .SetValue(base::Value::ToUniquePtrValue(base::Value(strict_))) .Build()); - const char* function = (index == (selector_.selectors.size() - 1) && - selector_.pseudo_type == PseudoType::UNDEFINED && - check_type_ == kVisibilityCheck) - ? kQuerySelectorVisible - : kQuerySelector; + std::string function; + if (index == (selector_.selectors.size() - 1)) { + bool visible = check_type_ == kVisibilityCheck; + if (visible || !selector_.inner_text_pattern.empty()) { + function.assign(kQuerySelectorWithConditions); + argument.emplace_back( + runtime::CallArgument::Builder() + .SetValue(base::Value::ToUniquePtrValue(base::Value(visible))) + .Build()); + argument.emplace_back(runtime::CallArgument::Builder() + .SetValue(base::Value::ToUniquePtrValue( + base::Value(selector_.inner_text_pattern))) + .Build()); + } + } + if (function.empty()) { + function.assign(kQuerySelector); + } devtools_client_->GetRuntime()->CallFunctionOn( runtime::CallFunctionOnParams::Builder() .SetObjectId(object_id) @@ -550,6 +601,12 @@ void WebController::ElementFinder::OnQuerySelectorAll( size_t index, std::unique_ptr<runtime::CallFunctionOnResult> result) { + if (!result || result->HasExceptionDetails()) { + DVLOG(1) << __func__ << "Failed to query selector " << index << " of " + << selector_; + SendResult(ClientStatus(OTHER_ACTION_STATUS)); + return; + } if (!result || !result->GetResult() || !result->GetResult()->HasObjectId()) { SendResult(ClientStatus(ELEMENT_RESOLUTION_FAILED)); return; @@ -598,7 +655,7 @@ std::unique_ptr<dom::DescribeNodeResult> result) { if (!result || !result->GetNode()) { DVLOG(1) << __func__ << " Failed to describe the node for pseudo element."; - SendResult(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + SendResult(UnexpectedErrorStatus(__FILE__, __LINE__)); return; } @@ -628,7 +685,6 @@ if (result && result->GetObject() && result->GetObject()->HasObjectId()) { element_result_->object_id = result->GetObject()->GetObjectId(); } - SendResult(OkClientStatus()); } @@ -638,7 +694,7 @@ std::unique_ptr<dom::DescribeNodeResult> result) { if (!result || !result->GetNode()) { DVLOG(1) << __func__ << " Failed to describe the node."; - SendResult(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + SendResult(UnexpectedErrorStatus(__FILE__, __LINE__)); return; } @@ -669,7 +725,7 @@ frame_name, node->GetContentDocument()->GetDocumentURL()); if (!element_result_->container_frame_host) { DVLOG(1) << __func__ << " Failed to find corresponding owner frame."; - SendResult(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + SendResult(UnexpectedErrorStatus(__FILE__, __LINE__)); return; } } else if (node->HasFrameId()) { @@ -703,7 +759,7 @@ std::unique_ptr<dom::ResolveNodeResult> result) { if (!result || !result->GetObject() || !result->GetObject()->HasObjectId()) { DVLOG(1) << __func__ << " Failed to resolve object id from backend id."; - SendResult(ClientStatus(OTHER_ACTION_STATUS)); + SendResult(UnexpectedErrorStatus(__FILE__, __LINE__)); return; } @@ -849,7 +905,10 @@ std::unique_ptr<runtime::CallFunctionOnResult> result) { if (!result || result->HasExceptionDetails()) { DVLOG(1) << __func__ << " Failed to scroll the element."; - std::move(callback).Run(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + std::move(callback).Run(JavaScriptErrorStatus( + __FILE__, __LINE__, + result->HasExceptionDetails() ? result->GetExceptionDetails() + : nullptr)); return; } @@ -916,7 +975,7 @@ if (!result) { DVLOG(1) << __func__ << " Failed to dispatch mouse left button pressed event."; - std::move(callback).Run(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__)); return; } @@ -943,7 +1002,7 @@ std::unique_ptr<input::DispatchTouchEventResult> result) { if (!result) { DVLOG(1) << __func__ << " Failed to dispatch touch start event."; - std::move(callback).Run(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__)); return; } @@ -1052,7 +1111,10 @@ std::unique_ptr<runtime::CallFunctionOnResult> result) { if (!result || result->HasExceptionDetails()) { DVLOG(1) << __func__ << " Failed to focus on element."; - std::move(callback).Run(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + std::move(callback).Run(JavaScriptErrorStatus( + __FILE__, __LINE__, + result->HasExceptionDetails() ? result->GetExceptionDetails() + : nullptr)); return; } std::move(callback).Run(OkClientStatus()); @@ -1108,7 +1170,8 @@ const autofill::FormFieldData& form_field) { if (form_data.fields.empty()) { DVLOG(1) << __func__ << " Failed to get form data to fill form."; - std::move(callback).Run(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + std::move(callback).Run( + UnexpectedErrorStatus(__FILE__, __LINE__)); // unexpected return; } @@ -1116,7 +1179,8 @@ ContentAutofillDriver::GetForRenderFrameHost(container_frame_host); if (!driver) { DVLOG(1) << __func__ << " Failed to get the autofill driver."; - std::move(callback).Run(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + std::move(callback).Run( + UnexpectedErrorStatus(__FILE__, __LINE__)); // unexpected return; } @@ -1192,12 +1256,15 @@ base::OnceCallback<void(const ClientStatus&)> callback, std::unique_ptr<runtime::CallFunctionOnResult> result) { if (!result || result->HasExceptionDetails() || - !result->GetResult()->GetValue()->GetBool()) { + !result->GetResult()->GetValue()->is_bool()) { DVLOG(1) << __func__ << " Failed to select option."; - std::move(callback).Run(ClientStatus(OTHER_ACTION_STATUS)); // unexpected return; } - DCHECK(result->GetResult()->GetValue()->is_bool()); + if (!result->GetResult()->GetValue()->GetBool()) { + DVLOG(1) << __func__ << " Failed to find option."; + std::move(callback).Run(ClientStatus(OPTION_VALUE_NOT_FOUND)); + return; + } std::move(callback).Run(OkClientStatus()); } @@ -1243,7 +1310,10 @@ if (!result || result->HasExceptionDetails() || !result->GetResult()->GetValue()->GetBool()) { DVLOG(1) << __func__ << " Failed to highlight element."; - std::move(callback).Run(ClientStatus(OTHER_ACTION_STATUS)); // unexpected + std::move(callback).Run(JavaScriptErrorStatus( + __FILE__, __LINE__, + result->HasExceptionDetails() ? result->GetExceptionDetails() + : nullptr)); // unexpected return; } DCHECK(result->GetResult()->GetValue()->is_bool()); @@ -1445,9 +1515,13 @@ void WebController::OnSetValueAttribute( base::OnceCallback<void(const ClientStatus&)> callback, std::unique_ptr<runtime::CallFunctionOnResult> result) { - std::move(callback).Run(result && !result->HasExceptionDetails() - ? OkClientStatus() - : ClientStatus(OTHER_ACTION_STATUS)); + std::move(callback).Run( + result && !result->HasExceptionDetails() + ? OkClientStatus() + : ClientStatus(JavaScriptErrorStatus( + __FILE__, __LINE__, + result->HasExceptionDetails() ? result->GetExceptionDetails() + : nullptr))); } void WebController::SetAttribute( @@ -1505,9 +1579,13 @@ void WebController::OnSetAttribute( base::OnceCallback<void(const ClientStatus&)> callback, std::unique_ptr<runtime::CallFunctionOnResult> result) { - std::move(callback).Run(result && !result->HasExceptionDetails() - ? OkClientStatus() - : ClientStatus(OTHER_ACTION_STATUS)); + std::move(callback).Run( + result && !result->HasExceptionDetails() + ? OkClientStatus() + : JavaScriptErrorStatus(__FILE__, __LINE__, + result->HasExceptionDetails() + ? result->GetExceptionDetails() + : nullptr)); } void WebController::SendKeyboardInput( @@ -1651,7 +1729,7 @@ if (!result || result->HasExceptionDetails() || !result->GetResult() || !result->GetResult()->GetValue()->is_string()) { DVLOG(2) << __func__ << " Failed to get HTML content for GetOuterHtml"; - std::move(callback).Run(ClientStatus(OTHER_ACTION_STATUS), ""); + std::move(callback).Run(UnexpectedErrorStatus(__FILE__, __LINE__), ""); return; }
diff --git a/components/autofill_assistant/browser/web_controller_browsertest.cc b/components/autofill_assistant/browser/web_controller_browsertest.cc index 4fe3ff8..26cd2e6 100644 --- a/components/autofill_assistant/browser/web_controller_browsertest.cc +++ b/components/autofill_assistant/browser/web_controller_browsertest.cc
@@ -509,6 +509,45 @@ false); } +IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, InnerTextCondition) { + Selector selector({"#with_inner_text span"}); + RunLaxElementCheck(kVisibilityCheck, selector, true); + RunStrictElementCheck(kVisibilityCheck, selector, false); + + // No matches + selector.inner_text_pattern = "no match"; + RunLaxElementCheck(kExistenceCheck, selector, false); + RunLaxElementCheck(kVisibilityCheck, selector, false); + + // Matches exactly one visible element. + selector.inner_text_pattern = "hello, world"; + RunLaxElementCheck(kExistenceCheck, selector, true); + RunStrictElementCheck(kExistenceCheck, selector, true); + RunLaxElementCheck(kVisibilityCheck, selector, true); + RunStrictElementCheck(kVisibilityCheck, selector, true); + + // Matches two visible elements + selector.inner_text_pattern = "^hello"; + RunLaxElementCheck(kExistenceCheck, selector, true); + RunStrictElementCheck(kExistenceCheck, selector, false); + RunLaxElementCheck(kVisibilityCheck, selector, true); + RunStrictElementCheck(kVisibilityCheck, selector, false); + + // Matches one visible, one invisible element + selector.inner_text_pattern = "world$"; + RunLaxElementCheck(kExistenceCheck, selector, true); + RunStrictElementCheck(kExistenceCheck, selector, false); + RunLaxElementCheck(kVisibilityCheck, selector, true); + RunStrictElementCheck(kVisibilityCheck, selector, true); + + // Inner text conditions are applied before looking for the pseudo-type. + selector.pseudo_type = PseudoType::BEFORE; + selector.inner_text_pattern = "world"; + RunLaxElementCheck(kExistenceCheck, selector, true); + selector.inner_text_pattern = "before"; // matches :before content + RunLaxElementCheck(kExistenceCheck, selector, false); +} + IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, ConcurrentElementsVisibilityCheck) { std::vector<Selector> selectors; @@ -735,7 +774,7 @@ IN_PROC_BROWSER_TEST_F(WebControllerBrowserTest, SelectOption) { Selector selector; selector.selectors.emplace_back("#select"); - EXPECT_EQ(OTHER_ACTION_STATUS, + EXPECT_EQ(OPTION_VALUE_NOT_FOUND, SelectOption(selector, "incorrect_label").proto_status()); EXPECT_EQ(ACTION_APPLIED, SelectOption(selector, "two").proto_status());
diff --git a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc index e270678..67db6a6 100644 --- a/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc +++ b/components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.cc
@@ -5,7 +5,6 @@ #include "components/data_reduction_proxy/content/common/data_reduction_proxy_url_loader_throttle.h" #include "base/bind.h" -#include "base/metrics/histogram_macros.h" #include "components/data_reduction_proxy/content/common/header_util.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers.h" @@ -21,17 +20,6 @@ namespace data_reduction_proxy { -namespace { -void RecordQuicProxyStatus(const net::ProxyServer& proxy_server) { - if (proxy_server.is_https()) { - RecordQuicProxyStatus(IsQuicProxy(proxy_server) - ? QUIC_PROXY_STATUS_AVAILABLE - : QUIC_PROXY_NOT_SUPPORTED); - } -} - -} // namespace - DataReductionProxyURLLoaderThrottle::DataReductionProxyURLLoaderThrottle( const net::HttpRequestHeaders& post_cache_headers, DataReductionProxyThrottleManager* manager) @@ -90,7 +78,6 @@ before_will_process_response_received_ = true; MaybeRetry(proxy_server, response_head.headers.get(), net::OK, defer); - RecordQuicProxyStatus(proxy_server); } void DataReductionProxyURLLoaderThrottle::MaybeRetry(
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc index 99a7bd7..367c0b73 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.cc
@@ -15,7 +15,6 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_io_data.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_request_options.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_util.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_switches.h" #include "net/base/host_port_pair.h" @@ -27,6 +26,12 @@ namespace data_reduction_proxy { +namespace { + +static const char kDataReductionCoreProxy[] = "proxy.googlezip.net"; + +} // namespace + DataReductionProxyDelegate::DataReductionProxyDelegate( DataReductionProxyConfig* config, const DataReductionProxyConfigurator* configurator, @@ -199,7 +204,18 @@ bool DataReductionProxyDelegate::SupportsQUIC( const net::ProxyServer& proxy_server) const { DCHECK(thread_checker_.CalledOnValidThread()); - return IsQuicProxy(proxy_server); + // Enable QUIC for whitelisted proxies. + return params::IsQuicEnabledForNonCoreProxies() || + proxy_server == + net::ProxyServer(net::ProxyServer::SCHEME_HTTPS, + net::HostPortPair(kDataReductionCoreProxy, 443)); +} + +void DataReductionProxyDelegate::RecordQuicProxyStatus( + QuicProxyStatus status) const { + DCHECK(thread_checker_.CalledOnValidThread()); + UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.Quic.ProxyStatus", status, + QUIC_PROXY_STATUS_BOUNDARY); } } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h index 8f5e0c4..14ba5fa 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate.h
@@ -56,7 +56,20 @@ // Returns true if |proxy_server| supports QUIC. virtual bool SupportsQUIC(const net::ProxyServer& proxy_server) const; + // Availability status of data reduction QUIC proxy. + // Protected so that the enum values are accessible for testing. + enum QuicProxyStatus { + QUIC_PROXY_STATUS_AVAILABLE, + QUIC_PROXY_NOT_SUPPORTED, + QUIC_PROXY_STATUS_MARKED_AS_BROKEN, + QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL, + QUIC_PROXY_STATUS_BOUNDARY + }; + private: + // Records the availability status of data reduction proxy. + void RecordQuicProxyStatus(QuicProxyStatus status) const; + // Checks if the first proxy server in |result| supports QUIC and if so // adds an alternative proxy configuration to |result|. void GetAlternativeProxy(const GURL& url,
diff --git a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc index c38b9c9..fc1049e 100644 --- a/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc +++ b/components/data_reduction_proxy/core/browser/data_reduction_proxy_delegate_unittest.cc
@@ -33,7 +33,6 @@ #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_service.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_settings.h" #include "components/data_reduction_proxy/core/browser/data_reduction_proxy_test_utils.h" -#include "components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_headers_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_params_test_utils.h" #include "components/data_reduction_proxy/core/common/data_reduction_proxy_pref_names.h" @@ -105,19 +104,27 @@ if (expect_alternative_proxy_server && !broken) { histogram_tester.ExpectUniqueSample( "DataReductionProxy.Quic.ProxyStatus", - QuicProxyStatus::QUIC_PROXY_STATUS_AVAILABLE, 1); + TestDataReductionProxyDelegate::QuicProxyStatus:: + QUIC_PROXY_STATUS_AVAILABLE, + 1); } else if (!supports_quic && !broken) { histogram_tester.ExpectUniqueSample( "DataReductionProxy.Quic.ProxyStatus", - QuicProxyStatus::QUIC_PROXY_NOT_SUPPORTED, 1); + TestDataReductionProxyDelegate::QuicProxyStatus:: + QUIC_PROXY_NOT_SUPPORTED, + 1); } else { ASSERT_TRUE(broken); histogram_tester.ExpectUniqueSample( "DataReductionProxy.Quic.ProxyStatus", - QuicProxyStatus::QUIC_PROXY_STATUS_MARKED_AS_BROKEN, 1); + TestDataReductionProxyDelegate::QuicProxyStatus:: + QUIC_PROXY_STATUS_MARKED_AS_BROKEN, + 1); } } + using DataReductionProxyDelegate::QuicProxyStatus; + private: const bool proxy_supports_quic_;
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.cc b/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.cc index 4bdb409..6ffe2d4 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.cc +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.cc
@@ -27,8 +27,6 @@ namespace { -static const char kDataReductionCoreProxy[] = "proxy.googlezip.net"; - // Returns the Data Reduction Proxy servers in |proxy_type_info| that should be // marked bad according to |data_reduction_proxy_info|. std::vector<net::ProxyServer> GetProxiesToMarkBad( @@ -295,17 +293,4 @@ return true; } -bool IsQuicProxy(const net::ProxyServer& proxy_server) { - // Enable QUIC for whitelisted proxies. - return params::IsQuicEnabledForNonCoreProxies() || - proxy_server == - net::ProxyServer(net::ProxyServer::SCHEME_HTTPS, - net::HostPortPair(kDataReductionCoreProxy, 443)); -} - -void RecordQuicProxyStatus(QuicProxyStatus status) { - UMA_HISTOGRAM_ENUMERATION("DataReductionProxy.Quic.ProxyStatus", status, - QUIC_PROXY_STATUS_BOUNDARY); -} - } // namespace data_reduction_proxy
diff --git a/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h b/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h index b3ba446..d87153bb 100644 --- a/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h +++ b/components/data_reduction_proxy/core/common/data_reduction_proxy_bypass_protocol.h
@@ -15,15 +15,6 @@ struct DataReductionProxyTypeInfo; -// Availability status of data reduction QUIC proxy. -enum QuicProxyStatus { - QUIC_PROXY_STATUS_AVAILABLE, - QUIC_PROXY_NOT_SUPPORTED, - QUIC_PROXY_STATUS_MARKED_AS_BROKEN, - QUIC_PROXY_DISABLED_VIA_FIELD_TRIAL, - QUIC_PROXY_STATUS_BOUNDARY -}; - // Records a data reduction proxy bypass event as a "BlockType" if // |bypass_all| is true and as a "BypassType" otherwise. Records the event as // "Primary" if |is_primary| is true and "Fallback" otherwise. @@ -119,11 +110,6 @@ base::TimeTicks t, base::TimeDelta* retry_delay); -// Returns true if the proxy supports QUIC. -bool IsQuicProxy(const net::ProxyServer& proxy_server); - -void RecordQuicProxyStatus(QuicProxyStatus status); - } // namespace data_reduction_proxy #endif // COMPONENTS_DATA_REDUCTION_PROXY_CORE_COMMON_DATA_REDUCTION_PROXY_BYPASS_PROTOCOL_H_
diff --git a/components/keyed_service/core/simple_keyed_service_factory.h b/components/keyed_service/core/simple_keyed_service_factory.h index 18584bb..25ce3654 100644 --- a/components/keyed_service/core/simple_keyed_service_factory.h +++ b/components/keyed_service/core/simple_keyed_service_factory.h
@@ -24,6 +24,40 @@ // We do this because services depend on each other and we need to control // shutdown/destruction order. In each derived classes' constructors, the // implementors must explicitly state on which services they depend. +// +// Note: +// The SimpleKeyedServiceFactory (SKSF) provides a way to create or get a +// SimpleKeyedService before BrowserContext is created. +// BrowserContextKeyedServiceFactories (BCKSFs) can only be converted to +// SKSFs as long as they access only part of Profile properties: +// path, PrefService, and is_off_the_record flag. +// +// An SKSF shouldn't declare DependsOn() of any BCKSF on creation (constructor). +// It is because an SKSF can't depend on any BCKSF when it is created. However, +// dependencies from SKSFs to BCKSFs may exist after full browser launches, +// since some SimpleKeyedServices move from "reduced mode" to "full browser +// mode" when the full browser starts up, which involves injection of +// BrowserContextKeyedService dependencies into the SimpleKeyedService. +// +// If such dependencies exist in a SimpleKeyedService, the service **MUST** +// explicitly reset/clean up the dependencies in KeyedService::Shutdown(). +// +// Once the dependencies are reset, the dependencies from the BCKSF dependency +// graph to the SKSF dependency graph are removed. Therefore, we adopt a +// two-phase shutdown: +// - Shutdown of all BCKSFactories +// - Shutdown of all SKSFactories +// - Destruction of all BCKSFactories +// - Destruction of all SKSFactories + +// A SimpleKeyedService should *AVOID* full browser inflation whenever it is +// possible. A solution might be splitting the part of the service that +// depends on BrowserContextKeyedService or BrowserContext into a separate +// BrowserContextKeyedService. +// +// See +// https://docs.google.com/document/d/1caWonaPnBhMb6sk4syNe0BbdsQih13S6QmDW237Mcrg/edit?usp=sharing +// for more details. class KEYED_SERVICE_EXPORT SimpleKeyedServiceFactory : public KeyedServiceFactory { public:
diff --git a/components/password_manager/core/browser/new_password_form_manager_unittest.cc b/components/password_manager/core/browser/new_password_form_manager_unittest.cc index 953358f1..556fa88 100644 --- a/components/password_manager/core/browser/new_password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/new_password_form_manager_unittest.cc
@@ -420,7 +420,6 @@ TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); CreateFormManager(observed_form_); - EXPECT_CALL(driver_, AllowPasswordGenerationForForm(_)); EXPECT_CALL(driver_, FormEligibleForGenerationFound(_)).Times(0); PasswordFormFillData fill_data; EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data)); @@ -1269,7 +1268,6 @@ TEST_F(NewPasswordFormManagerTest, RecordReadonlyWhenFilling) { TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); ukm::TestAutoSetUkmRecorder test_ukm_recorder; - EXPECT_CALL(driver_, AllowPasswordGenerationForForm(_)); EXPECT_CALL(driver_, FillPasswordForm(_)); SetNonFederatedAndNotifyFetchCompleted({&saved_match_});
diff --git a/components/password_manager/core/browser/password_form_filling_unittest.cc b/components/password_manager/core/browser/password_form_filling_unittest.cc index 043740a..c0c2eab6 100644 --- a/components/password_manager/core/browser/password_form_filling_unittest.cc +++ b/components/password_manager/core/browser/password_form_filling_unittest.cc
@@ -97,7 +97,6 @@ TEST_F(PasswordFormFillingTest, NoSavedCredentials) { std::map<base::string16, const autofill::PasswordForm*> best_matches; - EXPECT_CALL(driver_, AllowPasswordGenerationForForm(observed_form_)); EXPECT_CALL(driver_, InformNoSavedCredentials()); EXPECT_CALL(driver_, FillPasswordForm(_)).Times(0); EXPECT_CALL(driver_, ShowInitialPasswordAccountSuggestions(_)).Times(0); @@ -117,8 +116,6 @@ another_saved_match.password_value += ASCIIToUTF16("1"); best_matches[another_saved_match.username_value] = &another_saved_match; - EXPECT_CALL(driver_, AllowPasswordGenerationForForm(observed_form_)) - .Times(is_blacklisted ? 0 : 1); EXPECT_CALL(driver_, InformNoSavedCredentials()).Times(0); PasswordFormFillData fill_data; EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data)); @@ -212,7 +209,6 @@ std::map<base::string16, const autofill::PasswordForm*> best_matches; best_matches[saved_match_.username_value] = &psl_saved_match_; - EXPECT_CALL(driver_, AllowPasswordGenerationForForm(observed_form_)); EXPECT_CALL(driver_, InformNoSavedCredentials()).Times(0); PasswordFormFillData fill_data; EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&fill_data));
diff --git a/components/password_manager/core/browser/password_form_manager_unittest.cc b/components/password_manager/core/browser/password_form_manager_unittest.cc index 9f3d248a..973448f 100644 --- a/components/password_manager/core/browser/password_form_manager_unittest.cc +++ b/components/password_manager/core/browser/password_form_manager_unittest.cc
@@ -398,6 +398,11 @@ psl_saved_match_.action = GURL("http://m.accounts.google.com/a/Login"); psl_saved_match_.signon_realm = "http://m.accounts.google.com"; + scoped_feature_list_.InitWithFeatures( + /* enabled_features */ {}, + /* disabled_features*/ {features::kNewPasswordFormParsing, + features::kNewPasswordFormParsingForSaving, + features::kOnlyNewParser}); password_manager_.reset(new PasswordManager(&client_)); form_manager_.reset(new PasswordFormManager( password_manager_.get(), &client_, client_.driver(), observed_form_, @@ -1018,6 +1023,7 @@ // needs to outlive the latter. FakeFormFetcher fake_form_fetcher_; std::unique_ptr<PasswordFormManager> form_manager_; + base::test::ScopedFeatureList scoped_feature_list_; }; class PasswordFormManagerFillOnAccountSelectTest
diff --git a/components/password_manager/core/browser/password_generation_frame_helper_unittest.cc b/components/password_manager/core/browser/password_generation_frame_helper_unittest.cc index 98df547..8d6f550 100644 --- a/components/password_manager/core/browser/password_generation_frame_helper_unittest.cc +++ b/components/password_manager/core/browser/password_generation_frame_helper_unittest.cc
@@ -11,6 +11,7 @@ #include "base/metrics/field_trial.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" #include "components/autofill/core/browser/autofill_field.h" #include "components/autofill/core/browser/autofill_metrics.h" @@ -27,6 +28,7 @@ #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/browser/stub_password_manager_driver.h" #include "components/password_manager/core/browser/test_password_store.h" +#include "components/password_manager/core/common/password_manager_features.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -344,6 +346,13 @@ EXPECT_CALL(*client_, GetPasswordSyncState()) .WillRepeatedly(testing::Return(SYNCING_NORMAL_ENCRYPTION)); + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitWithFeatures( + /* enabled_features */ {}, + /* disabled_features*/ {features::kNewPasswordFormParsing, + features::kNewPasswordFormParsingForSaving, + features::kOnlyNewParser}); + autofill::FormData login_form; login_form.origin = GURL("http://www.yahoo.com/login/"); autofill::FormFieldData username;
diff --git a/components/password_manager/core/browser/password_manager_unittest.cc b/components/password_manager/core/browser/password_manager_unittest.cc index 27304f9..7006db1 100644 --- a/components/password_manager/core/browser/password_manager_unittest.cc +++ b/components/password_manager/core/browser/password_manager_unittest.cc
@@ -265,6 +265,12 @@ .WillByDefault(WithArg<0>(DeletePtr())); ON_CALL(client_, ShowManualFallbackForSavingPtr(_, _, _)) .WillByDefault(WithArg<0>(DeletePtr())); + + // When waiting for predictions is on, it makes tests more complicated. + // Disable waiting, since most tests have nothing to do with predictions. + // All tests that test working with prediction should explicitly turn + // predictions on. + NewPasswordFormManager::set_wait_for_server_predictions_for_filling(false); } void TearDown() override { @@ -692,8 +698,10 @@ PasswordForm form(MakeSimpleForm()); std::vector<PasswordForm> observed = {form}; EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(PasswordStore::FormDigest(form), _)) - .WillOnce(WithArg<1>(InvokeConsumer(existing_different))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(existing_different))); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) @@ -833,8 +841,10 @@ std::vector<PasswordForm> observed = {form}; EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) .WillRepeatedly(Return(true)); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(form))); EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1161,8 +1171,11 @@ std::vector<PasswordForm> observed; observed.push_back(form); EXPECT_CALL(driver_, FillPasswordForm(_)); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the + // old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(form))); manager()->OnPasswordFormsParsed(&driver_, observed); observed.clear(); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1177,8 +1190,10 @@ std::vector<PasswordForm> observed; observed.push_back(form); EXPECT_CALL(driver_, FillPasswordForm(_)); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(form))); manager()->OnPasswordFormsParsed(&driver_, observed); } @@ -1526,8 +1541,10 @@ form.new_password_element = ASCIIToUTF16("new_password_element"); form.new_password_value.clear(); observed.push_back(form); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms())); + .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1560,8 +1577,10 @@ // Loads passsword form without username input field. PasswordForm form(MakeSimpleFormWithOnlyPasswordField()); observed.push_back(form); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms())); + .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1600,11 +1619,9 @@ TEST_F(PasswordManagerTest, FillPasswordOnManyFrames_SameId) { // Setting task runner is required since NewPasswordFormManager uses // PostDelayTask for making filling. + NewPasswordFormManager::set_wait_for_server_predictions_for_filling(true); TestMockTimeTaskRunner::ScopedContext scoped_context_(task_runner_.get()); - base::test::ScopedFeatureList scoped_feature_list; - scoped_feature_list.InitAndEnableFeature(features::kNewPasswordFormParsing); - // Two unrelated forms... FormData form_data; form_data.origin = GURL("http://www.google.com/a/LoginAuth"); @@ -1665,7 +1682,10 @@ // similar, then it is important to ensure that the single governing // PasswordFormManager knows about both PasswordManagerDriver instances and // instructs them to fill. +// TODO(https://crbug.com/949519): Remove this test when the old parser is gone. TEST_F(PasswordManagerTest, FillPasswordOnManyFrames_SameForm) { + base::test::ScopedFeatureList scoped_feature_list; + TurnOnNewParsingForFilling(&scoped_feature_list, false); PasswordForm same_form = MakeSimpleForm(); // Observe the form in the first frame. @@ -1690,7 +1710,7 @@ PasswordForm form(MakeSimpleForm()); observed.push_back(form); EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms())); + .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1708,7 +1728,10 @@ EXPECT_CALL(*store_, AddLogin(FormMatches(form))); // The Save() call triggers updating for |pending_login_managers_|, hence the // further GetLogins call. - EXPECT_CALL(*store_, GetLogins(_, _)); + // There are 2 calls to |store_| because both PasswordFormManager and + // NewPasswordFormManager call it. TODO(https://crbug.com/949519): remove + // Times(2) when the old parser is gone. + EXPECT_CALL(*store_, GetLogins(_, _)).Times(2); form_manager_to_save->Save(); } @@ -1722,8 +1745,10 @@ PasswordForm blacklisted_form(form); blacklisted_form.username_value = ASCIIToUTF16(""); blacklisted_form.blacklisted_by_user = true; + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(blacklisted_form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(blacklisted_form))); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1892,8 +1917,10 @@ PasswordForm form(MakeSimpleForm()); observed.push_back(form); EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(form))); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -1927,7 +1954,10 @@ // GetLogins calls remain unanswered to emulate that PasswordStore did not // fetch a form in time before submission. - EXPECT_CALL(*store_, GetLogins(_, _)); + // There are 2 calls to |store_| because both PasswordFormManager and + // NewPasswordFormManager call it. TODO(https://crbug.com/949519): remove + // Times(2) when the old parser is gone. + EXPECT_CALL(*store_, GetLogins(_, _)).Times(2); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); ASSERT_EQ(1u, manager()->pending_login_managers().size()); @@ -2365,8 +2395,10 @@ autofill::PasswordFormFillData form_data; EXPECT_CALL(driver_, FillPasswordForm(_)).WillOnce(SaveArg<0>(&form_data)); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(android_form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(android_form))); manager()->OnPasswordFormsParsed(&driver_, observed_forms); observed_forms.clear(); manager()->OnPasswordFormsRendered(&driver_, observed_forms, true); @@ -2410,8 +2442,10 @@ std::vector<PasswordForm> observed_forms = {observed_form}; EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(android_form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(android_form))); manager()->OnPasswordFormsParsed(&driver_, observed_forms); manager()->OnPasswordFormsRendered(&driver_, observed_forms, true); @@ -2453,7 +2487,9 @@ std::vector<PasswordForm> observed = {form}; // Emulate page load. - EXPECT_CALL(*store_, GetLogins(PasswordStore::FormDigest(form), _)); + // TODO(https://crbug.com/949519): remove Times(2) when the old parser is + // gone. + EXPECT_CALL(*store_, GetLogins(PasswordStore::FormDigest(form), _)).Times(2); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); ASSERT_EQ(1u, manager()->pending_login_managers().size()); @@ -2549,8 +2585,10 @@ stored_form.password_value = ASCIIToUTF16("old_password"); EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) .WillRepeatedly(Return(true)); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(stored_form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(stored_form))); EXPECT_CALL(driver_, FillPasswordForm(_)).Times(2); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -2599,7 +2637,10 @@ PasswordStoreConsumer* store_consumer = nullptr; EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) .WillRepeatedly(Return(true)); - EXPECT_CALL(*store_, GetLogins(_, _)).WillOnce(SaveArg<1>(&store_consumer)); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. + EXPECT_CALL(*store_, GetLogins(_, _)) + .WillRepeatedly(SaveArg<1>(&store_consumer)); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -2623,8 +2664,10 @@ observed.push_back(form); EXPECT_CALL(client_, IsSavingAndFillingEnabled(form.origin)) .WillRepeatedly(Return(true)); + // TODO(https://crbug.com/949519): replace WillRepeatedly with WillOnce when + // the old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeEmptyConsumerWithForms())); + .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); manager()->OnPasswordFormsParsed(&driver_, observed); manager()->OnPasswordFormsRendered(&driver_, observed, true); @@ -2852,8 +2895,11 @@ }; const std::vector<PasswordForm> observed = {PasswordForm()}; - // PasswordStore requested only once for the same form. - EXPECT_CALL(*store_, GetLogins(_, _)); + // PasswordStore requested only once for the same form by both + // PasswordFormManager and NewPasswordFormManager. + // TODO(https://crbug.com/949519): remove Times(2) when the old parser is + // gone. + EXPECT_CALL(*store_, GetLogins(_, _)).Times(2); for (const auto& test_case : kCases) { SCOPED_TRACE(testing::Message("index of test_case = ") @@ -3216,6 +3262,7 @@ // Check that when autofill predictions are received before a form is found then // server predictions are not ignored and used for filling. TEST_F(PasswordManagerTest, AutofillPredictionBeforeFormParsed) { + NewPasswordFormManager::set_wait_for_server_predictions_for_filling(true); TestMockTimeTaskRunner::ScopedContext scoped_context(task_runner_.get()); base::test::ScopedFeatureList scoped_feature_list; scoped_feature_list.InitAndEnableFeature(features::kNewPasswordFormParsing);
diff --git a/components/password_manager/core/common/password_manager_features.cc b/components/password_manager/core/common/password_manager_features.cc index 99538db..70386e5 100644 --- a/components/password_manager/core/common/password_manager_features.cc +++ b/components/password_manager/core/common/password_manager_features.cc
@@ -62,7 +62,7 @@ // Enables new password form parsing mechanism for filling passwords, details in // https://goo.gl/QodPH1 const base::Feature kNewPasswordFormParsing = { - "new-password-form-parsing", base::FEATURE_DISABLED_BY_DEFAULT}; + "new-password-form-parsing", base::FEATURE_ENABLED_BY_DEFAULT}; // Enables new password form parsing mechanism for saving passwords, details in // https://goo.gl/QodPH1
diff --git a/components/plugins/renderer/webview_plugin.cc b/components/plugins/renderer/webview_plugin.cc index 58f56a3..5a83474 100644 --- a/components/plugins/renderer/webview_plugin.cc +++ b/components/plugins/renderer/webview_plugin.cc
@@ -370,8 +370,10 @@ v8::Context::Scope context_scope(context); v8::Local<v8::Object> global = context->Global(); - global->Set(gin::StringToV8(isolate, "plugin"), - plugin_->delegate_->GetV8Handle(isolate)); + global + ->Set(context, gin::StringToV8(isolate, "plugin"), + plugin_->delegate_->GetV8Handle(isolate)) + .Check(); } void WebViewPlugin::WebViewHelper::FrameDetached(DetachType type) {
diff --git a/components/policy/core/common/cloud/cloud_policy_client.cc b/components/policy/core/common/cloud/cloud_policy_client.cc index 63cb402a..c6dc10b 100644 --- a/components/policy/core/common/cloud/cloud_policy_client.cc +++ b/components/policy/core/common/cloud/cloud_policy_client.cc
@@ -672,7 +672,9 @@ std::unique_ptr<DMAuth> auth, const CloudPolicyClient::StatusCallback& callback) { CHECK(is_registered()); - DCHECK(auth->has_oauth_token() || auth->has_enrollment_token()); + // This condition is wrong in case of Attestation enrollment + // (https://crbug.com/942013). + // DCHECK(auth->has_oauth_token() || auth->has_enrollment_token()); std::unique_ptr<DeviceManagementRequestJob> request_job(service_->CreateJob( DeviceManagementRequestJob::TYPE_ATTRIBUTE_UPDATE_PERMISSION,
diff --git a/components/signin/core/browser/about_signin_internals.cc b/components/signin/core/browser/about_signin_internals.cc index 6210b15..b3cffb2 100644 --- a/components/signin/core/browser/about_signin_internals.cc +++ b/components/signin/core/browser/about_signin_internals.cc
@@ -414,11 +414,6 @@ NotifyObservers(); } -void AboutSigninInternals::OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) { - NotifyObservers(); -} - void AboutSigninInternals::OnPrimaryAccountSet( const CoreAccountInfo& primary_account_info) { NotifyObservers();
diff --git a/components/signin/core/browser/about_signin_internals.h b/components/signin/core/browser/about_signin_internals.h index 89a1b42a..370e47f 100644 --- a/components/signin/core/browser/about_signin_internals.h +++ b/components/signin/core/browser/about_signin_internals.h
@@ -203,8 +203,6 @@ // IdentityManager::Observer implementations. void OnRefreshTokensLoaded() override; void OnEndBatchOfRefreshTokenStateChanges() override; - void OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) override; void OnPrimaryAccountSet( const CoreAccountInfo& primary_account_info) override; void OnPrimaryAccountCleared(
diff --git a/components/signin/core/browser/account_reconcilor_unittest.cc b/components/signin/core/browser/account_reconcilor_unittest.cc index abced09d..e8c81d90 100644 --- a/components/signin/core/browser/account_reconcilor_unittest.cc +++ b/components/signin/core/browser/account_reconcilor_unittest.cc
@@ -2204,9 +2204,9 @@ } base::HistogramTester::CountsMap expected_counts; - expected_counts["Signin.Reconciler.Duration.Success"] = 1; + expected_counts["Signin.Reconciler.Duration.UpTo3mins.Success"] = 1; EXPECT_THAT(histogram_tester()->GetTotalCountsForPrefix( - "Signin.Reconciler.Duration.Success"), + "Signin.Reconciler.Duration.UpTo3mins.Success"), testing::ContainerEq(expected_counts)); } @@ -2307,10 +2307,10 @@ identity_test_env()->ClearPrimaryAccount(); base::HistogramTester::CountsMap expected_counts; - expected_counts["Signin.Reconciler.Duration.Failure"] = 1; + expected_counts["Signin.Reconciler.Duration.UpTo3mins.Failure"] = 1; if (!IsMultiloginEnabled()) { EXPECT_THAT(histogram_tester()->GetTotalCountsForPrefix( - "Signin.Reconciler.Duration.Failure"), + "Signin.Reconciler.Duration.UpTo3mins.Failure"), testing::ContainerEq(expected_counts)); } }
diff --git a/components/signin/core/browser/signin_manager.cc b/components/signin/core/browser/signin_manager.cc index fc683c3..0975933 100644 --- a/components/signin/core/browser/signin_manager.cc +++ b/components/signin/core/browser/signin_manager.cc
@@ -41,12 +41,6 @@ local_state_pref_registrar_.RemoveAll(); } -void SigninManager::HandleAuthError(const GoogleServiceAuthError& error) { - if (observer_ != nullptr) { - observer_->GoogleSigninFailed(error); - } -} - void SigninManager::SignOut( signin_metrics::ProfileSignout signout_source_metric, signin_metrics::SignoutDelete signout_delete_metric) {
diff --git a/components/signin/core/browser/signin_manager.h b/components/signin/core/browser/signin_manager.h index 1b5ebf6..d4a0b78 100644 --- a/components/signin/core/browser/signin_manager.h +++ b/components/signin/core/browser/signin_manager.h
@@ -40,7 +40,6 @@ #include "net/cookies/canonical_cookie.h" class GaiaCookieManagerService; -class GoogleServiceAuthError; class PrefService; namespace identity { @@ -142,11 +141,6 @@ // OAuth2TokenService::Observer: void OnRefreshTokensLoaded() override; - // Called to handle an error from a GAIA auth fetch. Sets the last error - // to |error|, sends out a notification of login failure and clears the - // transient signin data. - void HandleAuthError(const GoogleServiceAuthError& error); - // Starts the sign out process. void StartSignOut(signin_metrics::ProfileSignout signout_source_metric, signin_metrics::SignoutDelete signout_delete_metric,
diff --git a/components/signin/core/browser/signin_manager_base.h b/components/signin/core/browser/signin_manager_base.h index 5344bd1b..234d1de 100644 --- a/components/signin/core/browser/signin_manager_base.h +++ b/components/signin/core/browser/signin_manager_base.h
@@ -46,9 +46,6 @@ public: class Observer { public: - // Called when a user fails to sign into Google services such as sync. - virtual void GoogleSigninFailed(const GoogleServiceAuthError& error) {} - // Called when a user signs into Google services such as sync. // This method is not called during a reauth. virtual void GoogleSigninSucceeded(const AccountInfo& account_info) {}
diff --git a/components/signin/core/browser/signin_manager_unittest.cc b/components/signin/core/browser/signin_manager_unittest.cc index b5f7b96..f6f77f7 100644 --- a/components/signin/core/browser/signin_manager_unittest.cc +++ b/components/signin/core/browser/signin_manager_unittest.cc
@@ -38,21 +38,14 @@ class TestSigninManagerObserver : public SigninManagerBase::Observer { public: - TestSigninManagerObserver() - : num_failed_signins_(0), num_successful_signins_(0), num_signouts_(0) {} + TestSigninManagerObserver() : num_successful_signins_(0), num_signouts_(0) {} ~TestSigninManagerObserver() override {} - int num_failed_signins_; int num_successful_signins_; int num_signouts_; private: - // SigninManagerBase::Observer: - void GoogleSigninFailed(const GoogleServiceAuthError& error) override { - num_failed_signins_++; - } - void GoogleSigninSucceeded(const AccountInfo& account_info) override { num_successful_signins_++; } @@ -136,7 +129,6 @@ // Should go into token service and stop. EXPECT_EQ(1, test_observer_.num_successful_signins_); - EXPECT_EQ(0, test_observer_.num_failed_signins_); } base::test::ScopedTaskEnvironment task_environment_; @@ -318,7 +310,6 @@ std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com"); manager_->SignIn("user@gmail.com"); EXPECT_EQ(1, test_observer_.num_successful_signins_); - EXPECT_EQ(0, test_observer_.num_failed_signins_); EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email); EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId()); } @@ -332,13 +323,11 @@ std::string account_id = AddToAccountTracker("gaia_id", "user@gmail.com"); manager_->SignIn("user@gmail.com"); EXPECT_EQ(1, test_observer_.num_successful_signins_); - EXPECT_EQ(0, test_observer_.num_failed_signins_); EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email); EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId()); manager_->SignIn("user@gmail.com"); EXPECT_EQ(1, test_observer_.num_successful_signins_); - EXPECT_EQ(0, test_observer_.num_failed_signins_); EXPECT_EQ("user@gmail.com", manager_->GetAuthenticatedAccountInfo().email); EXPECT_EQ(account_id, manager_->GetAuthenticatedAccountId()); }
diff --git a/components/signin/core/browser/signin_metrics.cc b/components/signin/core/browser/signin_metrics.cc index d2cdbef..3827846 100644 --- a/components/signin/core/browser/signin_metrics.cc +++ b/components/signin/core/browser/signin_metrics.cc
@@ -697,9 +697,13 @@ void LogSigninAccountReconciliationDuration(base::TimeDelta duration, bool successful) { if (successful) { - UMA_HISTOGRAM_TIMES("Signin.Reconciler.Duration.Success", duration); + UMA_HISTOGRAM_CUSTOM_TIMES("Signin.Reconciler.Duration.UpTo3mins.Success", + duration, base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMinutes(3), 100); } else { - UMA_HISTOGRAM_TIMES("Signin.Reconciler.Duration.Failure", duration); + UMA_HISTOGRAM_CUSTOM_TIMES("Signin.Reconciler.Duration.UpTo3mins.Failure", + duration, base::TimeDelta::FromMilliseconds(1), + base::TimeDelta::FromMinutes(3), 100); } }
diff --git a/components/sync/BUILD.gn b/components/sync/BUILD.gn index 5fdf913c..000c7425 100644 --- a/components/sync/BUILD.gn +++ b/components/sync/BUILD.gn
@@ -472,6 +472,8 @@ "nigori/nigori_model_type_processor.cc", "nigori/nigori_model_type_processor.h", "nigori/nigori_sync_bridge.h", + "nigori/nigori_sync_bridge_impl.cc", + "nigori/nigori_sync_bridge_impl.h", "protocol/proto_enum_conversions.cc", "protocol/proto_enum_conversions.h", "protocol/proto_memory_estimations.cc",
diff --git a/components/sync/engine/sync_engine_switches.cc b/components/sync/engine/sync_engine_switches.cc index c0d6921..e05efd0 100644 --- a/components/sync/engine/sync_engine_switches.cc +++ b/components/sync/engine/sync_engine_switches.cc
@@ -23,7 +23,7 @@ // via scrypt when we receive a remote Nigori node that specifies it as the key // derivation method. const base::Feature kSyncUseScryptForNewCustomPassphrases{ - "SyncUseScryptForNewCustomPassphrases", base::FEATURE_DISABLED_BY_DEFAULT}; + "SyncUseScryptForNewCustomPassphrases", base::FEATURE_ENABLED_BY_DEFAULT}; // Enable USS implementation of Nigori datatype. const base::Feature kSyncUSSNigori{"SyncUSSNigori",
diff --git a/components/sync/engine_impl/sync_encryption_handler_impl_unittest.cc b/components/sync/engine_impl/sync_encryption_handler_impl_unittest.cc index a3bfcd66..baa6fdd 100644 --- a/components/sync/engine_impl/sync_encryption_handler_impl_unittest.cc +++ b/components/sync/engine_impl/sync_encryption_handler_impl_unittest.cc
@@ -1752,9 +1752,9 @@ VerifyPassphraseType(PassphraseType::CUSTOM_PASSPHRASE); EXPECT_TRUE(encryption_handler()->IsEncryptEverythingEnabled()); EXPECT_FALSE(encryption_handler()->custom_passphrase_time().is_null()); - VerifyMigratedNigoriWithTimestamp(migration_time, - PassphraseType::CUSTOM_PASSPHRASE, kNewKey, - {KeyDerivationParams::CreateForPbkdf2()}); + VerifyMigratedNigoriWithTimestamp( + migration_time, PassphraseType::CUSTOM_PASSPHRASE, kNewKey, + {KeyDerivationParams::CreateForScrypt(kScryptSalt)}); // Check that the cryptographer can decrypt the old key. sync_pb::EncryptedData old_encrypted; @@ -1770,8 +1770,9 @@ keystore_cryptographer.EncryptString("string", &keystore_encrypted); EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted)); - // Check the the cryptographer is encrypting with the new key. - KeyParams new_key = {KeyDerivationParams::CreateForPbkdf2(), kNewKey}; + // Check that the cryptographer is encrypting with the new key. + KeyParams new_key = {KeyDerivationParams::CreateForScrypt(kScryptSalt), + kNewKey}; Cryptographer new_cryptographer(GetCryptographer()->encryptor()); new_cryptographer.AddKey(new_key); sync_pb::EncryptedData new_encrypted; @@ -1783,7 +1784,7 @@ VerifyRestoreAfterExplicitPaspshrase( migration_time, kNewKey, captured_bootstrap_token, captured_nigori_state, PassphraseType::CUSTOM_PASSPHRASE, - {KeyDerivationParams::CreateForPbkdf2()}); + {KeyDerivationParams::CreateForScrypt(kScryptSalt)}); } // Test that if a client without a keystore key (e.g. one without keystore @@ -1864,9 +1865,9 @@ VerifyPassphraseType(PassphraseType::CUSTOM_PASSPHRASE); EXPECT_TRUE(encryption_handler()->IsEncryptEverythingEnabled()); EXPECT_FALSE(encryption_handler()->custom_passphrase_time().is_null()); - VerifyMigratedNigoriWithTimestamp(migration_time, - PassphraseType::CUSTOM_PASSPHRASE, kNewKey, - {KeyDerivationParams::CreateForPbkdf2()}); + VerifyMigratedNigoriWithTimestamp( + migration_time, PassphraseType::CUSTOM_PASSPHRASE, kNewKey, + {KeyDerivationParams::CreateForScrypt(kScryptSalt)}); // Check that the cryptographer can decrypt the old key. sync_pb::EncryptedData old_encrypted; @@ -1881,8 +1882,9 @@ keystore_cryptographer.EncryptString("string", &keystore_encrypted); EXPECT_TRUE(GetCryptographer()->CanDecrypt(keystore_encrypted)); - // Check the the cryptographer is encrypting with the new key. - KeyParams new_key = {KeyDerivationParams::CreateForPbkdf2(), kNewKey}; + // Check that the cryptographer is encrypting with the new key. + KeyParams new_key = {KeyDerivationParams::CreateForScrypt(kScryptSalt), + kNewKey}; Cryptographer new_cryptographer(GetCryptographer()->encryptor()); new_cryptographer.AddKey(new_key); sync_pb::EncryptedData new_encrypted; @@ -1894,7 +1896,7 @@ VerifyRestoreAfterExplicitPaspshrase( migration_time, kNewKey, captured_bootstrap_token, captured_nigori_state, PassphraseType::CUSTOM_PASSPHRASE, - {KeyDerivationParams::CreateForPbkdf2()}); + {KeyDerivationParams::CreateForScrypt(kScryptSalt)}); } // Test that if a client without a keystore key (e.g. one without keystore
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.cc b/components/sync/nigori/nigori_sync_bridge_impl.cc new file mode 100644 index 0000000..2481db8 --- /dev/null +++ b/components/sync/nigori/nigori_sync_bridge_impl.cc
@@ -0,0 +1,99 @@ +// 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. + +#include "components/sync/nigori/nigori_sync_bridge_impl.h" + +namespace syncer { + +NigoriSyncBridgeImpl::NigoriSyncBridgeImpl() = default; + +NigoriSyncBridgeImpl::~NigoriSyncBridgeImpl() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} + +void NigoriSyncBridgeImpl::AddObserver(Observer* observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriSyncBridgeImpl::RemoveObserver(Observer* observer) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriSyncBridgeImpl::Init() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriSyncBridgeImpl::SetEncryptionPassphrase( + const std::string& passphrase) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriSyncBridgeImpl::SetDecryptionPassphrase( + const std::string& passphrase) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +void NigoriSyncBridgeImpl::EnableEncryptEverything() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +bool NigoriSyncBridgeImpl::IsEncryptEverythingEnabled() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); + return false; +} + +bool NigoriSyncBridgeImpl::NeedKeystoreKey() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); + return false; +} + +bool NigoriSyncBridgeImpl::SetKeystoreKeys( + const std::vector<std::string>& keys) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); + return false; +} + +base::Optional<ModelError> NigoriSyncBridgeImpl::MergeSyncData( + const base::Optional<EntityData>& data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); + return base::nullopt; +} + +base::Optional<ModelError> NigoriSyncBridgeImpl::ApplySyncChanges( + const EntityData& data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); + return base::nullopt; +} + +std::unique_ptr<EntityData> NigoriSyncBridgeImpl::GetData() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); + return nullptr; +} + +ConflictResolution NigoriSyncBridgeImpl::ResolveConflict( + const EntityData& local_data, + const EntityData& remote_data) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); + return ConflictResolution::UseLocal(); +} + +void NigoriSyncBridgeImpl::ApplyDisableSyncChanges() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + NOTIMPLEMENTED(); +} + +} // namespace syncer
diff --git a/components/sync/nigori/nigori_sync_bridge_impl.h b/components/sync/nigori/nigori_sync_bridge_impl.h new file mode 100644 index 0000000..f52a676 --- /dev/null +++ b/components/sync/nigori/nigori_sync_bridge_impl.h
@@ -0,0 +1,68 @@ +// 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. + +#ifndef COMPONENTS_SYNC_NIGORI_NIGORI_SYNC_BRIDGE_IMPL_H_ +#define COMPONENTS_SYNC_NIGORI_NIGORI_SYNC_BRIDGE_IMPL_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "base/macros.h" +#include "base/optional.h" +#include "base/sequence_checker.h" +#include "components/sync/engine/sync_encryption_handler.h" +#include "components/sync/model/conflict_resolution.h" +#include "components/sync/model/model_error.h" +#include "components/sync/nigori/keystore_keys_handler.h" +#include "components/sync/nigori/nigori_sync_bridge.h" + +namespace syncer { + +// USS implementation of SyncEncryptionHandler. +// This class holds the current Nigori state and processes incoming changes and +// queries: +// 1. Serves observers of SyncEncryptionHandler interface. +// 2. Allows the passphrase manipulations (via SyncEncryptionHandler). +// 3. Communicates local and remote changes with a processor (via +// NigoriSyncBridge). +// 4. Handles keystore keys from a sync server (via KeystoreKeysHandler). +class NigoriSyncBridgeImpl : public KeystoreKeysHandler, + public NigoriSyncBridge, + public SyncEncryptionHandler { + public: + NigoriSyncBridgeImpl(); + ~NigoriSyncBridgeImpl() override; + + // SyncEncryptionHandler implementation. + void AddObserver(Observer* observer) override; + void RemoveObserver(Observer* observer) override; + void Init() override; + void SetEncryptionPassphrase(const std::string& passphrase) override; + void SetDecryptionPassphrase(const std::string& passphrase) override; + void EnableEncryptEverything() override; + bool IsEncryptEverythingEnabled() const override; + + // KeystoreKeysHandler implementation. + bool NeedKeystoreKey() const override; + bool SetKeystoreKeys(const std::vector<std::string>& keys) override; + + // NigoriSyncBridge implementation. + base::Optional<ModelError> MergeSyncData( + const base::Optional<EntityData>& data) override; + base::Optional<ModelError> ApplySyncChanges(const EntityData& data) override; + std::unique_ptr<EntityData> GetData() override; + ConflictResolution ResolveConflict(const EntityData& local_data, + const EntityData& remote_data) override; + void ApplyDisableSyncChanges() override; + + private: + SEQUENCE_CHECKER(sequence_checker_); + + DISALLOW_COPY_AND_ASSIGN(NigoriSyncBridgeImpl); +}; + +} // namespace syncer + +#endif // COMPONENTS_SYNC_NIGORI_NIGORI_SYNC_BRIDGE_IMPL_H_
diff --git a/components/sync_preferences/pref_model_associator.cc b/components/sync_preferences/pref_model_associator.cc index 1acf64c..d3e8110 100644 --- a/components/sync_preferences/pref_model_associator.cc +++ b/components/sync_preferences/pref_model_associator.cc
@@ -169,14 +169,6 @@ // we'll send the new user controlled value to the syncer. } -void PrefModelAssociator::RegisterMergeDataFinishedCallback( - const base::Closure& callback) { - if (!models_associated_) - callback_list_.push_back(callback); - else - callback.Run(); -} - void PrefModelAssociator::WaitUntilReadyToSync(base::OnceClosure done) { // Prefs are loaded very early during profile initialization. DCHECK_NE(pref_service_->GetAllPrefStoresInitializationStatus(), @@ -229,10 +221,6 @@ if (merge_result.error().IsSet()) return merge_result; - for (const auto& callback : callback_list_) - callback.Run(); - callback_list_.clear(); - models_associated_ = true; pref_service_->OnIsSyncingChanged(); return merge_result;
diff --git a/components/sync_preferences/pref_model_associator.h b/components/sync_preferences/pref_model_associator.h index ebf59e4..4271095d 100644 --- a/components/sync_preferences/pref_model_associator.h +++ b/components/sync_preferences/pref_model_associator.h
@@ -5,12 +5,10 @@ #ifndef COMPONENTS_SYNC_PREFERENCES_PREF_MODEL_ASSOCIATOR_H_ #define COMPONENTS_SYNC_PREFERENCES_PREF_MODEL_ASSOCIATOR_H_ -#include <map> #include <memory> #include <set> #include <string> #include <unordered_map> -#include <vector> #include "base/callback.h" #include "base/compiler_specific.h" @@ -119,10 +117,6 @@ // Returns the PrefModelAssociatorClient for this object. const PrefModelAssociatorClient* client() const { return client_; } - // Register callback method which will get called at the end of - // PrefModelAssociator::MergeDataAndStartSyncing(). - void RegisterMergeDataFinishedCallback(const base::Closure& callback); - private: friend class PrefServiceSyncableTest; @@ -202,8 +196,6 @@ const PrefModelAssociatorClient* client_; // Weak. - std::vector<base::Closure> callback_list_; - SEQUENCE_CHECKER(sequence_checker_); DISALLOW_COPY_AND_ASSIGN(PrefModelAssociator);
diff --git a/components/sync_preferences/pref_service_syncable.cc b/components/sync_preferences/pref_service_syncable.cc index e95aa297..7cdc8ed 100644 --- a/components/sync_preferences/pref_service_syncable.cc +++ b/components/sync_preferences/pref_service_syncable.cc
@@ -175,11 +175,6 @@ priority_pref_sync_associator_.RemoveSyncedPrefObserver(name, observer); } -void PrefServiceSyncable::RegisterMergeDataFinishedCallback( - const base::Closure& callback) { - pref_sync_associator_.RegisterMergeDataFinishedCallback(callback); -} - void PrefServiceSyncable::AddRegisteredSyncablePreference( const std::string& path, uint32_t flags) {
diff --git a/components/sync_preferences/pref_service_syncable.h b/components/sync_preferences/pref_service_syncable.h index b5bc127..85e3384 100644 --- a/components/sync_preferences/pref_service_syncable.h +++ b/components/sync_preferences/pref_service_syncable.h
@@ -78,8 +78,6 @@ void AddObserver(PrefServiceSyncableObserver* observer); void RemoveObserver(PrefServiceSyncableObserver* observer); - void RegisterMergeDataFinishedCallback(const base::Closure& callback); - // TODO(zea): Have PrefServiceSyncable implement // syncer::SyncableService directly. syncer::SyncableService* GetSyncableService(const syncer::ModelType& type);
diff --git a/components/sync_preferences/pref_service_syncable_unittest.cc b/components/sync_preferences/pref_service_syncable_unittest.cc index e792149..85fda24 100644 --- a/components/sync_preferences/pref_service_syncable_unittest.cc +++ b/components/sync_preferences/pref_service_syncable_unittest.cc
@@ -57,10 +57,6 @@ const char kNonDefaultCharsetValue[] = "foo"; const char kDefaultCharsetValue[] = "utf-8"; -void Increment(int* num) { - (*num)++; -} - class TestSyncProcessorStub : public syncer::SyncChangeProcessor { public: explicit TestSyncProcessorStub(syncer::SyncChangeList* output) @@ -909,17 +905,6 @@ EXPECT_TRUE(pref->IsDefaultValue()); } -TEST_F(PrefServiceSyncableTest, RegisterMergeDataFinishedCallback) { - int num_callbacks = 0; - - prefs_.RegisterMergeDataFinishedCallback( - base::Bind(&Increment, &num_callbacks)); - EXPECT_EQ(0, num_callbacks); - - InitWithNoSyncData(); - EXPECT_EQ(1, num_callbacks); -} - } // namespace } // namespace sync_preferences
diff --git a/components/test/data/autofill_assistant/autofill_assistant_target_website.html b/components/test/data/autofill_assistant/autofill_assistant_target_website.html index e8ef87b..6c995ab 100644 --- a/components/test/data/autofill_assistant/autofill_assistant_target_website.html +++ b/components/test/data/autofill_assistant/autofill_assistant_target_website.html
@@ -60,6 +60,10 @@ content: "before"; } + #with_inner_text span::before { + content: "before"; + } + #button::before { content: "before"; display: none; @@ -188,5 +192,11 @@ upperCaseInput.value = upperCaseInput.value.toUpperCase(); }); </script> + + <div id="with_inner_text"> + <span>hello</span> + <span>hello, world</span> + <span style="display: none">world</span> + </div> </body> </html>
diff --git a/components/viz/common/resources/resource_format_utils.cc b/components/viz/common/resources/resource_format_utils.cc index f7852c4..548c20d2 100644 --- a/components/viz/common/resources/resource_format_utils.cc +++ b/components/viz/common/resources/resource_format_utils.cc
@@ -36,8 +36,8 @@ case LUMINANCE_8: return kGray_8_SkColorType; case RGBX_8888: - return kRGB_888x_SkColorType; case ETC1: + return kRGB_888x_SkColorType; case RED_8: case LUMINANCE_F16: case R16_EXT: @@ -275,11 +275,11 @@ case R16_EXT: return GL_R16_EXT; case RGBX_8888: + case ETC1: return GL_RGB8_OES; case RGBX_1010102: return GL_RGB10_A2_EXT; case BGR_565: - case ETC1: case BGRX_8888: case BGRX_1010102: case YVU_420:
diff --git a/components/viz/host/host_frame_sink_manager_unittest.cc b/components/viz/host/host_frame_sink_manager_unittest.cc index 9fcb12a7..34403f5 100644 --- a/components/viz/host/host_frame_sink_manager_unittest.cc +++ b/components/viz/host/host_frame_sink_manager_unittest.cc
@@ -16,6 +16,7 @@ #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/service/surfaces/surface.h" #include "components/viz/service/surfaces/surface_manager.h" #include "components/viz/test/compositor_frame_helpers.h" #include "components/viz/test/fake_host_frame_sink_client.h"
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index 8392dc6..090d82cd 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -164,8 +164,6 @@ "surfaces/surface_deadline_client.h", "surfaces/surface_dependency_deadline.cc", "surfaces/surface_dependency_deadline.h", - "surfaces/surface_dependency_tracker.cc", - "surfaces/surface_dependency_tracker.h", "surfaces/surface_hittest.cc", "surfaces/surface_hittest.h", "surfaces/surface_hittest_delegate.h",
diff --git a/components/viz/service/display/display.h b/components/viz/service/display/display.h index 9323237..4c77f44 100644 --- a/components/viz/service/display/display.h +++ b/components/viz/service/display/display.h
@@ -23,6 +23,7 @@ #include "components/viz/service/display/software_output_device_client.h" #include "components/viz/service/display/surface_aggregator.h" #include "components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h" +#include "components/viz/service/surfaces/surface.h" #include "components/viz/service/surfaces/surface_manager.h" #include "components/viz/service/viz_service_export.h" #include "gpu/command_buffer/common/texture_in_use_response.h"
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.cc b/components/viz/service/display_embedder/skia_output_surface_impl.cc index 59c3c89..54b2c14 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl.cc
@@ -123,6 +123,7 @@ sk_sp<SkImage> MakePromiseSkImage(SkiaOutputSurfaceImpl* impl) { SkColorType color_type = ResourceFormatToClosestSkColorType( true /* gpu_compositing */, resource_format_); + impl->CreateFallbackPromiseImage(color_type); GrBackendFormat backend_format = impl->GetGrBackendFormatForTexture( resource_format_, render_pass_id_ ? GL_TEXTURE_2D : mailbox_holder_.texture_target); @@ -285,6 +286,7 @@ renderer_settings_(renderer_settings), weak_ptr_factory_(this) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + seen_resource_formats_.resize(kLastEnum_SkColorType + 1); } SkiaOutputSurfaceImpl::~SkiaOutputSurfaceImpl() { @@ -771,4 +773,14 @@ } } +void SkiaOutputSurfaceImpl::CreateFallbackPromiseImage(SkColorType color_type) { + if (seen_resource_formats_[color_type]) + return; + seen_resource_formats_[color_type] = true; + auto callback = + base::BindOnce(&SkiaOutputSurfaceImplOnGpu::CreateFallbackPromiseImage, + base::Unretained(impl_on_gpu_.get()), color_type); + ScheduleGpuTask(std::move(callback), std::vector<gpu::SyncToken>()); +} + } // namespace viz
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl.h b/components/viz/service/display_embedder/skia_output_surface_impl.h index 74a70ac..7334d12 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl.h
@@ -128,6 +128,8 @@ GrBackendFormat GetGrBackendFormatForTexture(ResourceFormat resource_format, uint32_t gl_texture_target); + void CreateFallbackPromiseImage(SkColorType color_type); + uint64_t sync_fence_release_ = 0; GpuServiceImpl* const gpu_service_; @@ -172,6 +174,8 @@ // Observers for context lost. base::ObserverList<ContextLostObserver>::Unchecked observers_; + std::vector<bool> seen_resource_formats_; + THREAD_CHECKER(thread_checker_); base::WeakPtr<SkiaOutputSurfaceImpl> weak_ptr_;
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc index eae8a86..91e70c5 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.cc
@@ -12,6 +12,7 @@ #include "base/synchronization/waitable_event.h" #include "components/viz/common/frame_sinks/copy_output_request.h" #include "components/viz/common/frame_sinks/copy_output_util.h" +#include "components/viz/common/resources/resource_format_utils.h" #include "components/viz/common/skia_helper.h" #include "components/viz/service/display/gl_renderer_copier.h" #include "components/viz/service/display/output_surface_frame.h" @@ -284,6 +285,7 @@ context_lost_callback_(context_lost_callback), weak_ptr_factory_(this) { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + fallback_promise_image_texture_.resize(kLastEnum_SkColorType + 1); weak_ptr_ = weak_ptr_factory_.GetWeakPtr(); } @@ -646,6 +648,13 @@ } } +sk_sp<SkPromiseImageTexture> SkiaOutputSurfaceImplOnGpu::FallbackPromiseImage( + ResourceFormat format) { + SkColorType color_type = + ResourceFormatToClosestSkColorType(true /* gpu_compositing */, format); + return fallback_promise_image_texture_[color_type]; +} + sk_sp<SkPromiseImageTexture> SkiaOutputSurfaceImplOnGpu::FulfillPromiseTexture( const gpu::MailboxHolder& mailbox_holder, const gfx::Size& size, @@ -660,12 +669,12 @@ if (!shared_image) { DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage " "mailbox not found in SharedImageManager."; - return nullptr; + return FallbackPromiseImage(resource_format); } if (!(shared_image->usage() & gpu::SHARED_IMAGE_USAGE_DISPLAY)) { DLOG(ERROR) << "Failed to fulfill the promise texture - SharedImage " "was not created with display usage."; - return nullptr; + return FallbackPromiseImage(resource_format); } *shared_image_out = std::move(shared_image); } @@ -681,13 +690,13 @@ // Probably this texture is created with wrong inteface (GLES2Interface). DLOG(ERROR) << "Failed to fulfill the promise texture whose backend is not " "compitable with vulkan."; - return nullptr; + return FallbackPromiseImage(resource_format); } auto* texture_base = mailbox_manager_->ConsumeTexture(mailbox_holder.mailbox); if (!texture_base) { DLOG(ERROR) << "Failed to fulfill the promise texture."; - return nullptr; + return FallbackPromiseImage(resource_format); } BindOrCopyTextureIfNecessary(texture_base); GrBackendTexture backend_texture; @@ -696,7 +705,7 @@ &backend_texture); if (!backend_texture.isValid()) { DLOG(ERROR) << "Failed to fulfill the promise texture."; - return nullptr; + return FallbackPromiseImage(resource_format); } return SkPromiseImageTexture::Make(backend_texture); } @@ -740,6 +749,29 @@ ReleaseFenceSyncAndPushTextureUpdates(sync_fence_release); } +void SkiaOutputSurfaceImplOnGpu::CreateFallbackPromiseImage( + SkColorType color_type) { + MakeCurrent(false /* need_fbo0 */); + + auto image_info = SkImageInfo::Make(1 /* width */, 1 /* height */, color_type, + kOpaque_SkAlphaType); + auto surface = SkSurface::MakeRenderTarget( + gr_context(), SkBudgeted::kNo, image_info, 0 /* sampleCount */, + kTopLeft_GrSurfaceOrigin, nullptr /* surfaceProps */); + DCHECK(!!surface); + auto* canvas = surface->getCanvas(); +#if DCHECK_IS_ON() + canvas->clear(SK_ColorRED); +#else + canvas->clear(SK_ColorWHITE); +#endif + fallback_promise_images_.push_back(surface->makeImageSnapshot()); + auto gr_texture = fallback_promise_images_.back()->getBackendTexture( + false /* flushPendingGrContextIO */); + fallback_promise_image_texture_[color_type] = + SkPromiseImageTexture::Make(gr_texture); +} + void SkiaOutputSurfaceImplOnGpu::SetCapabilitiesForTesting( const OutputSurface::Capabilities& capabilities) { MakeCurrent(false /* need_fbo0 */);
diff --git a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h index 01a910e..d5ceea4 100644 --- a/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h +++ b/components/viz/service/display_embedder/skia_output_surface_impl_on_gpu.h
@@ -154,6 +154,8 @@ void DestroySkImages(std::vector<sk_sp<SkImage>>&& images, uint64_t sync_fence_release); + void CreateFallbackPromiseImage(SkColorType color_type); + bool was_context_lost() { return context_state_->context_lost(); } class ScopedUseContextProvider; @@ -187,6 +189,8 @@ return output_device_->draw_surface(); } + sk_sp<SkPromiseImageTexture> FallbackPromiseImage(ResourceFormat format); + const gpu::SurfaceHandle surface_handle_; scoped_refptr<gpu::gles2::FeatureInfo> feature_info_; gpu::MailboxManager* const mailbox_manager_; @@ -247,6 +251,11 @@ gl::GLApi* api_ = nullptr; bool supports_alpha_ = false; + // What we display when the mailbox for a texture is invalid. Indexed by + // SkColorType. + std::vector<sk_sp<SkPromiseImageTexture>> fallback_promise_image_texture_; + std::vector<sk_sp<SkImage>> fallback_promise_images_; + THREAD_CHECKER(thread_checker_); base::WeakPtr<SkiaOutputSurfaceImplOnGpu> weak_ptr_;
diff --git a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc index 6824d9d..d365085 100644 --- a/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc +++ b/components/viz/service/frame_sinks/compositor_frame_sink_support_unittest.cc
@@ -14,6 +14,7 @@ #include "components/viz/common/surfaces/surface_info.h" #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/service/surfaces/surface.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/compositor_frame_helpers.h" #include "components/viz/test/fake_compositor_frame_sink_client.h"
diff --git a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc index d23cb76..9955da0 100644 --- a/components/viz/service/frame_sinks/surface_synchronization_unittest.cc +++ b/components/viz/service/frame_sinks/surface_synchronization_unittest.cc
@@ -8,6 +8,7 @@ #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/service/surfaces/surface.h" #include "components/viz/service/surfaces/surface_allocation_group.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/compositor_frame_helpers.h" @@ -412,7 +413,7 @@ parent_support().SubmitCompositorFrame( parent_id.local_surface_id(), - MakeCompositorFrame({child_id2}, empty_surface_ranges(), + MakeCompositorFrame({child_id2}, {SurfaceRange(base::nullopt, child_id2)}, std::vector<TransferableResource>())); // parent_support is blocked on |child_id2|. @@ -425,7 +426,7 @@ // child_support1 should now be blocked on |child_id2|. child_support1().SubmitCompositorFrame( child_id1.local_surface_id(), - MakeCompositorFrame({child_id2}, empty_surface_ranges(), + MakeCompositorFrame({child_id2}, {SurfaceRange(base::nullopt, child_id2)}, std::vector<TransferableResource>())); EXPECT_TRUE(child_surface1()->has_deadline()); @@ -3138,9 +3139,7 @@ EXPECT_TRUE(child_surface2->has_deadline()); // |child_id3| Surface should activate immediately because it corresponds to a - // parent-initiated synchronization event. |child_surface3| activating - // triggers all predecessors to activate as well if they're blocked on a - // parent. + // parent-initiated synchronization event. child_support1().SubmitCompositorFrame(child_id3.local_surface_id(), MakeDefaultCompositorFrame()); Surface* child_surface3 = GetSurfaceForId(child_id3); @@ -3148,12 +3147,6 @@ EXPECT_FALSE(child_surface3->HasPendingFrame()); EXPECT_TRUE(child_surface3->HasActiveFrame()); EXPECT_FALSE(IsMarkedForDestruction(child_id3)); - - // |child_surface2| should have activated now (and should be a candidate for - // garbage collection). - EXPECT_FALSE(child_surface2->HasPendingFrame()); - EXPECT_TRUE(child_surface2->HasActiveFrame()); - EXPECT_TRUE(IsMarkedForDestruction(child_id2)); } TEST_F(SurfaceSynchronizationTest, EvictSurface) { @@ -3528,4 +3521,58 @@ EXPECT_TRUE(surface_manager()->GetAllocationGroupForSurfaceId(child_id2)); } +// This test verifies that the child gets unthrottled when the parent embeds the +// second last surface. https://crbug.com/898460 +TEST_F(SurfaceSynchronizationTest, + ChildUnthrottledWhenSecondLastSurfaceEmbedded) { + const SurfaceId parent_id = MakeSurfaceId(kParentFrameSink, 1); + const SurfaceId child_id1 = MakeSurfaceId(kChildFrameSink1, 1, 1); + const SurfaceId child_id2 = MakeSurfaceId(kChildFrameSink1, 1, 2); + const SurfaceId child_id3 = MakeSurfaceId(kChildFrameSink1, 1, 3); + + // |child_id1| Surface should immediately activate because one unembedded + // surface is allowed. + child_support1().SubmitCompositorFrame(child_id1.local_surface_id(), + MakeDefaultCompositorFrame()); + Surface* child_surface1 = GetSurfaceForId(child_id1); + ASSERT_NE(nullptr, child_surface1); + EXPECT_FALSE(child_surface1->HasPendingFrame()); + EXPECT_TRUE(child_surface1->HasActiveFrame()); + + // |child_id2| Surface should not activate because now there are two surfaces + // not embedded by the parent makes child throttling kick in. + child_support1().SubmitCompositorFrame( + child_id2.local_surface_id(), + MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(), + std::vector<TransferableResource>(), + MakeDeadline(1u))); + Surface* child_surface2 = GetSurfaceForId(child_id2); + ASSERT_NE(nullptr, child_surface2); + EXPECT_TRUE(child_surface2->HasPendingFrame()); + EXPECT_FALSE(child_surface2->HasActiveFrame()); + EXPECT_TRUE(child_surface2->has_deadline()); + + // The parent embeds |child_id1| and blocks. Both |child_id2| should activate + // because now again there is only one surface not embedded by the parent. + parent_support().SubmitCompositorFrame( + parent_id.local_surface_id(), + MakeCompositorFrame({child_id1}, {SurfaceRange(base::nullopt, child_id1)}, + std::vector<TransferableResource>(), + MakeDefaultDeadline())); + EXPECT_FALSE(child_surface2->HasPendingFrame()); + EXPECT_TRUE(child_surface2->HasActiveFrame()); + + // The child submits to |child_id3|. Now again we have two unembedded surface + // so throttling should kick in. + child_support1().SubmitCompositorFrame( + child_id3.local_surface_id(), + MakeCompositorFrame(empty_surface_ids(), empty_surface_ranges(), + std::vector<TransferableResource>(), + MakeDeadline(1u))); + Surface* child_surface3 = GetSurfaceForId(child_id3); + ASSERT_NE(nullptr, child_surface3); + EXPECT_TRUE(child_surface3->HasPendingFrame()); + EXPECT_FALSE(child_surface3->HasActiveFrame()); +} + } // namespace viz
diff --git a/components/viz/service/frame_sinks/video_detector.cc b/components/viz/service/frame_sinks/video_detector.cc index 8f560c3af..b84e9b2 100644 --- a/components/viz/service/frame_sinks/video_detector.cc +++ b/components/viz/service/frame_sinks/video_detector.cc
@@ -6,6 +6,7 @@ #include "base/time/time.h" #include "components/viz/common/quads/compositor_frame.h" +#include "components/viz/service/surfaces/surface.h" #include "components/viz/service/surfaces/surface_manager.h" #include "ui/gfx/geometry/dip_util.h" #include "ui/gfx/geometry/rect.h"
diff --git a/components/viz/service/hit_test/hit_test_aggregator.h b/components/viz/service/hit_test/hit_test_aggregator.h index 3d09c668..203ff01 100644 --- a/components/viz/service/hit_test/hit_test_aggregator.h +++ b/components/viz/service/hit_test/hit_test_aggregator.h
@@ -6,6 +6,7 @@ #define COMPONENTS_VIZ_SERVICE_HIT_TEST_HIT_TEST_AGGREGATOR_H_ #include "components/viz/common/hit_test/aggregated_hit_test_region.h" +#include "components/viz/common/quads/render_pass.h" #include "components/viz/common/surfaces/surface_id.h" #include "components/viz/service/hit_test/hit_test_manager.h" #include "components/viz/service/surfaces/surface_observer.h"
diff --git a/components/viz/service/hit_test/hit_test_manager.cc b/components/viz/service/hit_test/hit_test_manager.cc index ce7e72b7..8c2239d 100644 --- a/components/viz/service/hit_test/hit_test_manager.cc +++ b/components/viz/service/hit_test/hit_test_manager.cc
@@ -6,6 +6,7 @@ #include "components/viz/common/hit_test/aggregated_hit_test_region.h" #include "components/viz/service/surfaces/latest_local_surface_id_lookup_delegate.h" +#include "components/viz/service/surfaces/surface.h" namespace viz {
diff --git a/components/viz/service/surfaces/surface.cc b/components/viz/service/surfaces/surface.cc index 81b583ba..01a6440 100644 --- a/components/viz/service/surfaces/surface.cc +++ b/components/viz/service/surfaces/surface.cc
@@ -57,6 +57,8 @@ // it references. for (SurfaceAllocationGroup* group : referenced_allocation_groups_) group->UnregisterActiveEmbedder(this); + for (SurfaceAllocationGroup* group : blocking_allocation_groups_) + group->UnregisterBlockedEmbedder(this, false /* did_activate */); DCHECK(deadline_); deadline_->Cancel(); @@ -196,8 +198,6 @@ if (!activation_dependencies_.empty() || !pending_frame_data_) return; - DCHECK(frame_sink_id_dependencies_.empty()); - // All blockers have been cleared. The surface can be activated now. ActivatePendingFrame(base::nullopt); } @@ -241,9 +241,7 @@ if (!seen_first_surface_dependency_) { // We should not throttle this client if there is another client blocked on // it, in order to avoid deadlocks. - seen_first_surface_dependency_ = - surface_manager_->dependency_tracker()->HasSurfaceBlockedOn( - surface_id().frame_sink_id()); + seen_first_surface_dependency_ = allocation_group_->HasBlockedEmbedder(); } bool block_activation = @@ -259,17 +257,9 @@ FrameData(std::move(frame), frame_index, std::move(presented_callback)); RejectCompositorFramesToFallbackSurfaces(); - // Ask SurfaceDependencyTracker to inform |this| when it is embedded. - if (block_activation) - surface_manager_->dependency_tracker()->TrackEmbedding(this); - // If the deadline is in the past, then the CompositorFrame will activate // immediately. - if (deadline_->Set(ResolveFrameDeadline(pending_frame_data_->frame))) { - // Ask the SurfaceDependencyTracker to inform |this| when its dependencies - // are resolved. - surface_manager_->dependency_tracker()->RequestSurfaceResolution(this); - } + deadline_->Set(ResolveFrameDeadline(pending_frame_data_->frame)); } // Returns resources for the previous pending frame. @@ -302,61 +292,16 @@ copy_requests.push_back(std::move(copy_request)); } -void Surface::NotifySurfaceIdAvailable(const SurfaceId& surface_id) { - auto it = frame_sink_id_dependencies_.find(surface_id.frame_sink_id()); - if (it == frame_sink_id_dependencies_.end()) - return; - - if (surface_id.local_surface_id().parent_sequence_number() > - it->second.parent_sequence_number || - surface_id.local_surface_id().child_sequence_number() > - it->second.child_sequence_number || - (surface_id.local_surface_id().parent_sequence_number() == - it->second.parent_sequence_number && - surface_id.local_surface_id().child_sequence_number() == - it->second.child_sequence_number)) { - frame_sink_id_dependencies_.erase(it); - surface_manager_->SurfaceDependenciesChanged(this, {}, - {surface_id.frame_sink_id()}); - } - - // TODO(fsamuel): This is a linear scan which is probably fine today because - // a given surface has a small number of dependencies. We might need to - // revisit this in the future if the number of dependencies grows - // significantly. - auto delete_fn = [surface_id](const SurfaceId& dependency) { - if (dependency.frame_sink_id() != surface_id.frame_sink_id()) - return false; - // The dependency will never get satisfied if the child is already using a - // larger parent or child sequence number, so drop the dependency in that - // case. - if (dependency.local_surface_id().parent_sequence_number() < - surface_id.local_surface_id().parent_sequence_number() || - dependency.local_surface_id().child_sequence_number() < - surface_id.local_surface_id().child_sequence_number()) { - return true; - } - // For the dependency to get satisfied, both parent and child sequence - // numbers of the activated SurfaceId must be equal to those of the - // dependency. - return dependency.local_surface_id().parent_sequence_number() == - surface_id.local_surface_id().parent_sequence_number() && - dependency.local_surface_id().child_sequence_number() == - surface_id.local_surface_id().child_sequence_number(); - }; - - base::EraseIf(activation_dependencies_, delete_fn); - - // We cannot activate this CompositorFrame if there are still missing - // activation dependencies or this surface is blocked on its parent arriving - // and the parent has not arrived yet. +void Surface::OnActivationDependencyResolved( + const SurfaceId& activation_dependency, + SurfaceAllocationGroup* group) { + DCHECK(activation_dependencies_.count(activation_dependency)); + activation_dependencies_.erase(activation_dependency); + blocking_allocation_groups_.erase(group); bool block_activation = block_activation_on_parent_ && !seen_first_surface_dependency_; if (block_activation || !activation_dependencies_.empty()) return; - - DCHECK(frame_sink_id_dependencies_.empty()); - // All blockers have been cleared. The surface can be activated now. ActivatePendingFrame(base::nullopt); } @@ -369,7 +314,12 @@ // If a frame is being activated because of a deadline, then clear its set // of blockers. activation_dependencies_.clear(); - frame_sink_id_dependencies_.clear(); + + // We treat an activation (by deadline) as being the equivalent of a parent + // embedding the surface in order to avoid blocking future frames to the same + // surface. + seen_first_surface_dependency_ = true; + ActivatePendingFrame(duration); } @@ -440,7 +390,7 @@ surface_range.end()); if (end_allocation_group) { new_referenced_allocation_groups.push_back(end_allocation_group); - end_allocation_group->UpdateLastReferencedSurfaceAndMaybeActivate( + end_allocation_group->UpdateLastActiveReferenceAndMaybeActivate( surface_range.end()); } // Only reference the allocation group for the start of SurfaceRange if the @@ -453,7 +403,7 @@ *surface_range.start()); if (start_allocation_group) { new_referenced_allocation_groups.push_back(start_allocation_group); - start_allocation_group->UpdateLastReferencedSurfaceAndMaybeActivate( + start_allocation_group->UpdateLastActiveReferenceAndMaybeActivate( *surface_range.start()); } } @@ -487,6 +437,12 @@ active_frame_data_ = std::move(frame_data); + // We no longer have a pending frame, so unregister self from + // |blocking_allocation_groups_|. + for (SurfaceAllocationGroup* group : blocking_allocation_groups_) + group->UnregisterBlockedEmbedder(this, true /* did_activate */); + blocking_allocation_groups_.clear(); + RecomputeActiveReferencedSurfaces(); for (auto& copy_request : old_copy_requests) @@ -531,7 +487,7 @@ // active frame already, active this frame immediately so we have something to // show. if (!HasActiveFrame() && - allocation_group_->GetLastReferencedSurfaceId().IsSameOrNewerThan( + allocation_group_->GetLastActiveReference().IsSameOrNewerThan( surface_id())) { return FrameDeadline::MakeZero(); } @@ -560,76 +516,41 @@ void Surface::UpdateActivationDependencies( const CompositorFrame& current_frame) { - base::flat_map<FrameSinkId, SequenceNumbers> new_frame_sink_id_dependencies; - base::flat_set<SurfaceId> new_activation_dependencies; + for (SurfaceAllocationGroup* group : blocking_allocation_groups_) + group->UnregisterBlockedEmbedder(this, false /* did_activate */); + blocking_allocation_groups_.clear(); + activation_dependencies_.clear(); + std::vector<SurfaceAllocationGroup*> new_blocking_allocation_groups; + std::vector<SurfaceId> new_activation_dependencies; for (const SurfaceId& surface_id : current_frame.metadata.activation_dependencies) { - // Inform the Surface |dependency| that it's been added as a dependency in - // another Surface's CompositorFrame. - surface_manager_->SurfaceDependencyAdded(surface_id); - + SurfaceAllocationGroup* group = + surface_manager_->GetOrCreateAllocationGroupForSurfaceId(surface_id); + if (group) + group->UpdateLastPendingReferenceAndMaybeActivate(surface_id); Surface* dependency = surface_manager_->GetSurfaceForId(surface_id); - - // If a activation dependency does not have a corresponding active frame in - // the display compositor, then it blocks this frame. - if (!dependency || !dependency->HasActiveFrame()) { - new_activation_dependencies.insert(surface_id); - TRACE_EVENT_WITH_FLOW2( - TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"), - "LocalSurfaceId.Embed.Flow", - TRACE_ID_GLOBAL(surface_id.local_surface_id().embed_trace_id()), - TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step", - "AddedActivationDependency", "child_surface_id", - surface_id.ToString()); - - // Record the latest |parent_sequence_number| this surface is interested - // in observing for the provided FrameSinkId. - uint32_t& parent_sequence_number = - new_frame_sink_id_dependencies[surface_id.frame_sink_id()] - .parent_sequence_number; - parent_sequence_number = - std::max(parent_sequence_number, - surface_id.local_surface_id().parent_sequence_number()); - - uint32_t& child_sequence_number = - new_frame_sink_id_dependencies[surface_id.frame_sink_id()] - .child_sequence_number; - child_sequence_number = - std::max(child_sequence_number, - surface_id.local_surface_id().child_sequence_number()); + if (dependency && dependency->HasActiveFrame()) { + // Normally every creation of SurfaceAllocationGroup should be followed by + // a call to Register* to keep it alive. However, since this one already + // has a registered surface, we don't have to do that. + DCHECK(!group->IsReadyToDestroy()); + continue; } + if (group) { + group->RegisterBlockedEmbedder(this, surface_id); + new_blocking_allocation_groups.push_back(group); + } + TRACE_EVENT_WITH_FLOW2( + TRACE_DISABLED_BY_DEFAULT("viz.surface_id_flow"), + "LocalSurfaceId.Embed.Flow", + TRACE_ID_GLOBAL(surface_id.local_surface_id().embed_trace_id()), + TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, "step", + "AddedActivationDependency", "child_surface_id", surface_id.ToString()); + new_activation_dependencies.push_back(surface_id); } - - // If this Surface has a previous pending frame, then we must determine the - // changes in dependencies so that we can update the SurfaceDependencyTracker - // map. - ComputeChangeInDependencies(new_frame_sink_id_dependencies); - activation_dependencies_ = std::move(new_activation_dependencies); - frame_sink_id_dependencies_ = std::move(new_frame_sink_id_dependencies); -} - -void Surface::ComputeChangeInDependencies( - const base::flat_map<FrameSinkId, SequenceNumbers>& new_dependencies) { - base::flat_set<FrameSinkId> added_dependencies; - base::flat_set<FrameSinkId> removed_dependencies; - - for (const auto& kv : frame_sink_id_dependencies_) { - if (!new_dependencies.count(kv.first)) - removed_dependencies.insert(kv.first); - } - - for (const auto& kv : new_dependencies) { - if (!frame_sink_id_dependencies_.count(kv.first)) - added_dependencies.insert(kv.first); - } - - // If there is a change in the dependency set, then inform SurfaceManager. - if (!added_dependencies.empty() || !removed_dependencies.empty()) { - surface_manager_->SurfaceDependenciesChanged(this, added_dependencies, - removed_dependencies); - } + blocking_allocation_groups_ = std::move(new_blocking_allocation_groups); } void Surface::TakeCopyOutputRequests(Surface::CopyRequestsMap* copy_requests) { @@ -824,4 +745,17 @@ ActivatePendingFrameForDeadline(base::nullopt); } +void Surface::ResetBlockActivationOnParent() { + if (!block_activation_on_parent_) + return; + + block_activation_on_parent_ = false; + + if (!activation_dependencies_.empty() || !pending_frame_data_) + return; + + // All blockers have been cleared. The surface can be activated now. + ActivatePendingFrame(base::nullopt); +} + } // namespace viz
diff --git a/components/viz/service/surfaces/surface.h b/components/viz/service/surfaces/surface.h index 1d779af..2f8d332 100644 --- a/components/viz/service/surfaces/surface.h +++ b/components/viz/service/surfaces/surface.h
@@ -229,12 +229,16 @@ // is already taken. bool is_latency_info_taken() { return is_latency_info_taken_; } - private: - struct SequenceNumbers { - uint32_t parent_sequence_number = 0u; - uint32_t child_sequence_number = 0u; - }; + // Called by a blocking SurfaceAllocationGroup when |activation_dependency| + // is resolved. |this| will be automatically unregistered from |group|, the + // SurfaceAllocationGroup corresponding to |activation_dependency|. + void OnActivationDependencyResolved(const SurfaceId& activation_dependency, + SurfaceAllocationGroup* group); + // Called when this surface's activation no longer has to block on the parent. + void ResetBlockActivationOnParent(); + + private: struct FrameData { FrameData(CompositorFrame&& frame, uint64_t frame_index, @@ -292,9 +296,6 @@ // dependencies will be added even if they're not yet available. void UpdateActivationDependencies(const CompositorFrame& current_frame); - void ComputeChangeInDependencies( - const base::flat_map<FrameSinkId, SequenceNumbers>& new_dependencies); - void UnrefFrameResourcesAndRunCallbacks(base::Optional<FrameData> frame_data); void ClearCopyRequests(); @@ -318,18 +319,7 @@ bool seen_first_surface_embedding_ = false; bool seen_first_surface_dependency_ = false; const bool needs_sync_tokens_; - const bool block_activation_on_parent_; - - base::flat_set<SurfaceId> activation_dependencies_; - - // A map from FrameSinkIds of SurfaceIds that this surface depends on for - // activation to the latest local_id associated with the given FrameSinkId - // that this surface is dependent on. This map is used to determine which - // FrameSinkIds this surface would like to observe activations for. Once - // the latest activated SurfaceId associated with the given FrameSinkId - // passes the local_id in the map, then this surface is no longer interested - // in observing activations for that FrameSinkId. - base::flat_map<FrameSinkId, SequenceNumbers> frame_sink_id_dependencies_; + bool block_activation_on_parent_ = false; // A set of all valid SurfaceIds contained |last_surface_id_for_range_| to // avoid recompution. @@ -344,6 +334,16 @@ // Allocation groups that this surface references by its active frame. base::flat_set<SurfaceAllocationGroup*> referenced_allocation_groups_; + // The set of the SurfaceIds that are blocking the pending frame from being + // activated. + base::flat_set<SurfaceId> activation_dependencies_; + + // The SurfaceAllocationGroups corresponding to the surfaces in + // |activation_dependencies_|. When an activation dependency is + // resolved, the corresponding SurfaceAllocationGroup will call back into this + // surface to let us know. + base::flat_set<SurfaceAllocationGroup*> blocking_allocation_groups_; + bool is_latency_info_taken_ = false; SurfaceAllocationGroup* const allocation_group_;
diff --git a/components/viz/service/surfaces/surface_allocation_group.cc b/components/viz/service/surfaces/surface_allocation_group.cc index 7e67c9f..6e60ce22 100644 --- a/components/viz/service/surfaces/surface_allocation_group.cc +++ b/components/viz/service/surfaces/surface_allocation_group.cc
@@ -17,10 +17,15 @@ embed_token_(embed_token), surface_manager_(surface_manager) {} -SurfaceAllocationGroup::~SurfaceAllocationGroup() = default; +SurfaceAllocationGroup::~SurfaceAllocationGroup() { + DCHECK(surfaces_.empty()); + DCHECK(active_embedders_.empty()); + DCHECK(blocked_embedders_.empty()); +} bool SurfaceAllocationGroup::IsReadyToDestroy() const { - return surfaces_.empty() && active_embedders_.empty(); + return surfaces_.empty() && active_embedders_.empty() && + blocked_embedders_.empty(); } void SurfaceAllocationGroup::RegisterSurface(Surface* surface) { @@ -39,6 +44,27 @@ MaybeMarkForDestruction(); } +void SurfaceAllocationGroup::RegisterBlockedEmbedder( + Surface* surface, + const SurfaceId& activation_dependency) { + blocked_embedders_[surface] = activation_dependency; +} + +void SurfaceAllocationGroup::UnregisterBlockedEmbedder(Surface* surface, + bool did_activate) { + DCHECK(blocked_embedders_.count(surface)); + blocked_embedders_.erase(surface); + // If the pending frame activated, don't notify SurfaceManager that this + // allocation group needs to be destroyed, because the embedder will soon + // call RegisterActiveEmbedder. + if (!did_activate) + MaybeMarkForDestruction(); +} + +bool SurfaceAllocationGroup::HasBlockedEmbedder() const { + return !blocked_embedders_.empty(); +} + void SurfaceAllocationGroup::RegisterActiveEmbedder(Surface* surface) { DCHECK(!active_embedders_.count(surface)); active_embedders_.insert(surface); @@ -50,22 +76,32 @@ MaybeMarkForDestruction(); } -void SurfaceAllocationGroup::UpdateLastReferencedSurfaceAndMaybeActivate( +void SurfaceAllocationGroup::UpdateLastActiveReferenceAndMaybeActivate( const SurfaceId& surface_id) { DCHECK_EQ(submitter_, surface_id.frame_sink_id()); DCHECK_EQ(embed_token_, surface_id.local_surface_id().embed_token()); - if (last_referenced_surface_id_.is_valid() && - last_referenced_surface_id_.IsSameOrNewerThan(surface_id)) { + if (last_active_reference_.is_valid() && + last_active_reference_.IsSameOrNewerThan(surface_id)) { return; } - last_referenced_surface_id_ = surface_id; + last_active_reference_ = surface_id; auto it = FindLatestSurfaceUpTo(surface_id); if (it != surfaces_.end() && !(*it)->HasActiveFrame()) (*it)->ActivatePendingFrameForInheritedDeadline(); + UpdateLastReferenceAndMaybeActivate(surface_id); } -const SurfaceId& SurfaceAllocationGroup::GetLastReferencedSurfaceId() { - return last_referenced_surface_id_; +void SurfaceAllocationGroup::UpdateLastPendingReferenceAndMaybeActivate( + const SurfaceId& surface_id) { + UpdateLastReferenceAndMaybeActivate(surface_id); +} + +const SurfaceId& SurfaceAllocationGroup::GetLastActiveReference() { + return last_active_reference_; +} + +const SurfaceId& SurfaceAllocationGroup::GetLastReference() { + return last_reference_; } Surface* SurfaceAllocationGroup::FindLatestActiveSurfaceInRange( @@ -121,6 +157,23 @@ void SurfaceAllocationGroup::OnFirstSurfaceActivation(Surface* surface) { for (Surface* embedder : active_embedders_) embedder->OnChildActivatedForActiveFrame(surface->surface_id()); + base::flat_map<Surface*, SurfaceId> embedders_to_notify; + for (const auto& entry : blocked_embedders_) { + if (!entry.second.IsNewerThan(surface->surface_id())) + embedders_to_notify[entry.first] = entry.second; + } + for (const auto& entry : embedders_to_notify) + blocked_embedders_.erase(entry.first); + for (const auto& entry : embedders_to_notify) + entry.first->OnActivationDependencyResolved(entry.second, this); +} + +void SurfaceAllocationGroup::WillNotRegisterNewSurfaces() { + base::flat_map<Surface*, SurfaceId> embedders = std::move(blocked_embedders_); + blocked_embedders_.clear(); + for (const auto& entry : embedders) { + entry.first->OnActivationDependencyResolved(entry.second, this); + } } std::vector<Surface*>::const_iterator @@ -178,4 +231,21 @@ surface_manager_->SetAllocationGroupsNeedGarbageCollection(); } +void SurfaceAllocationGroup::UpdateLastReferenceAndMaybeActivate( + const SurfaceId& surface_id) { + if (last_reference_.IsSameOrNewerThan(surface_id)) + return; + last_reference_ = surface_id; + if (surfaces_.empty()) + return; + auto it = FindLatestSurfaceUpTo(surface_id); + if (it == surfaces_.end()) + return; + (*it)->OnSurfaceDependencyAdded(); + ++it; + if (it == surfaces_.end()) + return; + (*it)->ResetBlockActivationOnParent(); +} + } // namespace viz
diff --git a/components/viz/service/surfaces/surface_allocation_group.h b/components/viz/service/surfaces/surface_allocation_group.h index cd36f27..f88acdf 100644 --- a/components/viz/service/surfaces/surface_allocation_group.h +++ b/components/viz/service/surfaces/surface_allocation_group.h
@@ -51,6 +51,21 @@ // allocation group. void UnregisterSurface(Surface* surface); + // Called by |surface| when it has a pending frame that is blocked on + // |activation_dependency| in this allocation group. The embedder will be + // notified when |activation_dependency| becomes available. + void RegisterBlockedEmbedder(Surface* surface, + const SurfaceId& activation_dependency); + + // Called by |surface| when its pending frame that still has an unresolved + // activation dependency in this allocation group either activates + // (|did_activate| == true) or gets dropped (|did_activate| == false). + void UnregisterBlockedEmbedder(Surface* surface, bool did_activate); + + // Returns whether there is any embedder that is blocked on a surface in this + // allocation group. + bool HasBlockedEmbedder() const; + // Called by |surface| when its newly activated frame references a surface in // this allocation group. The embedder will be notified whenever a surface in // this allocation group activates for the first time. @@ -60,14 +75,23 @@ // surface in this allocation group. void UnregisterActiveEmbedder(Surface* surface); - // Called by an active embedder when its CompositorFrame references a surface - // in this allocation group. |surface_id| or the last surface prior to it will - // be forcefully activated due to deadline inheritance. - void UpdateLastReferencedSurfaceAndMaybeActivate(const SurfaceId& surface_id); + // Notifies that a surface exists whose active frame references |surface_id| + // in this allocation group. |surface_id| or the last surface prior to it may + // be activated due to deadline inheritance. + void UpdateLastActiveReferenceAndMaybeActivate(const SurfaceId& surface_id); + + // Notifies that a surface exists whose pending frame references |surface_id| + // in this allocation group. |surface_id| or some surface prior to it might + // activate if it was blocked due to child throttling. + void UpdateLastPendingReferenceAndMaybeActivate(const SurfaceId& surface_id); // Returns the last SurfaceId in this allocation group that was ever - // referenced. - const SurfaceId& GetLastReferencedSurfaceId(); + // referenced by the active frame of a surface. + const SurfaceId& GetLastActiveReference(); + + // Returns the last SurfaceId in this allocation group that was ever + // referenced by a pending or an active frame of a surface. + const SurfaceId& GetLastReference(); // Returns the latest active surface in the given range that is a part of this // allocation group. The embed token of at least one end of the range must @@ -84,6 +108,11 @@ // time. void OnFirstSurfaceActivation(Surface* surface); + // Called when there will not be any calls to RegisterSurface in the future. + // All pending embedders that were blocked on surfaces that don't exist yet + // will have their dependency resolved. + void WillNotRegisterNewSurfaces(); + // Returns the last surface created in this allocation group. Surface* last_created_surface() const { return surfaces_.empty() ? nullptr : surfaces_.back(); @@ -105,6 +134,10 @@ // (see IsReadyToDestroy() for the requirements). void MaybeMarkForDestruction(); + // Updates the last reference. |surface_id| or a surface prior to it might + // activate if it was blocked due to child throttling. + void UpdateLastReferenceAndMaybeActivate(const SurfaceId& surface_id); + // The ID of the FrameSink that is submitting to the surfaces in this // allocation group. const FrameSinkId submitter_; @@ -119,6 +152,10 @@ // increasing. std::vector<Surface*> surfaces_; + // A map from the surfaces that have an unresolved activation dependency in + // this allocation group, to the said activation dependency. + base::flat_map<Surface*, SurfaceId> blocked_embedders_; + // The set of surfaces that reference a surface in this allocation group by // their active frame. base::flat_set<Surface*> active_embedders_; @@ -127,9 +164,13 @@ // ready to be destroyed. SurfaceManager* const surface_manager_; - // The last SurfaceId of this allocation group that was ever referenced by an - // active embedder. - SurfaceId last_referenced_surface_id_; + // The last SurfaceId of this allocation group that was ever referenced by the + // active frame of a surface. + SurfaceId last_active_reference_; + + // The last SurfaceId of this allocation group that was ever referenced by the + // active or pending frame of a surface. + SurfaceId last_reference_; DISALLOW_COPY_AND_ASSIGN(SurfaceAllocationGroup); };
diff --git a/components/viz/service/surfaces/surface_dependency_tracker.cc b/components/viz/service/surfaces/surface_dependency_tracker.cc deleted file mode 100644 index 0f06d6e..0000000 --- a/components/viz/service/surfaces/surface_dependency_tracker.cc +++ /dev/null
@@ -1,167 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/viz/service/surfaces/surface_dependency_tracker.h" - -#include "build/build_config.h" -#include "components/viz/common/surfaces/surface_info.h" -#include "components/viz/service/surfaces/surface.h" -#include "components/viz/service/surfaces/surface_manager.h" - -namespace viz { - -SurfaceDependencyTracker::SurfaceDependencyTracker( - SurfaceManager* surface_manager) - : surface_manager_(surface_manager) {} - -SurfaceDependencyTracker::~SurfaceDependencyTracker() = default; - -void SurfaceDependencyTracker::TrackEmbedding(Surface* surface) { - // If |surface| is blocking on the arrival of a parent and the parent frame - // has not yet arrived then track this |surface|'s SurfaceId by FrameSinkId so - // that if a parent refers to it or a more recent surface, then - // SurfaceDependencyTracker reports back that a dependency has been added. - if (surface->block_activation_on_parent() && !surface->HasDependentFrame()) { - surfaces_blocked_on_parent_by_frame_sink_id_[surface->surface_id() - .frame_sink_id()] - .insert(surface->surface_id()); - } -} - -void SurfaceDependencyTracker::RequestSurfaceResolution(Surface* surface) { - DCHECK(surface->HasPendingFrame()); - - // Activation dependencies that aren't currently known to the surface manager - // or do not have an active CompositorFrame block this frame. - for (const SurfaceId& surface_id : surface->activation_dependencies()) { - Surface* dependency = surface_manager_->GetSurfaceForId(surface_id); - if (!dependency || !dependency->HasActiveFrame()) { - blocked_surfaces_from_dependency_[surface_id.frame_sink_id()].insert( - surface->surface_id()); - } - } -} - -bool SurfaceDependencyTracker::HasSurfaceBlockedOn( - const FrameSinkId& frame_sink_id) const { - auto it = blocked_surfaces_from_dependency_.find(frame_sink_id); - DCHECK(it == blocked_surfaces_from_dependency_.end() || !it->second.empty()); - return it != blocked_surfaces_from_dependency_.end(); -} - -void SurfaceDependencyTracker::OnSurfaceActivated(Surface* surface) { - NotifySurfaceIdAvailable(surface->surface_id()); - // We treat an activation (by deadline) as being the equivalent of a parent - // embedding the surface. - OnSurfaceDependencyAdded(surface->surface_id()); -} - -void SurfaceDependencyTracker::OnSurfaceDependencyAdded( - const SurfaceId& surface_id) { - auto it = surfaces_blocked_on_parent_by_frame_sink_id_.find( - surface_id.frame_sink_id()); - if (it == surfaces_blocked_on_parent_by_frame_sink_id_.end()) - return; - - std::vector<SurfaceId> dependencies_to_notify; - - base::flat_set<SurfaceId>& blocked_surfaces = it->second; - for (auto iter = blocked_surfaces.begin(); iter != blocked_surfaces.end();) { - bool should_notify = - iter->local_surface_id() <= surface_id.local_surface_id(); -#if defined(OS_ANDROID) - // On Android we work around a throttling bug by also firing if the - // immediately preceding surface has a dependency added. - // TODO(https://crbug.com/898460): Solve this generally. - bool is_same_parent = - iter->local_surface_id().parent_sequence_number() == - surface_id.local_surface_id().parent_sequence_number(); - bool is_next_child = - iter->local_surface_id().child_sequence_number() == - surface_id.local_surface_id().child_sequence_number() + 1; - should_notify |= is_same_parent && is_next_child; -#endif - if (should_notify) { - dependencies_to_notify.push_back(*iter); - iter = blocked_surfaces.erase(iter); - } else { - ++iter; - } - } - - if (blocked_surfaces.empty()) - surfaces_blocked_on_parent_by_frame_sink_id_.erase(it); - - for (const SurfaceId& dependency : dependencies_to_notify) { - Surface* surface = surface_manager_->GetSurfaceForId(dependency); - if (surface) - surface->OnSurfaceDependencyAdded(); - } -} - -void SurfaceDependencyTracker::OnSurfaceDependenciesChanged( - Surface* surface, - const base::flat_set<FrameSinkId>& added_dependencies, - const base::flat_set<FrameSinkId>& removed_dependencies) { - // Update the |blocked_surfaces_from_dependency_| map with the changes in - // dependencies. - for (const FrameSinkId& frame_sink_id : added_dependencies) { - blocked_surfaces_from_dependency_[frame_sink_id].insert( - surface->surface_id()); - } - - for (const FrameSinkId& frame_sink_id : removed_dependencies) { - auto it = blocked_surfaces_from_dependency_.find(frame_sink_id); - if (it != blocked_surfaces_from_dependency_.end()) { - it->second.erase(surface->surface_id()); - if (it->second.empty()) - blocked_surfaces_from_dependency_.erase(it); - } - } -} - -void SurfaceDependencyTracker::OnSurfaceDiscarded(Surface* surface) { - base::flat_set<FrameSinkId> removed_dependencies; - for (const SurfaceId& surface_id : surface->activation_dependencies()) - removed_dependencies.insert(surface_id.frame_sink_id()); - - OnSurfaceDependenciesChanged(surface, {}, removed_dependencies); - - // Pretend that the discarded surface's SurfaceId is now available to - // unblock dependencies because we now know the surface will never activate. - NotifySurfaceIdAvailable(surface->surface_id()); - OnSurfaceDependencyAdded(surface->surface_id()); -} - -void SurfaceDependencyTracker::OnFrameSinkInvalidated( - const FrameSinkId& frame_sink_id) { - // We now know the frame sink will never generated any more frames, - // thus unblock all dependencies to any future surfaces. - NotifySurfaceIdAvailable(SurfaceId::MaxSequenceId(frame_sink_id)); - OnSurfaceDependencyAdded(SurfaceId::MaxSequenceId(frame_sink_id)); -} - -void SurfaceDependencyTracker::NotifySurfaceIdAvailable( - const SurfaceId& surface_id) { - auto it = blocked_surfaces_from_dependency_.find(surface_id.frame_sink_id()); - if (it == blocked_surfaces_from_dependency_.end()) - return; - - // Unblock surfaces that depend on this |surface_id|. - base::flat_set<SurfaceId> blocked_surfaces_by_id(it->second); - - // Tell each surface about the availability of its blocker. - for (const SurfaceId& blocked_surface_by_id : blocked_surfaces_by_id) { - Surface* blocked_surface = - surface_manager_->GetSurfaceForId(blocked_surface_by_id); - if (!blocked_surface) { - // A blocked surface may have been garbage collected during dependency - // resolution. - continue; - } - blocked_surface->NotifySurfaceIdAvailable(surface_id); - } -} - -} // namespace viz
diff --git a/components/viz/service/surfaces/surface_dependency_tracker.h b/components/viz/service/surfaces/surface_dependency_tracker.h deleted file mode 100644 index eacb163..0000000 --- a/components/viz/service/surfaces/surface_dependency_tracker.h +++ /dev/null
@@ -1,76 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_DEPENDENCY_TRACKER_H_ -#define COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_DEPENDENCY_TRACKER_H_ - -#include "components/viz/service/surfaces/surface.h" -#include "components/viz/service/viz_service_export.h" - -namespace viz { - -class SurfaceManager; - -// SurfaceDependencyTracker tracks unresolved dependencies blocking -// CompositorFrames from activating. This class maintains a map from -// a dependent surface ID to a set of Surfaces that have CompositorFrames -// blocked on that surface ID. SurfaceDependencyTracker observes when -// dependent frames activate, and informs blocked surfaces. -// -// When a blocking CompositorFrame is first submitted, -// SurfaceDependencyTracker will begin listening for BeginFrames, setting a -// deadline some number of BeginFrames in the future. If there are unresolved -// dependencies when the deadline hits, then SurfaceDependencyTracker will clear -// then and activate all pending CompositorFrames. Once there are no more -// remaining pending frames, then SurfaceDependencyTracker will stop observing -// BeginFrames. -class VIZ_SERVICE_EXPORT SurfaceDependencyTracker { - public: - explicit SurfaceDependencyTracker(SurfaceManager* surface_manager); - ~SurfaceDependencyTracker(); - - // Called when |surface| wishes to track when it is embedded. - void TrackEmbedding(Surface* surface); - - // Called when |surface| has a pending CompositorFrame and it wishes to be - // informed when that surface's dependencies are resolved. - void RequestSurfaceResolution(Surface* surface); - - // Returns whether the dependency tracker has a surface blocked on the - // provided |frame_sink_id|. - bool HasSurfaceBlockedOn(const FrameSinkId& frame_sink_id) const; - - void OnSurfaceActivated(Surface* surface); - void OnSurfaceDependencyAdded(const SurfaceId& surface_id); - void OnSurfaceDependenciesChanged( - Surface* surface, - const base::flat_set<FrameSinkId>& added_dependencies, - const base::flat_set<FrameSinkId>& removed_dependencies); - void OnSurfaceDiscarded(Surface* surface); - void OnFrameSinkInvalidated(const FrameSinkId& frame_sink_id); - - private: - // Informs all Surfaces with pending frames blocked on the provided - // |surface_id| that there is now an active frame available in Surface - // corresponding to |surface_id|. - void NotifySurfaceIdAvailable(const SurfaceId& surface_id); - - SurfaceManager* const surface_manager_; - - // A map from a FrameSinkId to the set of Surfaces that are blocked on - // surfaces associated with that FrameSinkId. - std::unordered_map<FrameSinkId, base::flat_set<SurfaceId>, FrameSinkIdHash> - blocked_surfaces_from_dependency_; - - // A map from a FrameSinkid to a set of surfaces with that FrameSinkId that - // are blocked on a parent arriving to embed them. - std::unordered_map<FrameSinkId, base::flat_set<SurfaceId>, FrameSinkIdHash> - surfaces_blocked_on_parent_by_frame_sink_id_; - - DISALLOW_COPY_AND_ASSIGN(SurfaceDependencyTracker); -}; - -} // namespace viz - -#endif // COMPONENTS_VIZ_SERVICE_SURFACES_SURFACE_DEPENDENCY_TRACKER_H_
diff --git a/components/viz/service/surfaces/surface_manager.cc b/components/viz/service/surfaces/surface_manager.cc index b6c4318..0c522bf 100644 --- a/components/viz/service/surfaces/surface_manager.cc +++ b/components/viz/service/surfaces/surface_manager.cc
@@ -47,7 +47,6 @@ base::Optional<uint32_t> activation_deadline_in_frames) : delegate_(delegate), activation_deadline_in_frames_(activation_deadline_in_frames), - dependency_tracker_(this), root_surface_id_(FrameSinkId(0u, 0u), LocalSurfaceId(1u, base::UnguessableToken::Create())), tick_clock_(base::DefaultTickClock::GetInstance()), @@ -150,8 +149,12 @@ } void SurfaceManager::InvalidateFrameSinkId(const FrameSinkId& frame_sink_id) { - dependency_tracker_.OnFrameSinkInvalidated(frame_sink_id); - + auto it = frame_sink_id_to_allocation_groups_.find(frame_sink_id); + if (it != frame_sink_id_to_allocation_groups_.end()) { + for (SurfaceAllocationGroup* group : it->second) { + group->WillNotRegisterNewSurfaces(); + } + } GarbageCollectSurfaces(); } @@ -487,26 +490,11 @@ for (auto& observer : observer_list_) observer.OnSurfaceActivated(surface->surface_id(), duration); - - dependency_tracker_.OnSurfaceActivated(surface); -} - -void SurfaceManager::SurfaceDependencyAdded(const SurfaceId& surface_id) { - dependency_tracker_.OnSurfaceDependencyAdded(surface_id); -} - -void SurfaceManager::SurfaceDependenciesChanged( - Surface* surface, - const base::flat_set<FrameSinkId>& added_dependencies, - const base::flat_set<FrameSinkId>& removed_dependencies) { - dependency_tracker_.OnSurfaceDependenciesChanged(surface, added_dependencies, - removed_dependencies); } void SurfaceManager::SurfaceDestroyed(Surface* surface) { for (auto& observer : observer_list_) observer.OnSurfaceDestroyed(surface->surface_id()); - dependency_tracker_.OnSurfaceDiscarded(surface); } void SurfaceManager::SurfaceDamageExpected(const SurfaceId& surface_id, @@ -591,6 +579,8 @@ allocation_group = std::make_unique<SurfaceAllocationGroup>( this, surface_id.frame_sink_id(), surface_id.local_surface_id().embed_token()); + frame_sink_id_to_allocation_groups_[surface_id.frame_sink_id()].push_back( + allocation_group.get()); } return allocation_group.get(); } @@ -617,8 +607,30 @@ if (!allocation_groups_need_garbage_collection_) return; - base::EraseIf(embed_token_to_allocation_group_, - [](auto& entry) { return entry.second->IsReadyToDestroy(); }); + bool did_destroy = false; + for (auto it = embed_token_to_allocation_group_.begin(); + it != embed_token_to_allocation_group_.end(); ++it) { + if (!it->second->IsReadyToDestroy()) + continue; + // Before destroying the allocation group, remove it from + // |frame_sink_id_to_allocation_groups_|. + auto list_it = frame_sink_id_to_allocation_groups_.find( + it->second->submitter_frame_sink_id()); + DCHECK(list_it != frame_sink_id_to_allocation_groups_.end()); + base::Erase(list_it->second, it->second.get()); + if (list_it->second.empty()) + frame_sink_id_to_allocation_groups_.erase(list_it); + // Destroy the allocation group. Removing it from the map is done in a + // separate pass to avoid invalidating the iterator. + it->second.reset(); + did_destroy = true; + } + + // Remove the destroyed allocation groups from the map. + if (did_destroy) { + base::EraseIf(embed_token_to_allocation_group_, + [](auto& entry) { return !entry.second; }); + } allocation_groups_need_garbage_collection_ = false; }
diff --git a/components/viz/service/surfaces/surface_manager.h b/components/viz/service/surfaces/surface_manager.h index f8e4b534..1635548 100644 --- a/components/viz/service/surfaces/surface_manager.h +++ b/components/viz/service/surfaces/surface_manager.h
@@ -23,7 +23,6 @@ #include "base/timer/timer.h" #include "components/viz/common/surfaces/frame_sink_id.h" #include "components/viz/common/surfaces/surface_id.h" -#include "components/viz/service/surfaces/surface_dependency_tracker.h" #include "components/viz/service/surfaces/surface_observer.h" #include "components/viz/service/surfaces/surface_reference.h" @@ -38,9 +37,12 @@ namespace viz { +class BeginFrameSource; class Surface; class SurfaceAllocationGroup; +class SurfaceClient; class SurfaceManagerDelegate; +class SurfaceRange; struct BeginFrameAck; struct BeginFrameArgs; @@ -65,10 +67,6 @@ return activation_deadline_in_frames_; } - SurfaceDependencyTracker* dependency_tracker() { - return &dependency_tracker_; - } - // Sets an alternative base::TickClock to pass into surfaces for surface // synchronization deadlines. This allows unit tests to mock the wall clock. void SetTickClockForTesting(const base::TickClock* tick_clock); @@ -117,17 +115,6 @@ void SurfaceActivated(Surface* surface, base::Optional<base::TimeDelta> duration); - // Called when this |surface_id| is referenced as an activation dependency - // from a parent CompositorFrame. - void SurfaceDependencyAdded(const SurfaceId& surface_id); - - // Called when the dependencies of a pending CompositorFrame within |surface| - // has changed. - void SurfaceDependenciesChanged( - Surface* surface, - const base::flat_set<FrameSinkId>& added_dependencies, - const base::flat_set<FrameSinkId>& removed_dependencies); - // Called when |surface| is being destroyed. void SurfaceDestroyed(Surface* surface); @@ -284,10 +271,11 @@ base::Optional<uint32_t> activation_deadline_in_frames_; - // SurfaceDependencyTracker needs to be destroyed after Surfaces are destroyed - // because they will call back into the dependency tracker. - SurfaceDependencyTracker dependency_tracker_; - + base::flat_map<base::UnguessableToken, + std::unique_ptr<SurfaceAllocationGroup>> + embed_token_to_allocation_group_; + base::flat_map<FrameSinkId, std::vector<SurfaceAllocationGroup*>> + frame_sink_id_to_allocation_groups_; base::flat_map<SurfaceId, std::unique_ptr<Surface>> surface_map_; base::ObserverList<SurfaceObserver>::Unchecked observer_list_; base::ThreadChecker thread_checker_; @@ -332,10 +320,6 @@ // are temporary references. Also the timer isn't used with Android WebView. base::Optional<base::RepeatingTimer> expire_timer_; - base::flat_map<base::UnguessableToken, - std::unique_ptr<SurfaceAllocationGroup>> - embed_token_to_allocation_group_; - bool allocation_groups_need_garbage_collection_ = false; base::WeakPtrFactory<SurfaceManager> weak_factory_;
diff --git a/components/viz/service/surfaces/surface_unittest.cc b/components/viz/service/surfaces/surface_unittest.cc index 579d055..122abfbb 100644 --- a/components/viz/service/surfaces/surface_unittest.cc +++ b/components/viz/service/surfaces/surface_unittest.cc
@@ -10,7 +10,6 @@ #include "components/viz/service/display_embedder/server_shared_bitmap_manager.h" #include "components/viz/service/frame_sinks/compositor_frame_sink_support.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" -#include "components/viz/service/surfaces/surface_dependency_tracker.h" #include "components/viz/test/begin_frame_args_test.h" #include "components/viz/test/compositor_frame_helpers.h" #include "components/viz/test/fake_external_begin_frame_source.h"
diff --git a/content/browser/accessibility/accessibility_event_recorder_auralinux.cc b/content/browser/accessibility/accessibility_event_recorder_auralinux.cc index 8683b72..24c83f29 100644 --- a/content/browser/accessibility/accessibility_event_recorder_auralinux.cc +++ b/content/browser/accessibility/accessibility_event_recorder_auralinux.cc
@@ -152,6 +152,8 @@ AddATKEventListener("ATK:AtkObject:state-change"); AddATKEventListener("ATK:AtkObject:focus-event"); AddATKEventListener("ATK:AtkObject:property-change"); + AddATKEventListener("ATK:AtkText:text-insert"); + AddATKEventListener("ATK:AtkText:text-remove"); AddATKEventListener("ATK:AtkSelection:selection-changed"); } @@ -190,8 +192,9 @@ return; } + std::string event_name(event); std::string log; - if (std::string(event).find("property-change") != std::string::npos) { + if (event_name.find("property-change") != std::string::npos) { DCHECK_GE(n_params, 2u); AtkPropertyValues* property_values = static_cast<AtkPropertyValues*>(g_value_get_pointer(¶ms[1])); @@ -213,9 +216,20 @@ } } else { log += base::ToUpperASCII(event); - if (std::string(event).find("state-change") != std::string::npos) { - log += ":" + base::ToUpperASCII(g_value_get_string(¶ms[1])); - log += base::StringPrintf(":%s", g_strdup_value_contents(¶ms[2])); + if (event_name.find("state-change") != std::string::npos) { + std::string state_type = g_value_get_string(¶ms[1]); + log += ":" + base::ToUpperASCII(state_type); + + gchar* parameter = g_strdup_value_contents(¶ms[2]); + log += base::StringPrintf(":%s", parameter); + g_free(parameter); + + } else if (event_name.find("text-insert") != std::string::npos || + event_name.find("text-remove") != std::string::npos) { + DCHECK_GE(n_params, 4u); + log += base::StringPrintf( + " (start=%i length=%i '%s')", g_value_get_int(¶ms[1]), + g_value_get_int(¶ms[2]), g_value_get_string(¶ms[3])); } }
diff --git a/content/browser/accessibility/dump_accessibility_events_browsertest.cc b/content/browser/accessibility/dump_accessibility_events_browsertest.cc index 1217bae..8531dfe 100644 --- a/content/browser/accessibility/dump_accessibility_events_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_events_browsertest.cc
@@ -574,6 +574,11 @@ } IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest, + AccessibilityEventsTextChangedContentEditable) { + RunEventTest(FILE_PATH_LITERAL("text-changed-contenteditable.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityEventsTest, AccessibilityEventsAriaCheckedChanged) { RunEventTest(FILE_PATH_LITERAL("aria-checked-changed.html")); }
diff --git a/content/browser/browser_main_loop.cc b/content/browser/browser_main_loop.cc index 22560099..9168181a 100644 --- a/content/browser/browser_main_loop.cc +++ b/content/browser/browser_main_loop.cc
@@ -517,6 +517,17 @@ #if defined(OS_ANDROID) bool g_browser_main_loop_shutting_down = false; + +namespace { +// Whether or not BrowserMainLoop::CreateStartupTasks() posts any tasks. +bool g_post_startup_tasks = true; +} // namespace + +// static +void BrowserMainLoop::EnableStartupTasks(bool enabled) { + g_post_startup_tasks = enabled; +} + #endif // BrowserMainLoop construction / destruction ============================= @@ -873,9 +884,15 @@ DCHECK(!startup_task_runner_); #if defined(OS_ANDROID) + // Some java scheduler tests need to test migration to C++, but the browser + // environment isn't set up fully and if these tasks run they may crash. + if (!g_post_startup_tasks) + return; + startup_task_runner_ = std::make_unique<StartupTaskRunner>( base::BindOnce(&BrowserStartupComplete), - base::ThreadTaskRunnerHandle::Get()); + base::CreateSingleThreadTaskRunnerWithTraits( + {BrowserThread::UI, BrowserTaskType::kBootstrap})); #else startup_task_runner_ = std::make_unique<StartupTaskRunner>( base::OnceCallback<void(int)>(), base::ThreadTaskRunnerHandle::Get());
diff --git a/content/browser/browser_main_loop.h b/content/browser/browser_main_loop.h index febdcd0..24cca0cf 100644 --- a/content/browser/browser_main_loop.h +++ b/content/browser/browser_main_loop.h
@@ -212,6 +212,12 @@ #if defined(OS_ANDROID) void SynchronouslyFlushStartupTasks(); + + // |enabled| Whether or not CreateStartupTasks() posts any tasks. This is + // useful because some javatests want to test native task posting without the + // whole browser loaded. In that scenario tasks posted by CreateStartupTasks() + // may crash if run. + static void EnableStartupTasks(bool enabled); #endif // OS_ANDROID #if !defined(OS_ANDROID)
diff --git a/content/browser/frame_host/navigation_handle_impl.cc b/content/browser/frame_host/navigation_handle_impl.cc index acd158e..f0107bb 100644 --- a/content/browser/frame_host/navigation_handle_impl.cc +++ b/content/browser/frame_host/navigation_handle_impl.cc
@@ -123,7 +123,6 @@ NavigationRequest* navigation_request, const std::vector<GURL>& redirect_chain, int pending_nav_entry_id, - std::unique_ptr<NavigationUIData> navigation_ui_data, net::HttpRequestHeaders request_headers, const Referrer& sanitized_referrer) : navigation_request_(navigation_request), @@ -134,14 +133,12 @@ subframe_entry_committed_(false), request_headers_(std::move(request_headers)), pending_nav_entry_id_(pending_nav_entry_id), - navigation_ui_data_(std::move(navigation_ui_data)), navigation_id_(CreateUniqueHandleID()), redirect_chain_(redirect_chain), reload_type_(ReloadType::NONE), restore_type_(RestoreType::NONE), navigation_type_(NAVIGATION_TYPE_UNKNOWN), is_same_process_(true), - throttle_runner_(this, this), weak_factory_(this) { const GURL& url = navigation_request_->common_params().url; TRACE_EVENT_ASYNC_BEGIN2("navigation", "NavigationHandle", this, @@ -192,8 +189,6 @@ navigation_handle_proxy_ = std::make_unique<NavigationHandleProxy>(this); #endif - GetDelegate()->DidStartNavigation(this); - if (IsInMainFrame()) { TRACE_EVENT_ASYNC_BEGIN_WITH_TIMESTAMP1( "navigation", "Navigation StartToCommit", this, @@ -303,7 +298,7 @@ } const NavigationUIData* NavigationHandleImpl::GetNavigationUIData() { - return navigation_ui_data_.get(); + return navigation_request_->navigation_ui_data(); } bool NavigationHandleImpl::IsExternalProtocol() { @@ -409,26 +404,10 @@ : net::IPEndPoint(); } -void NavigationHandleImpl::Resume(NavigationThrottle* resuming_throttle) { - DCHECK(resuming_throttle); - TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this, - "Resume"); - throttle_runner_.ResumeProcessingNavigationEvent(resuming_throttle); - // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted - // by the previous call. -} - -void NavigationHandleImpl::CancelDeferredNavigation( - NavigationThrottle* cancelling_throttle, - NavigationThrottle::ThrottleCheckResult result) { - DCHECK(cancelling_throttle); - DCHECK_EQ(cancelling_throttle, throttle_runner_.GetDeferringThrottle()); - CancelDeferredNavigationInternal(result); -} - void NavigationHandleImpl::RegisterThrottleForTesting( std::unique_ptr<NavigationThrottle> navigation_throttle) { - throttle_runner_.AddThrottle(std::move(navigation_throttle)); + navigation_request_->RegisterThrottleForTesting( + std::move(navigation_throttle)); } #if defined(OS_ANDROID) @@ -439,7 +418,7 @@ #endif bool NavigationHandleImpl::IsDeferredForTesting() { - return throttle_runner_.GetDeferringThrottle() != nullptr; + return navigation_request_->IsDeferredForTesting(); } bool NavigationHandleImpl::WasStartedFromContextMenu() const { @@ -497,7 +476,7 @@ } void NavigationHandleImpl::CallResumeForTesting() { - throttle_runner_.CallResumeForTesting(); + navigation_request_->CallResumeForTesting(); } const base::Optional<url::Origin>& NavigationHandleImpl::GetInitiatorOrigin() { @@ -550,41 +529,6 @@ return std::move(appcache_handle_); } -void NavigationHandleImpl::WillStartRequest( - ThrottleChecksFinishedCallback callback) { - TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this, - "WillStartRequest"); - // WillStartRequest should only be called once. - if (state() != NavigationRequest::INITIAL) { - navigation_request_->set_handle_state(NavigationRequest::CANCELING); - RunCompleteCallback(NavigationThrottle::CANCEL); - return; - } - - navigation_request_->set_handle_state( - NavigationRequest::PROCESSING_WILL_START_REQUEST); - complete_callback_ = std::move(callback); - - if (IsSelfReferentialURL()) { - navigation_request_->set_handle_state(NavigationRequest::CANCELING); - RunCompleteCallback(NavigationThrottle::CANCEL); - return; - } - - throttle_runner_.RegisterNavigationThrottles(); - - // If the content/ embedder did not pass the NavigationUIData at the beginning - // of the navigation, ask for it now. - if (!navigation_ui_data_) - navigation_ui_data_ = GetDelegate()->GetNavigationUIData(this); - - // Notify each throttle of the request. - throttle_runner_.ProcessNavigationEvent( - NavigationThrottleRunner::Event::WillStartRequest); - // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted - // by the previous call. -} - void NavigationHandleImpl::UpdateStateFollowingRedirect( const GURL& new_referrer_url, ThrottleChecksFinishedCallback callback) { @@ -607,62 +551,12 @@ navigation_request_->set_handle_state( NavigationRequest::PROCESSING_WILL_REDIRECT_REQUEST); - complete_callback_ = std::move(callback); -} -void NavigationHandleImpl::WillRedirectRequest( - const GURL& new_referrer_url, - RenderProcessHost* post_redirect_process, - ThrottleChecksFinishedCallback callback) { - TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationHandle", this, - "WillRedirectRequest", "url", - GetURL().possibly_invalid_spec()); - UpdateStateFollowingRedirect(new_referrer_url, std::move(callback)); - navigation_request_->UpdateSiteURL(post_redirect_process); - - if (IsSelfReferentialURL()) { - navigation_request_->set_handle_state(NavigationRequest::CANCELING); - RunCompleteCallback(NavigationThrottle::CANCEL); - return; - } - - // Notify each throttle of the request. - throttle_runner_.ProcessNavigationEvent( - NavigationThrottleRunner::Event::WillRedirectRequest); - // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted - // by the previous call. -} - -void NavigationHandleImpl::WillFailRequest( - ThrottleChecksFinishedCallback callback) { - TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this, - "WillFailRequest"); +#if defined(OS_ANDROID) + navigation_handle_proxy_->DidRedirect(); +#endif complete_callback_ = std::move(callback); - navigation_request_->set_handle_state( - NavigationRequest::PROCESSING_WILL_FAIL_REQUEST); - - // Notify each throttle of the request. - throttle_runner_.ProcessNavigationEvent( - NavigationThrottleRunner::Event::WillFailRequest); - // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted - // by the previous call. -} - -void NavigationHandleImpl::WillProcessResponse( - ThrottleChecksFinishedCallback callback) { - TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this, - "WillProcessResponse"); - - navigation_request_->set_handle_state( - NavigationRequest::PROCESSING_WILL_PROCESS_RESPONSE); - complete_callback_ = std::move(callback); - - // Notify each throttle of the response. - throttle_runner_.ProcessNavigationEvent( - NavigationThrottleRunner::Event::WillProcessResponse); - // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted - // by the previous call. } void NavigationHandleImpl::ReadyToCommitNavigation(bool is_error) { @@ -814,115 +708,6 @@ } } -void NavigationHandleImpl::OnNavigationEventProcessed( - NavigationThrottleRunner::Event event, - NavigationThrottle::ThrottleCheckResult result) { - DCHECK_NE(NavigationThrottle::DEFER, result.action()); - switch (event) { - case NavigationThrottleRunner::Event::WillStartRequest: - OnWillStartRequestProcessed(result); - return; - case NavigationThrottleRunner::Event::WillRedirectRequest: - OnWillRedirectRequestProcessed(result); - return; - case NavigationThrottleRunner::Event::WillFailRequest: - OnWillFailRequestProcessed(result); - return; - case NavigationThrottleRunner::Event::WillProcessResponse: - OnWillProcessResponseProcessed(result); - return; - default: - NOTREACHED(); - } - NOTREACHED(); -} - -void NavigationHandleImpl::OnWillStartRequestProcessed( - NavigationThrottle::ThrottleCheckResult result) { - DCHECK_EQ(NavigationRequest::PROCESSING_WILL_START_REQUEST, state()); - DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action()); - if (result.action() == NavigationThrottle::PROCEED) { - navigation_request_->set_handle_state( - NavigationRequest::WILL_START_REQUEST); - } else { - navigation_request_->set_handle_state(NavigationRequest::CANCELING); - } - RunCompleteCallback(result); -} - -void NavigationHandleImpl::OnWillRedirectRequestProcessed( - NavigationThrottle::ThrottleCheckResult result) { - DCHECK_EQ(NavigationRequest::PROCESSING_WILL_REDIRECT_REQUEST, state()); - DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action()); - if (result.action() == NavigationThrottle::PROCEED) { - navigation_request_->set_handle_state( - NavigationRequest::WILL_REDIRECT_REQUEST); - -#if defined(OS_ANDROID) - navigation_handle_proxy_->DidRedirect(); -#endif - - // Notify the delegate that a redirect was encountered and will be followed. - if (GetDelegate()) - GetDelegate()->DidRedirectNavigation(this); - } else { - navigation_request_->set_handle_state(NavigationRequest::CANCELING); - } - RunCompleteCallback(result); -} - -void NavigationHandleImpl::OnWillFailRequestProcessed( - NavigationThrottle::ThrottleCheckResult result) { - DCHECK_EQ(NavigationRequest::PROCESSING_WILL_FAIL_REQUEST, state()); - DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action()); - if (result.action() == NavigationThrottle::PROCEED) { - navigation_request_->set_handle_state(NavigationRequest::WILL_FAIL_REQUEST); - result = NavigationThrottle::ThrottleCheckResult( - NavigationThrottle::PROCEED, net_error_code_); - } else { - navigation_request_->set_handle_state(NavigationRequest::CANCELING); - } - RunCompleteCallback(result); -} - -void NavigationHandleImpl::OnWillProcessResponseProcessed( - NavigationThrottle::ThrottleCheckResult result) { - DCHECK_EQ(NavigationRequest::PROCESSING_WILL_PROCESS_RESPONSE, state()); - DCHECK_NE(NavigationThrottle::BLOCK_REQUEST, result.action()); - DCHECK_NE(NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE, result.action()); - if (result.action() == NavigationThrottle::PROCEED) { - navigation_request_->set_handle_state( - NavigationRequest::WILL_PROCESS_RESPONSE); - // If the navigation is done processing the response, then it's ready to - // commit. Inform observers that the navigation is now ready to commit, - // unless it is not set to commit (204/205s/downloads). - if (GetRenderFrameHost()) - ReadyToCommitNavigation(false); - } else { - navigation_request_->set_handle_state(NavigationRequest::CANCELING); - } - RunCompleteCallback(result); -} - -void NavigationHandleImpl::CancelDeferredNavigationInternal( - NavigationThrottle::ThrottleCheckResult result) { - DCHECK(state() == NavigationRequest::PROCESSING_WILL_START_REQUEST || - state() == NavigationRequest::PROCESSING_WILL_REDIRECT_REQUEST || - state() == NavigationRequest::PROCESSING_WILL_FAIL_REQUEST || - state() == NavigationRequest::PROCESSING_WILL_PROCESS_RESPONSE); - DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE || - result.action() == NavigationThrottle::CANCEL || - result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE); - DCHECK(result.action() != NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE || - state() == NavigationRequest::PROCESSING_WILL_START_REQUEST || - state() == NavigationRequest::PROCESSING_WILL_REDIRECT_REQUEST); - - TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationHandle", this, - "CancelDeferredNavigation"); - navigation_request_->set_handle_state(NavigationRequest::CANCELING); - RunCompleteCallback(result); -} - void NavigationHandleImpl::RunCompleteCallback( NavigationThrottle::ThrottleCheckResult result) { DCHECK(result.action() != NavigationThrottle::DEFER); @@ -940,37 +725,6 @@ // destruction. } -bool NavigationHandleImpl::IsSelfReferentialURL() { - // about: URLs should be exempted since they are reserved for other purposes - // and cannot be the source of infinite recursion. See - // https://crbug.com/341858 . - if (GetURL().SchemeIs("about")) - return false; - - // Browser-triggered navigations should be exempted. - if (navigation_request_->browser_initiated()) - return false; - - // Some sites rely on constructing frame hierarchies where frames are loaded - // via POSTs with the same URLs, so exempt POST requests. See - // https://crbug.com/710008. - if (navigation_request_->common_params().method == "POST") - return false; - - // We allow one level of self-reference because some sites depend on that, - // but we don't allow more than one. - bool found_self_reference = false; - for (const FrameTreeNode* node = frame_tree_node()->parent(); node; - node = node->parent()) { - if (node->current_url().EqualsIgnoringRef(GetURL())) { - if (found_self_reference) - return true; - found_self_reference = true; - } - } - return false; -} - void NavigationHandleImpl::RenderProcessBlockedStateChanged(bool blocked) { if (blocked) StopCommitTimeout();
diff --git a/content/browser/frame_host/navigation_handle_impl.h b/content/browser/frame_host/navigation_handle_impl.h index e0639d4..5536a028 100644 --- a/content/browser/frame_host/navigation_handle_impl.h +++ b/content/browser/frame_host/navigation_handle_impl.h
@@ -59,8 +59,7 @@ // NavigationHandleImpl ownership is then transferred to the RenderFrameHost in // which the navigation will commit. It is finaly destroyed when the navigation // commits. -class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle, - NavigationThrottleRunner::Delegate { +class CONTENT_EXPORT NavigationHandleImpl : public NavigationHandle { public: ~NavigationHandleImpl() override; @@ -127,14 +126,6 @@ const std::string& GetOriginPolicy() const; - // Resume and CancelDeferredNavigation must only be called by the - // NavigationThrottle that is currently deferring the navigation. - // |resuming_throttle| and |cancelling_throttle| are the throttles calling - // these methods. - void Resume(NavigationThrottle* resuming_throttle); - void CancelDeferredNavigation(NavigationThrottle* cancelling_throttle, - NavigationThrottle::ThrottleCheckResult result); - // Simulates the navigation resuming. Most callers should just let the // deferring NavigationThrottle do the resuming. void CallResumeForTesting(); @@ -201,46 +192,12 @@ typedef base::OnceCallback<void(NavigationThrottle::ThrottleCheckResult)> ThrottleChecksFinishedCallback; - // Called when the URLRequest will start in the network stack. |callback| - // will be called when all throttle checks have completed. This will allow - // the caller to cancel the navigation or let it proceed. - void WillStartRequest(ThrottleChecksFinishedCallback callback); - // Updates the state of the navigation handle after encountering a server // redirect. void UpdateStateFollowingRedirect( const GURL& new_referrer_url, ThrottleChecksFinishedCallback callback); - // Called when the URLRequest will be redirected in the network stack. - // |callback| will be called when all throttles check have completed. This - // will allow the caller to cancel the navigation or let it proceed. - // This will also inform the delegate that the request was redirected. - // - // |post_redirect_process| is the renderer process we expect to - // use to commit the navigation now that it has been redirected. It can be - // null if there is no live process that can be used. In that case, a suitable - // renderer process will be created at commit time. - void WillRedirectRequest( - const GURL& new_referrer_url, - RenderProcessHost* post_redirect_process, - ThrottleChecksFinishedCallback callback); - - // Called when the URLRequest will fail. |callback| will be - // called when all throttles check have completed. This will allow the caller - // to explicitly cancel the navigation (with a custom error code and/or - // custom error page HTML) or let the failure proceed as normal. - void WillFailRequest(ThrottleChecksFinishedCallback callback); - - // Called when the URLRequest has delivered response headers and metadata. - // |callback| will be called when all throttle checks have completed, - // allowing the caller to cancel the navigation or let it proceed. - // NavigationHandle will not call |callback| with a result of DEFER. - // If the result is PROCEED, then 'ReadyToCommitNavigation' will be called - // just before calling |callback|. - void WillProcessResponse( - ThrottleChecksFinishedCallback callback); - // Returns the FrameTreeNode this navigation is happening in. FrameTreeNode* frame_tree_node() const { return navigation_request_->frame_tree_node(); @@ -270,7 +227,7 @@ } NavigationUIData* navigation_ui_data() const { - return navigation_ui_data_.get(); + return navigation_request_->navigation_ui_data(); } const GURL& base_url() { return base_url_; } @@ -312,7 +269,7 @@ } NavigationThrottle* GetDeferringThrottleForTesting() const { - return throttle_runner_.GetDeferringThrottle(); + return navigation_request_->GetDeferringThrottleForTesting(); } // Whether the navigation was sent to be committed in a renderer by the @@ -338,40 +295,21 @@ NavigationHandleImpl(NavigationRequest* navigation_request, const std::vector<GURL>& redirect_chain, int pending_nav_entry_id, - std::unique_ptr<NavigationUIData> navigation_ui_data, net::HttpRequestHeaders request_headers, const Referrer& sanitized_referrer); - // NavigationThrottleRunner::Delegate: - void OnNavigationEventProcessed( - NavigationThrottleRunner::Event event, - NavigationThrottle::ThrottleCheckResult result) override; - - void OnWillStartRequestProcessed( - NavigationThrottle::ThrottleCheckResult result); - void OnWillRedirectRequestProcessed( - NavigationThrottle::ThrottleCheckResult result); - void OnWillFailRequestProcessed( - NavigationThrottle::ThrottleCheckResult result); - void OnWillProcessResponseProcessed( - NavigationThrottle::ThrottleCheckResult result); - - void CancelDeferredNavigationInternal( - NavigationThrottle::ThrottleCheckResult result); - // Helper function to run and reset the |complete_callback_|. This marks the // end of a round of NavigationThrottleChecks. void RunCompleteCallback(NavigationThrottle::ThrottleCheckResult result); + void SetCompleteCallback(ThrottleChecksFinishedCallback callback) { + complete_callback_ = std::move(callback); + } + NavigationRequest::NavigationHandleState state() const { return navigation_request_->handle_state(); } - // Checks for attempts to navigate to a page that is already referenced more - // than once in the frame's ancestors. This is a helper function used by - // WillStartRequest and WillRedirectRequest to prevent the navigation. - bool IsSelfReferentialURL(); - // Called if READY_TO_COMMIT -> COMMIT state transition takes an unusually // long time. void OnCommitTimeout(); @@ -440,9 +378,6 @@ // Embedder data from the IO thread tied to this navigation. std::unique_ptr<NavigationData> navigation_data_; - // Embedder data from the UI thread tied to this navigation. - std::unique_ptr<NavigationUIData> navigation_ui_data_; - // The unique id to identify this to navigation with. int64_t navigation_id_; @@ -469,10 +404,6 @@ // TODO(clamy): Clean this up once the architecture of unit tests is better. scoped_refptr<net::HttpResponseHeaders> response_headers_for_testing_; - // Owns the NavigationThrottles associated with this navigation, and is - // responsible for notifying them about the various navigation events. - NavigationThrottleRunner throttle_runner_; - #if defined(OS_ANDROID) // For each C++ NavigationHandle, there is a Java counterpart. It is the JNI // bridge in between the two.
diff --git a/content/browser/frame_host/navigation_handle_impl_unittest.cc b/content/browser/frame_host/navigation_handle_impl_unittest.cc index d450671..2ad6c98 100644 --- a/content/browser/frame_host/navigation_handle_impl_unittest.cc +++ b/content/browser/frame_host/navigation_handle_impl_unittest.cc
@@ -77,11 +77,9 @@ RenderViewHostImplTestHarness::TearDown(); } - void Resume() { test_handle()->throttle_runner_.CallResumeForTesting(); } - void CancelDeferredNavigation( NavigationThrottle::ThrottleCheckResult result) { - test_handle()->CancelDeferredNavigationInternal(result); + request_->CancelDeferredNavigationInternal(result); } // Helper function to call WillStartRequest on |handle|. If this function @@ -93,7 +91,7 @@ // It's safe to use base::Unretained since the NavigationHandle is owned by // the NavigationHandleImplTest. - test_handle()->WillStartRequest( + request_->WillStartRequest( base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult, base::Unretained(this))); } @@ -109,7 +107,7 @@ // It's safe to use base::Unretained since the NavigationHandle is owned by // the NavigationHandleImplTest. - test_handle()->WillRedirectRequest( + request_->WillRedirectRequest( GURL(), nullptr, base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult, base::Unretained(this))); @@ -127,7 +125,7 @@ // It's safe to use base::Unretained since the NavigationHandle is owned by // the NavigationHandleImplTest. - test_handle()->WillFailRequest( + request_->WillFailRequest( base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult, base::Unretained(this))); } @@ -145,7 +143,7 @@ // by the NavigationHandleImplTest. The ConnectionInfo is different from // that sent to WillRedirectRequest to verify that it's correctly plumbed // in both cases. - test_handle()->WillProcessResponse( + request_->WillProcessResponse( base::Bind(&NavigationHandleImplTest::UpdateThrottleCheckResult, base::Unretained(this))); } @@ -220,6 +218,8 @@ return test_throttle; } + // TODO(zetamoo): Use NavigationSimulator instead of creating + // NavigationRequest and NavigationHandleImpl. void CreateNavigationHandle() { scoped_refptr<FrameNavigationEntry> frame_entry(new FrameNavigationEntry()); request_ = NavigationRequest::CreateBrowserInitiated(
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index ed9d688..28b2e1b 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -766,9 +766,8 @@ // the NavigationHandle where the callback will be stored. // TODO(clamy): pass the method to the NavigationHandle instead of a // boolean. - navigation_handle_->WillStartRequest( - base::Bind(&NavigationRequest::OnStartChecksComplete, - base::Unretained(this))); + WillStartRequest(base::Bind(&NavigationRequest::OnStartChecksComplete, + base::Unretained(this))); return; } @@ -832,8 +831,7 @@ handle_state_ = NavigationRequest::INITIAL; std::unique_ptr<NavigationHandleImpl> navigation_handle = base::WrapUnique(new NavigationHandleImpl( - this, redirect_chain, nav_entry_id_, std::move(navigation_ui_data_), - std::move(headers), + this, redirect_chain, nav_entry_id_, std::move(headers), Referrer::SanitizeForRequest(common_params_.url, common_params_.referrer))); @@ -844,6 +842,11 @@ } navigation_handle_ = std::move(navigation_handle); + + throttle_runner_ = base::WrapUnique( + new NavigationThrottleRunner(this, navigation_handle_.get())); + + GetDelegate()->DidStartNavigation(navigation_handle_.get()); } void NavigationRequest::ResetForCrossDocumentRestart() { @@ -1078,10 +1081,9 @@ // It's safe to use base::Unretained because this NavigationRequest owns the // NavigationHandle where the callback will be stored. - navigation_handle_->WillRedirectRequest( - common_params_.referrer.url, expected_process, - base::Bind(&NavigationRequest::OnRedirectChecksComplete, - base::Unretained(this))); + WillRedirectRequest(common_params_.referrer.url, expected_process, + base::Bind(&NavigationRequest::OnRedirectChecksComplete, + base::Unretained(this))); } void NavigationRequest::OnResponseStarted( @@ -1294,7 +1296,7 @@ } // Check if the navigation should be allowed to proceed. - navigation_handle_->WillProcessResponse( + WillProcessResponse( base::Bind(&NavigationRequest::OnWillProcessResponseChecksComplete, base::Unretained(this))); } @@ -1414,8 +1416,8 @@ CommitErrorPage(error_page_content); } else { // Check if the navigation should be allowed to proceed. - navigation_handle_->WillFailRequest(base::BindOnce( - &NavigationRequest::OnFailureChecksComplete, base::Unretained(this))); + WillFailRequest(base::BindOnce(&NavigationRequest::OnFailureChecksComplete, + base::Unretained(this))); } } @@ -2270,4 +2272,262 @@ rfh, blink::mojom::WebFeature::kDownloadPostPolicyCheck); } +void NavigationRequest::OnNavigationEventProcessed( + NavigationThrottleRunner::Event event, + NavigationThrottle::ThrottleCheckResult result) { + DCHECK_NE(NavigationThrottle::DEFER, result.action()); + switch (event) { + case NavigationThrottleRunner::Event::WillStartRequest: + OnWillStartRequestProcessed(result); + return; + case NavigationThrottleRunner::Event::WillRedirectRequest: + OnWillRedirectRequestProcessed(result); + return; + case NavigationThrottleRunner::Event::WillFailRequest: + OnWillFailRequestProcessed(result); + return; + case NavigationThrottleRunner::Event::WillProcessResponse: + OnWillProcessResponseProcessed(result); + return; + default: + NOTREACHED(); + } + NOTREACHED(); +} + +void NavigationRequest::OnWillStartRequestProcessed( + NavigationThrottle::ThrottleCheckResult result) { + DCHECK_EQ(PROCESSING_WILL_START_REQUEST, handle_state_); + DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action()); + if (result.action() == NavigationThrottle::PROCEED) + handle_state_ = WILL_START_REQUEST; + else + handle_state_ = CANCELING; + + // TODO(zetamoo): Remove CompleteCallback from NavigationHandleImpl, and call + // the NavigationRequest methods directly. + navigation_handle_->RunCompleteCallback(result); +} + +void NavigationRequest::OnWillRedirectRequestProcessed( + NavigationThrottle::ThrottleCheckResult result) { + DCHECK_EQ(PROCESSING_WILL_REDIRECT_REQUEST, handle_state_); + DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action()); + if (result.action() == NavigationThrottle::PROCEED) { + handle_state_ = WILL_REDIRECT_REQUEST; + + // Notify the delegate that a redirect was encountered and will be followed. + if (GetDelegate()) + GetDelegate()->DidRedirectNavigation(navigation_handle_.get()); + } else { + handle_state_ = NavigationRequest::CANCELING; + } + navigation_handle_->RunCompleteCallback(result); +} + +void NavigationRequest::OnWillFailRequestProcessed( + NavigationThrottle::ThrottleCheckResult result) { + DCHECK_EQ(NavigationRequest::PROCESSING_WILL_FAIL_REQUEST, handle_state_); + DCHECK_NE(NavigationThrottle::BLOCK_RESPONSE, result.action()); + if (result.action() == NavigationThrottle::PROCEED) { + handle_state_ = WILL_FAIL_REQUEST; + result = NavigationThrottle::ThrottleCheckResult( + NavigationThrottle::PROCEED, navigation_handle_->GetNetErrorCode()); + } else { + handle_state_ = CANCELING; + } + navigation_handle_->RunCompleteCallback(result); +} + +void NavigationRequest::OnWillProcessResponseProcessed( + NavigationThrottle::ThrottleCheckResult result) { + DCHECK_EQ(NavigationRequest::PROCESSING_WILL_PROCESS_RESPONSE, handle_state_); + DCHECK_NE(NavigationThrottle::BLOCK_REQUEST, result.action()); + DCHECK_NE(NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE, result.action()); + if (result.action() == NavigationThrottle::PROCEED) { + handle_state_ = WILL_PROCESS_RESPONSE; + // If the navigation is done processing the response, then it's ready to + // commit. Inform observers that the navigation is now ready to commit, + // unless it is not set to commit (204/205s/downloads). + if (render_frame_host_) + navigation_handle_->ReadyToCommitNavigation(false); + } else { + handle_state_ = NavigationRequest::CANCELING; + } + navigation_handle_->RunCompleteCallback(result); +} + +NavigatorDelegate* NavigationRequest::GetDelegate() const { + return frame_tree_node()->navigator()->GetDelegate(); +} + +void NavigationRequest::Resume(NavigationThrottle* resuming_throttle) { + DCHECK(resuming_throttle); + TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this, + "Resume"); + throttle_runner_->ResumeProcessingNavigationEvent(resuming_throttle); + // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted + // by the previous call. +} + +void NavigationRequest::CancelDeferredNavigation( + NavigationThrottle* cancelling_throttle, + NavigationThrottle::ThrottleCheckResult result) { + DCHECK(cancelling_throttle); + DCHECK_EQ(cancelling_throttle, throttle_runner_->GetDeferringThrottle()); + CancelDeferredNavigationInternal(result); +} + +void NavigationRequest::CallResumeForTesting() { + throttle_runner_->CallResumeForTesting(); +} + +void NavigationRequest::RegisterThrottleForTesting( + std::unique_ptr<NavigationThrottle> navigation_throttle) { + throttle_runner_->AddThrottle(std::move(navigation_throttle)); +} +bool NavigationRequest::IsDeferredForTesting() { + return throttle_runner_->GetDeferringThrottle() != nullptr; +} + +void NavigationRequest::CancelDeferredNavigationInternal( + NavigationThrottle::ThrottleCheckResult result) { + DCHECK(handle_state_ == PROCESSING_WILL_START_REQUEST || + handle_state_ == PROCESSING_WILL_REDIRECT_REQUEST || + handle_state_ == PROCESSING_WILL_FAIL_REQUEST || + handle_state_ == PROCESSING_WILL_PROCESS_RESPONSE); + DCHECK(result.action() == NavigationThrottle::CANCEL_AND_IGNORE || + result.action() == NavigationThrottle::CANCEL || + result.action() == NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE); + DCHECK(result.action() != NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE || + handle_state_ == PROCESSING_WILL_START_REQUEST || + handle_state_ == PROCESSING_WILL_REDIRECT_REQUEST); + + TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this, + "CancelDeferredNavigation"); + handle_state_ = NavigationRequest::CANCELING; + navigation_handle_->RunCompleteCallback(result); +} + +void NavigationRequest::WillStartRequest( + ThrottleChecksFinishedCallback callback) { + TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this, + "WillStartRequest"); + // WillStartRequest should only be called once. + if (handle_state_ != INITIAL) { + handle_state_ = CANCELING; + navigation_handle_->RunCompleteCallback(NavigationThrottle::CANCEL); + return; + } + + handle_state_ = PROCESSING_WILL_START_REQUEST; + navigation_handle_->SetCompleteCallback(std::move(callback)); + + if (IsSelfReferentialURL()) { + handle_state_ = CANCELING; + navigation_handle_->RunCompleteCallback(NavigationThrottle::CANCEL); + return; + } + + throttle_runner_->RegisterNavigationThrottles(); + + // If the content/ embedder did not pass the NavigationUIData at the beginning + // of the navigation, ask for it now. + if (!navigation_ui_data_) { + navigation_ui_data_ = + GetDelegate()->GetNavigationUIData(navigation_handle_.get()); + } + + // Notify each throttle of the request. + throttle_runner_->ProcessNavigationEvent( + NavigationThrottleRunner::Event::WillStartRequest); + // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted + // by the previous call. +} + +void NavigationRequest::WillRedirectRequest( + const GURL& new_referrer_url, + RenderProcessHost* post_redirect_process, + ThrottleChecksFinishedCallback callback) { + TRACE_EVENT_ASYNC_STEP_INTO1("navigation", "NavigationRequest", this, + "WillRedirectRequest", "url", + common_params_.url.possibly_invalid_spec()); + navigation_handle_->UpdateStateFollowingRedirect(new_referrer_url, + std::move(callback)); + UpdateSiteURL(post_redirect_process); + + if (IsSelfReferentialURL()) { + handle_state_ = CANCELING; + navigation_handle_->RunCompleteCallback(NavigationThrottle::CANCEL); + return; + } + + // Notify each throttle of the request. + throttle_runner_->ProcessNavigationEvent( + NavigationThrottleRunner::Event::WillRedirectRequest); + // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted + // by the previous call. +} + +void NavigationRequest::WillFailRequest( + ThrottleChecksFinishedCallback callback) { + TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this, + "WillFailRequest"); + + navigation_handle_->SetCompleteCallback(std::move(callback)); + handle_state_ = PROCESSING_WILL_FAIL_REQUEST; + + // Notify each throttle of the request. + throttle_runner_->ProcessNavigationEvent( + NavigationThrottleRunner::Event::WillFailRequest); + // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted + // by the previous call. +} + +void NavigationRequest::WillProcessResponse( + ThrottleChecksFinishedCallback callback) { + TRACE_EVENT_ASYNC_STEP_INTO0("navigation", "NavigationRequest", this, + "WillProcessResponse"); + + handle_state_ = PROCESSING_WILL_PROCESS_RESPONSE; + navigation_handle_->SetCompleteCallback(std::move(callback)); + + // Notify each throttle of the response. + throttle_runner_->ProcessNavigationEvent( + NavigationThrottleRunner::Event::WillProcessResponse); + // DO NOT ADD CODE AFTER THIS, as the NavigationHandle might have been deleted + // by the previous call. +} + +bool NavigationRequest::IsSelfReferentialURL() { + // about: URLs should be exempted since they are reserved for other purposes + // and cannot be the source of infinite recursion. + // See https://crbug.com/341858 . + if (common_params_.url.SchemeIs(url::kAboutScheme)) + return false; + + // Browser-triggered navigations should be exempted. + if (browser_initiated()) + return false; + + // Some sites rely on constructing frame hierarchies where frames are loaded + // via POSTs with the same URLs, so exempt POST requests. + // See https://crbug.com/710008. + if (common_params_.method == "POST") + return false; + + // We allow one level of self-reference because some sites depend on that, + // but we don't allow more than one. + bool found_self_reference = false; + for (const FrameTreeNode* node = frame_tree_node()->parent(); node; + node = node->parent()) { + if (node->current_url().EqualsIgnoringRef(common_params_.url)) { + if (found_self_reference) + return true; + found_self_reference = true; + } + } + return false; +} + } // namespace content
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index 0c2470c..0104f604 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -14,6 +14,7 @@ #include "base/optional.h" #include "base/strings/string_util.h" #include "content/browser/frame_host/navigation_entry_impl.h" +#include "content/browser/frame_host/navigation_throttle_runner.h" #include "content/browser/initiator_csp_context.h" #include "content/browser/loader/navigation_url_loader_delegate.h" #include "content/common/content_export.h" @@ -37,6 +38,7 @@ class NavigationURLLoader; class NavigationData; class NavigationUIData; +class NavigatorDelegate; class SiteInstanceImpl; struct SubresourceLoaderParams; @@ -45,7 +47,8 @@ // ResourceDispatcherHost (that lives on the IO thread). // TODO(clamy): Describe the interactions between the UI and IO thread during // the navigation following its refactoring. -class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate { +class CONTENT_EXPORT NavigationRequest : public NavigationURLLoaderDelegate, + NavigationThrottleRunner::Delegate { public: // Keeps track of the various stages of a NavigationRequest. enum NavigationState { @@ -314,7 +317,39 @@ NavigationHandleState handle_state() { return handle_state_; } + NavigationUIData* navigation_ui_data() const { + return navigation_ui_data_.get(); + } + + // Resume and CancelDeferredNavigation must only be called by the + // NavigationThrottle that is currently deferring the navigation. + // |resuming_throttle| and |cancelling_throttle| are the throttles calling + // these methods. + void Resume(NavigationThrottle* resuming_throttle); + void CancelDeferredNavigation(NavigationThrottle* cancelling_throttle, + NavigationThrottle::ThrottleCheckResult result); + + // Simulates the navigation resuming. Most callers should just let the + // deferring NavigationThrottle do the resuming. + void CallResumeForTesting(); + + void RegisterThrottleForTesting( + std::unique_ptr<NavigationThrottle> navigation_throttle); + + bool IsDeferredForTesting(); + + typedef base::OnceCallback<void(NavigationThrottle::ThrottleCheckResult)> + ThrottleChecksFinishedCallback; + + NavigationThrottle* GetDeferringThrottleForTesting() const { + return throttle_runner_->GetDeferringThrottle(); + } + private: + // TODO(clamy): Transform NavigationHandleImplTest into NavigationRequestTest + // once NavigationHandleImpl has become a wrapper around NavigationRequest. + friend class NavigationHandleImplTest; + NavigationRequest(FrameTreeNode* frame_tree_node, const CommonNavigationParams& common_params, mojom::BeginNavigationParamsPtr begin_params, @@ -478,6 +513,64 @@ // filtered by download_policy. void RecordDownloadUseCountersPostPolicyCheck(); + // NavigationThrottleRunner::Delegate: + void OnNavigationEventProcessed( + NavigationThrottleRunner::Event event, + NavigationThrottle::ThrottleCheckResult result) override; + + void OnWillStartRequestProcessed( + NavigationThrottle::ThrottleCheckResult result); + void OnWillRedirectRequestProcessed( + NavigationThrottle::ThrottleCheckResult result); + void OnWillFailRequestProcessed( + NavigationThrottle::ThrottleCheckResult result); + void OnWillProcessResponseProcessed( + NavigationThrottle::ThrottleCheckResult result); + + NavigatorDelegate* GetDelegate() const; + + void CancelDeferredNavigationInternal( + NavigationThrottle::ThrottleCheckResult result); + + // TODO(zetamoo): Remove the Will* methods and fold them into their callers. + + // Called when the URLRequest will start in the network stack. |callback| will + // be called when all throttle checks have completed. This will allow the + // caller to cancel the navigation or let it proceed. + void WillStartRequest(ThrottleChecksFinishedCallback callback); + + // Called when the URLRequest will be redirected in the network stack. + // |callback| will be called when all throttles check have completed. This + // will allow the caller to cancel the navigation or let it proceed. + // This will also inform the delegate that the request was redirected. + // + // |post_redirect_process| is the renderer process we expect to use to commit + // the navigation now that it has been redirected. It can be null if there is + // no live process that can be used. In that case, a suitable renderer process + // will be created at commit time. + void WillRedirectRequest(const GURL& new_referrer_url, + RenderProcessHost* post_redirect_process, + ThrottleChecksFinishedCallback callback); + + // Called when the URLRequest will fail. |callback| will be called when all + // throttles check have completed. This will allow the caller to explicitly + // cancel the navigation (with a custom error code and/or custom error page + // HTML) or let the failure proceed as normal. + void WillFailRequest(ThrottleChecksFinishedCallback callback); + + // Called when the URLRequest has delivered response headers and metadata. + // |callback| will be called when all throttle checks have completed, + // allowing the caller to cancel the navigation or let it proceed. + // NavigationHandle will not call |callback| with a result of DEFER. + // If the result is PROCEED, then 'ReadyToCommitNavigation' will be called + // just before calling |callback|. + void WillProcessResponse(ThrottleChecksFinishedCallback callback); + + // Checks for attempts to navigate to a page that is already referenced more + // than once in the frame's ancestors. This is a helper function used by + // WillStartRequest and WillRedirectRequest to prevent the navigation. + bool IsSelfReferentialURL(); + FrameTreeNode* frame_tree_node_; RenderFrameHostImpl* render_frame_host_ = nullptr; @@ -606,6 +699,10 @@ // TODO(zetamoo): Merge |handle_state_| with |state_|. NavigationHandleState handle_state_ = NOT_CREATED; + // Owns the NavigationThrottles associated with this navigation, and is + // responsible for notifying them about the various navigation events. + std::unique_ptr<NavigationThrottleRunner> throttle_runner_; + base::WeakPtrFactory<NavigationRequest> weak_factory_; DISALLOW_COPY_AND_ASSIGN(NavigationRequest);
diff --git a/content/browser/renderer_host/input/touch_action_filter.cc b/content/browser/renderer_host/input/touch_action_filter.cc index ed291227..ef2a97c 100644 --- a/content/browser/renderer_host/input/touch_action_filter.cc +++ b/content/browser/renderer_host/input/touch_action_filter.cc
@@ -138,11 +138,6 @@ touch_action = white_listed_touch_action_; } else { gesture_sequence_.append("B"); - static auto* crash_key = base::debug::AllocateCrashKeyString( - "scrollbegin-gestures", base::debug::CrashKeySize::Size256); - base::debug::SetCrashKeyString(crash_key, gesture_sequence_); - base::debug::DumpWithoutCrashing(); - gesture_sequence_.clear(); SetTouchAction(cc::kTouchActionAuto); touch_action = cc::kTouchActionAuto; }
diff --git a/content/browser/service_worker/embedded_worker_instance.cc b/content/browser/service_worker/embedded_worker_instance.cc index de48c61..a47da70 100644 --- a/content/browser/service_worker/embedded_worker_instance.cc +++ b/content/browser/service_worker/embedded_worker_instance.cc
@@ -111,7 +111,7 @@ // registering with DevTools. Called on the UI thread. Calls |callback| on the // IO thread. |context| and |weak_context| are only for passing to DevTools and // must not be dereferenced here on the UI thread. -// S13nServiceWorker: +// // This also sets up two URLLoaderFactoryBundles, one for // ServiceWorkerScriptLoaderFactory and the other is for passing to the // renderer. These bundles include factories for non-network URLs like
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h index c1e2129..1384ab8 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.h +++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -293,7 +293,6 @@ bool is_incognito() const { return is_incognito_; } - // S13nServiceWorker: // Used for starting a shared worker. Returns a provider host for the shared // worker and fills |out_provider_info| with info to send to the renderer to // connect to the host. The host stays alive as long as this info stays alive
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc index 7890ca4..51b693d9 100644 --- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc +++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
@@ -648,92 +648,7 @@ std::move(timing), version_); } -// Non-S13nServiceWorker bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload( - net::URLRequest* original_request, - base::OnceClosure on_response) { - if (resource_type_ != RESOURCE_TYPE_MAIN_FRAME && - resource_type_ != RESOURCE_TYPE_SUB_FRAME) { - return false; - } - if (!version_->navigation_preload_state().enabled) - return false; - // TODO(horo): Currently NavigationPreload doesn't support request body. - if (request_->blob) - return false; - - ResourceRequestInfoImpl* original_info = - ResourceRequestInfoImpl::ForRequest(original_request); - ResourceRequesterInfo* requester_info = original_info->requester_info(); - DCHECK(requester_info->IsBrowserSideNavigation()); - auto url_loader_factory = std::make_unique<URLLoaderFactoryImpl>( - ResourceRequesterInfo::CreateForNavigationPreload( - requester_info, - const_cast<net::URLRequestContext*>(original_request->context()))); - - network::ResourceRequest request; - request.method = original_request->method(); - request.url = original_request->url(); - request.site_for_cookies = original_request->site_for_cookies(); - request.request_initiator = - original_request->initiator().has_value() - ? original_request->initiator() - : url::Origin::Create(original_request->url()); - request.referrer = GURL(original_request->referrer()); - request.referrer_policy = - Referrer::ReferrerPolicyForUrlRequest(original_info->GetReferrerPolicy()); - request.is_prerendering = original_info->IsPrerendering(); - request.load_flags = original_request->load_flags(); - request.resource_type = RESOURCE_TYPE_NAVIGATION_PRELOAD; - request.priority = original_request->priority(); - request.skip_service_worker = true; - request.do_not_prompt_for_login = true; - request.render_frame_id = original_info->GetRenderFrameID(); - request.is_main_frame = original_info->IsMainFrame(); - request.enable_load_timing = original_info->is_load_timing_enabled(); - request.report_raw_headers = original_info->ShouldReportRawHeaders(); - request.throttling_profile_id = - network::ThrottlingController::GetProfileIDForNetLogSource( - original_request->net_log().source().id); - - DCHECK(net::HttpUtil::IsValidHeaderValue( - version_->navigation_preload_state().header)); - ServiceWorkerMetrics::RecordNavigationPreloadRequestHeaderSize( - version_->navigation_preload_state().header.length()); - request.headers.CopyFrom(original_request->extra_request_headers()); - request.headers.SetHeader("Service-Worker-Navigation-Preload", - version_->navigation_preload_state().header); - - const int request_id = ResourceDispatcherHostImpl::Get()->MakeRequestID(); - DCHECK_LT(request_id, -1); - - preload_handle_ = blink::mojom::FetchEventPreloadHandle::New(); - network::mojom::URLLoaderClientPtr inner_url_loader_client; - preload_handle_->url_loader_client_request = - mojo::MakeRequest(&inner_url_loader_client); - auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>( - std::move(inner_url_loader_client), std::move(on_response), request); - network::mojom::URLLoaderClientPtr url_loader_client_to_pass; - url_loader_client->Bind(&url_loader_client_to_pass); - network::mojom::URLLoaderPtr url_loader; - - url_loader_factory->CreateLoaderAndStart( - mojo::MakeRequest(&url_loader), original_info->GetRouteID(), request_id, - network::mojom::kURLLoadOptionNone, request, - std::move(url_loader_client_to_pass), - net::MutableNetworkTrafficAnnotationTag( - original_request->traffic_annotation())); - - preload_handle_->url_loader = url_loader.PassInterface(); - - DCHECK(!url_loader_assets_); - url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>( - std::move(url_loader_factory), std::move(url_loader_client)); - return true; -} - -// S13nServiceWorker -bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreloadWithURLLoader( const network::ResourceRequest& original_request, URLLoaderFactoryGetter* url_loader_factory_getter, scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h index cbf37a3d..f978d39 100644 --- a/content/browser/service_worker/service_worker_fetch_dispatcher.h +++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
@@ -26,10 +26,6 @@ #include "third_party/blink/public/mojom/fetch/fetch_api_response.mojom.h" #include "third_party/blink/public/mojom/service_worker/service_worker_event_status.mojom.h" -namespace net { -class URLRequest; -} // namespace net - namespace content { class ServiceWorkerContextWrapper; @@ -67,11 +63,7 @@ // If appropriate, starts the navigation preload request and creates // |preload_handle_|. Returns true if it started navigation preload. // |on_response| is invoked in OnReceiveResponse(). - bool MaybeStartNavigationPreload(net::URLRequest* original_request, - base::OnceClosure on_response); - // S13nServiceWorker - // Same as above but for S13N. - bool MaybeStartNavigationPreloadWithURLLoader( + bool MaybeStartNavigationPreload( const network::ResourceRequest& original_request, URLLoaderFactoryGetter* url_loader_factory_getter, scoped_refptr<ServiceWorkerContextWrapper> context_wrapper,
diff --git a/content/browser/service_worker/service_worker_installed_script_loader.h b/content/browser/service_worker/service_worker_installed_script_loader.h index 18733b0c..a23cadd 100644 --- a/content/browser/service_worker/service_worker_installed_script_loader.h +++ b/content/browser/service_worker/service_worker_installed_script_loader.h
@@ -18,9 +18,8 @@ class ServiceWorkerVersion; -// S13nServiceWorker: A URLLoader that loads an installed service worker script -// for a service worker that doesn't have a -// ServiceWorkerInstalledScriptsManager. +// A URLLoader that loads an installed service worker script for a service +// worker that doesn't have a ServiceWorkerInstalledScriptsManager. // // Some cases where this happens: // - a new (non-installed) service worker requests a script that it already
diff --git a/content/browser/service_worker/service_worker_navigation_loader.cc b/content/browser/service_worker/service_worker_navigation_loader.cc index 580f7bb..e5f5d22 100644 --- a/content/browser/service_worker/service_worker_navigation_loader.cc +++ b/content/browser/service_worker/service_worker_navigation_loader.cc
@@ -224,11 +224,10 @@ active_worker->running_status()), base::BindOnce(&ServiceWorkerNavigationLoader::DidDispatchFetchEvent, weak_factory_.GetWeakPtr())); - did_navigation_preload_ = - fetch_dispatcher_->MaybeStartNavigationPreloadWithURLLoader( - resource_request_, url_loader_factory_getter_.get(), - std::move(context), provider_host_->web_contents_getter(), - base::DoNothing(/* TODO(crbug/762357): metrics? */)); + did_navigation_preload_ = fetch_dispatcher_->MaybeStartNavigationPreload( + resource_request_, url_loader_factory_getter_.get(), std::move(context), + provider_host_->web_contents_getter(), + base::DoNothing(/* TODO(crbug/762357): metrics? */)); // Record worker start time here as |fetch_dispatcher_| will start a service // worker if there is no running service worker.
diff --git a/content/browser/service_worker/service_worker_navigation_loader.h b/content/browser/service_worker/service_worker_navigation_loader.h index 8c657f3..18b82555 100644 --- a/content/browser/service_worker/service_worker_navigation_loader.h +++ b/content/browser/service_worker/service_worker_navigation_loader.h
@@ -30,7 +30,6 @@ class ServiceWorkerVersion; class ServiceWorkerProviderHost; -// S13nServiceWorker: // ServiceWorkerNavigationLoader is the URLLoader used for main resource // requests (i.e., navigation and shared worker requests) that (potentially) go // through a service worker. This loader is only used for the main resource
diff --git a/content/browser/service_worker/service_worker_new_script_loader.h b/content/browser/service_worker/service_worker_new_script_loader.h index 532b50d97..ff2018fe 100644 --- a/content/browser/service_worker/service_worker_new_script_loader.h +++ b/content/browser/service_worker/service_worker_new_script_loader.h
@@ -21,7 +21,6 @@ class ServiceWorkerVersion; struct HttpResponseInfoIOBuffer; -// S13nServiceWorker: // This is the URLLoader used for loading scripts for a new (installing) service // worker. It fetches the script (the main script or imported script) from // network, and returns the response to |client|, while also writing the
diff --git a/content/browser/service_worker/service_worker_provider_host.h b/content/browser/service_worker/service_worker_provider_host.h index 88f4f18..2596395 100644 --- a/content/browser/service_worker/service_worker_provider_host.h +++ b/content/browser/service_worker/service_worker_provider_host.h
@@ -144,7 +144,6 @@ blink::mojom::ServiceWorkerProviderInfoForStartWorkerPtr* out_provider_info); - // S13nServiceWorker: // Used for starting a shared worker. Returns a provider host for the shared // worker and fills |out_provider_info| with info to send to the renderer to // connect to the host. The host stays alive as long as this info stays alive @@ -210,7 +209,6 @@ return running_hosted_version_.get(); } - // S13nServiceWorker: // For service worker clients. Similar to EnsureControllerServiceWorker, but // this returns a bound Mojo ptr which is supposed to be sent to clients. The // controller ptr passed to the clients will be used to intercept requests @@ -406,7 +404,6 @@ // cache. void NotifyControllerLost(); - // S13nServiceWorker: // For service worker clients. Called when |version| is the active worker upon // the main resource request for this client. Remembers |version| as needing // a Soft Update. To avoid affecting page load performance, the update occurs @@ -420,10 +417,6 @@ // // This can be called multiple times due to redirects during a main resource // load. All service workers are updated. - // - // For non-S13nServiceWorker: The update logic is controlled entirely by - // ServiceWorkerControlleeRequestHandler, which sees all resource request - // activity and schedules an update at a convenient time. void AddServiceWorkerToUpdate(scoped_refptr<ServiceWorkerVersion> version); // For service worker clients. |callback| is called when this client becomes
diff --git a/content/browser/service_worker/service_worker_registration_unittest.cc b/content/browser/service_worker/service_worker_registration_unittest.cc index a7a8098..028b022a0 100644 --- a/content/browser/service_worker/service_worker_registration_unittest.cc +++ b/content/browser/service_worker/service_worker_registration_unittest.cc
@@ -549,11 +549,11 @@ // Remove the controllee. Since there is an in-flight request, // activation should not yet happen. - // When S13nServiceWorker is on, the idle timer living in the renderer is - // requested to notify the browser the idle state ASAP. version_1->RemoveControllee(controllee()->client_uuid()); base::RunLoop().RunUntilIdle(); EXPECT_EQ(version_1.get(), reg->active_version()); + // The idle timer living in the renderer is requested to notify the idle state + // to the browser ASAP. EXPECT_TRUE(version_1_service_worker()->is_zero_idle_timer_delay()); // Finish the request. Activation should happen. @@ -582,10 +582,8 @@ EXPECT_EQ(version_1.get(), reg->active_version()); EXPECT_TRUE(version_1_service_worker()->is_zero_idle_timer_delay()); - // Finish the request. - // non-S13nServiceWorker: The service worker becomes idle. - // S13nServiceWorker: FinishRequest() doesn't immediately make the worker - // "no work" state. It needs to be notfied the idle state by + // Finish the request. FinishRequest() doesn't immediately make the worker + // reach the "no work" state. It needs to be notfied of the idle state by // RequestTermination(). version_1->FinishRequest(inflight_request_id(), true /* was_handled */); @@ -612,10 +610,7 @@ base::RunLoop().RunUntilIdle(); EXPECT_EQ(version_1.get(), reg->active_version()); - // Call skipWaiting. - // non-S13nServiceWorker: Activation should happen. - // S13nServiceWorker: Activation should happen after RequestTermination is - // triggered. + // Call skipWaiting. Activation happens after RequestTermination is triggered. base::Optional<bool> result; base::RunLoop skip_waiting_loop; SimulateSkipWaitingWithCallback(version_2.get(), &result,
diff --git a/content/browser/service_worker/service_worker_script_loader_factory.h b/content/browser/service_worker/service_worker_script_loader_factory.h index 62f54b0..adb571a 100644 --- a/content/browser/service_worker/service_worker_script_loader_factory.h +++ b/content/browser/service_worker/service_worker_script_loader_factory.h
@@ -22,7 +22,6 @@ class ServiceWorkerContextCore; class ServiceWorkerProviderHost; -// S13nServiceWorker: // Created per one running service worker for loading its scripts. This is kept // alive while the WebServiceWorkerNetworkProvider in the renderer process is // alive.
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 8625cd74..ba36f0a 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -602,10 +602,9 @@ if (expiration_time > max_request_expiration_time_) max_request_expiration_time_ = expiration_time; - // S13nServiceWorker: // Even if the worker is in the idle state, the new event which is about to // be dispatched will reset the idle status. That means the worker can receive - // events directly from any clients, so we cannot trigger OnNoWork after this + // events directly from any client, so we cannot trigger OnNoWork after this // point. worker_is_idle_on_renderer_ = false; return request_id; @@ -1635,7 +1634,6 @@ if (!pause_after_download()) InitializeGlobalScope(); - // S13nServiceWorker: if (!controller_request_.is_pending()) { DCHECK(!controller_ptr_.is_bound()); controller_request_ = mojo::MakeRequest(&controller_ptr_);
diff --git a/content/browser/service_worker/service_worker_version.h b/content/browser/service_worker/service_worker_version.h index 800ac889..7e346b38 100644 --- a/content/browser/service_worker/service_worker_version.h +++ b/content/browser/service_worker/service_worker_version.h
@@ -258,7 +258,6 @@ // soon after the service worker becomes idle if a waiting worker exists. void TriggerIdleTerminationAsap(); - // S13nServiceWorker: // Called when the renderer notifies the browser that the worker is now idle. // Returns true if the worker will be terminated and the worker should not // handle any events dispatched directly from clients (e.g. FetchEvents for @@ -344,10 +343,8 @@ return service_worker_ptr_.get(); } - // S13nServiceWorker: - // Returns the 'controller' interface ptr of this worker. It is expected - // that the worker is already starting or running, or is going to be started - // soon. + // Returns the 'controller' interface ptr of this worker. It is expected that + // the worker is already starting or running, or is going to be started soon. // TODO(kinuko): Relying on the callsites to start the worker when it's // not running is a bit sketchy, maybe this should queue a task to check // if the pending request is pending too long? https://crbug.com/797222 @@ -723,13 +720,10 @@ // ping. void StopWorkerIfIdle(); - // Non-S13nServiceWorker: returns true if the service worker has work to do: - // it has inflight requests, in-progress streaming URLRequestJobs, or pending - // start callbacks. + // Returns true if the service worker is known to have work to do because the + // browser process initiated a request to the service worker which isn't done + // yet. // - // S13nServiceWorker: returns true if the service worker has work to do: - // because the browser process initiated a request to the service worker which - // isn't done yet. // Note that this method may return false even when the service worker still // has work to do; clients may dispatch events to the service worker directly. // You can ensure no inflight requests exist when HasWorkInBrowser() returns @@ -789,10 +783,9 @@ void CleanUpExternalRequest(const std::string& request_uuid, blink::ServiceWorkerStatusCode status); - // Called if no inflight events exist on the browser process. - // Non-S13nServiceWorker: Triggers OnNoWork(). - // S13nServiceWorker: Triggers OnNoWork() if the renderer-side idle timeout - // has been fired or the worker has been stopped. + // Called if no inflight events exist on the browser process. Triggers + // OnNoWork() if the renderer-side idle timeout has been fired or the worker + // has been stopped. void OnNoWorkInBrowser(); bool IsStartWorkerAllowed() const; @@ -852,7 +845,7 @@ // Connected to ServiceWorkerContextClient while the worker is running. blink::mojom::ServiceWorkerPtr service_worker_ptr_; - // S13nServiceWorker: connected to the controller service worker. + // Connection to the controller service worker. // |controller_request_| is non-null only when the |controller_ptr_| is // requested before the worker is started, it is passed to the worker (and // becomes null) once it's started. @@ -873,14 +866,13 @@ // an inflight response. int inflight_stream_response_count_ = 0; - // S13nServiceWorker: // Set to true if the worker has no inflight events and the idle timer has // been triggered. Set back to false if another event starts since the worker // is no longer idle. bool worker_is_idle_on_renderer_ = true; - // S13nServiceWorker: Set to true when the worker needs to be terminated as - // soon as possible (e.g. activation). + // Set to true when the worker needs to be terminated as soon as possible + // (e.g. activation). bool needs_to_be_terminated_asap_ = false; // Keeps track of the provider hosting this running service worker for this
diff --git a/content/browser/worker_host/worker_script_loader_factory.h b/content/browser/worker_host/worker_script_loader_factory.h index 7ff56fd..27a53af 100644 --- a/content/browser/worker_host/worker_script_loader_factory.h +++ b/content/browser/worker_host/worker_script_loader_factory.h
@@ -20,7 +20,6 @@ class ResourceContext; class WorkerScriptLoader; -// S13nServiceWorker: // WorkerScriptLoaderFactory creates a WorkerScriptLoader to load the main // script for a web worker (dedicated worker or shared worker), which follows // redirects and sets the controller service worker on the web worker if needed.
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/scheduler/UiThreadSchedulerTest.java b/content/public/android/javatests/src/org/chromium/content/browser/scheduler/UiThreadSchedulerTest.java index 0c55f93..07ff7c6 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/scheduler/UiThreadSchedulerTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/scheduler/UiThreadSchedulerTest.java
@@ -28,6 +28,7 @@ import org.chromium.content_public.browser.BrowserTaskExecutor; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.test.NativeLibraryTestRule; +import org.chromium.content_public.browser.test.util.UiThreadSchedulerTestUtils; import java.util.ArrayList; import java.util.List; @@ -43,6 +44,8 @@ @Before public void setUp() { + // We don't load the browser process since we want tests to control when content + // is started and hence the native secheduler is ready. mNativeLibraryTestRule.loadNativeLibraryNoBrowserProcess(); ThreadUtils.setUiThread(null); ThreadUtils.setWillOverrideUiThread(true); @@ -52,10 +55,12 @@ BrowserTaskExecutor.register(); BrowserTaskExecutor.setShouldPrioritizeBootstrapTasks(true); mHandler = new Handler(mUiThread.getLooper()); + UiThreadSchedulerTestUtils.postBrowserMainLoopStartupTasks(false); } @After public void tearDown() { + UiThreadSchedulerTestUtils.postBrowserMainLoopStartupTasks(true); mUiThread.quitSafely(); ThreadUtils.setUiThread(null); ThreadUtils.setWillOverrideUiThread(false); @@ -157,6 +162,8 @@ public void testTaskNotRunOnUiThreadWithoutUiThreadTaskTraits() throws Exception { TaskRunner uiThreadTaskRunner = PostTask.createSingleThreadTaskRunner(new TaskTraits()); try { + // Test times out without this. + UiThreadSchedulerTestUtils.postBrowserMainLoopStartupTasks(true); startContentMainOnUiThread(); uiThreadTaskRunner.postTask(new Runnable() {
diff --git a/content/public/browser/navigation_throttle.cc b/content/public/browser/navigation_throttle.cc index 45ff97e..552b1af 100644 --- a/content/public/browser/navigation_throttle.cc +++ b/content/public/browser/navigation_throttle.cc
@@ -85,7 +85,9 @@ resume_callback_.Run(); return; } - static_cast<NavigationHandleImpl*>(navigation_handle_)->Resume(this); + static_cast<NavigationHandleImpl*>(navigation_handle_) + ->navigation_request() + ->Resume(this); } void NavigationThrottle::CancelDeferredNavigation( @@ -95,6 +97,7 @@ return; } static_cast<NavigationHandleImpl*>(navigation_handle_) + ->navigation_request() ->CancelDeferredNavigation(this, result); }
diff --git a/content/public/test/android/BUILD.gn b/content/public/test/android/BUILD.gn index 6705870d..9f36f4c 100644 --- a/content/public/test/android/BUILD.gn +++ b/content/public/test/android/BUILD.gn
@@ -55,6 +55,7 @@ "javatests/src/org/chromium/content_public/browser/test/util/TestTouchUtils.java", "javatests/src/org/chromium/content_public/browser/test/util/TestWebContentsObserver.java", "javatests/src/org/chromium/content_public/browser/test/util/TouchCommon.java", + "javatests/src/org/chromium/content_public/browser/test/util/UiThreadSchedulerTestUtils.java", "javatests/src/org/chromium/content_public/browser/test/util/UiUtils.java", "javatests/src/org/chromium/content_public/browser/test/util/WebContentsUtils.java", ] @@ -67,6 +68,7 @@ "javatests/src/org/chromium/content_public/browser/test/InterstitialPageDelegateAndroid.java", "javatests/src/org/chromium/content_public/browser/test/RenderFrameHostTestExt.java", "javatests/src/org/chromium/content_public/browser/test/util/DOMUtils.java", + "javatests/src/org/chromium/content_public/browser/test/util/UiThreadSchedulerTestUtils.java", "javatests/src/org/chromium/content_public/browser/test/util/WebContentsUtils.java", ] } @@ -86,6 +88,7 @@ "interstitial_page_delegate_android.h", "render_frame_host_test_ext.cc", "render_frame_host_test_ext.h", + "ui_thread_scheduler_test_utils.cc", "web_contents_utils.cc", ] deps = [
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/UiThreadSchedulerTestUtils.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/UiThreadSchedulerTestUtils.java new file mode 100644 index 0000000..ab73af9 --- /dev/null +++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/UiThreadSchedulerTestUtils.java
@@ -0,0 +1,24 @@ +// 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. + +package org.chromium.content_public.browser.test.util; + +import org.chromium.base.annotations.JNINamespace; + +/** + * Helper methods for testing the UiThreadScheduler + */ +@JNINamespace("content") +public class UiThreadSchedulerTestUtils { + /** + * @param enabled Whether or not BrowserMainLoop::CreateStartupTasks should post tasks. This + * is useful because they will crash in in some testing scenarios despite not being + * needed for the test. + */ + public static void postBrowserMainLoopStartupTasks(boolean enabled) { + nativePostBrowserMainLoopStartupTasks(enabled); + } + + private static native void nativePostBrowserMainLoopStartupTasks(boolean enabled); +}
diff --git a/content/public/test/android/ui_thread_scheduler_test_utils.cc b/content/public/test/android/ui_thread_scheduler_test_utils.cc new file mode 100644 index 0000000..fa022bd3 --- /dev/null +++ b/content/public/test/android/ui_thread_scheduler_test_utils.cc
@@ -0,0 +1,17 @@ +// 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. + +#include "base/android/jni_android.h" +#include "content/browser/browser_main_loop.h" +#include "jni/UiThreadSchedulerTestUtils_jni.h" + +namespace content { + +void JNI_UiThreadSchedulerTestUtils_PostBrowserMainLoopStartupTasks( + JNIEnv* env, + jboolean enabled) { + BrowserMainLoop::EnableStartupTasks(enabled); +} + +} // namespace content
diff --git a/content/public/test/hit_test_region_observer.cc b/content/public/test/hit_test_region_observer.cc index 06ae46f..a97c28f 100644 --- a/content/public/test/hit_test_region_observer.cc +++ b/content/public/test/hit_test_region_observer.cc
@@ -11,6 +11,7 @@ #include "components/viz/host/hit_test/hit_test_query.h" #include "components/viz/host/host_frame_sink_manager.h" #include "components/viz/service/frame_sinks/frame_sink_manager_impl.h" +#include "components/viz/service/surfaces/surface.h" #include "components/viz/service/surfaces/surface_manager.h" #include "content/browser/compositor/surface_utils.h" #include "content/browser/frame_host/cross_process_frame_connector.h"
diff --git a/content/renderer/loader/web_url_request_util.h b/content/renderer/loader/web_url_request_util.h index 58d5763..213dbfb 100644 --- a/content/renderer/loader/web_url_request_util.h +++ b/content/renderer/loader/web_url_request_util.h
@@ -49,7 +49,7 @@ std::vector<blink::mojom::BlobPtrInfo> blob_ptrs); // Takes a ResourceRequestBody and gets blob pointers for Blob entries. -// Used only in non-NetworkService cases but with S13nServiceWorker. +// Used only in non-NetworkService case. // TODO(kinuko): Remove this once Network Service is shipped. std::vector<blink::mojom::BlobPtrInfo> GetBlobPtrsForRequestBody( const network::ResourceRequestBody& input);
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.h b/content/renderer/loader/web_worker_fetch_context_impl.h index f49055e..e7561d9 100644 --- a/content/renderer/loader/web_worker_fetch_context_impl.h +++ b/content/renderer/loader/web_worker_fetch_context_impl.h
@@ -59,7 +59,6 @@ // security reasons like sandboxed iframes, insecure origins etc. // |loader_factory_info| is used for regular loading by the worker. // - // S13nServiceWorker: // If the worker is controlled by a service worker, this class makes another // loader factory which sends requests to the service worker, and passes // |fallback_factory_info| to that factory to use for network fallback. @@ -171,7 +170,6 @@ bool Send(IPC::Message* message); - // S13nServiceWorker: // Resets the service worker url loader factory of a URLLoaderFactoryImpl // which was passed to Blink. The url loader factory is connected to the // controller service worker. Sets nullptr if the worker context is not @@ -205,14 +203,12 @@ blink::mojom::ControllerServiceWorkerMode is_controlled_by_service_worker_ = blink::mojom::ControllerServiceWorkerMode::kNoController; - // S13nServiceWorker: // Initialized on the worker thread when InitializeOnWorkerThread() is called. // This can be null if the |provider_context| passed to Create() was null or // already being destructed (see // ServiceWorkerProviderContext::OnNetworkProviderDestroyed()). blink::mojom::ServiceWorkerContainerHostPtr service_worker_container_host_; - // S13nServiceWorker: // The Client#id value of the shared worker or dedicated worker (since // dedicated workers are not yet service worker clients, it is the parent // document's id in that case). Passed to ControllerServiceWorkerConnector. @@ -223,17 +219,15 @@ // Initialized on the worker thread when InitializeOnWorkerThread() is called. // |loader_factory_| is used for regular loading by the worker. In - // S13nServiceWorker, if the worker is controlled by a service worker, it - // creates a ServiceWorkerSubresourceLoaderFactory instead. + // If the worker is controlled by a service worker, it creates a + // ServiceWorkerSubresourceLoaderFactory instead. scoped_refptr<network::SharedURLLoaderFactory> loader_factory_; // Initialized on the worker thread when InitializeOnWorkerThread() is called. - // S13nServiceWorker: If the worker is controlled by a service worker, it - // passes this factory to ServiceWorkerSubresourceLoaderFactory to use for - // network fallback. + // If the worker is controlled by a service worker, it passes this factory to + // ServiceWorkerSubresourceLoaderFactory to use for network fallback. scoped_refptr<network::SharedURLLoaderFactory> fallback_factory_; - // S13nServiceWorker: // Initialized on the worker thread when InitializeOnWorkerThread() is called. scoped_refptr<base::RefCountedData<blink::mojom::BlobRegistryPtr>> blob_registry_;
diff --git a/content/renderer/p2p/ipc_socket_factory.cc b/content/renderer/p2p/ipc_socket_factory.cc index 135f41c8..78816b1a 100644 --- a/content/renderer/p2p/ipc_socket_factory.cc +++ b/content/renderer/p2p/ipc_socket_factory.cc
@@ -601,12 +601,8 @@ in_flight_packet_records_.pop_front(); TraceSendThrottlingState(); - int64_t send_time_ms = -1; - if (send_metrics.rtc_packet_id >= 0) { - send_time_ms = send_metrics.send_time.since_origin().InMilliseconds(); - } SignalSentPacket(this, rtc::SentPacket(send_metrics.rtc_packet_id, - send_time_ms)); + send_metrics.send_time_ms)); if (writable_signal_expected_ && send_bytes_available_ > 0) { WebRtcLogMessage(base::StringPrintf(
diff --git a/content/renderer/service_worker/controller_service_worker_impl.h b/content/renderer/service_worker/controller_service_worker_impl.h index c05ab0b..d2e56d8 100644 --- a/content/renderer/service_worker/controller_service_worker_impl.h +++ b/content/renderer/service_worker/controller_service_worker_impl.h
@@ -19,7 +19,6 @@ class ServiceWorkerContextClient; -// S13nServiceWorker: // An instance of this class is created on the service worker thread // when ServiceWorkerContextClient's WorkerContextData is created. // This implements blink::mojom::ControllerServiceWorker and its Mojo endpoint @@ -29,8 +28,8 @@ // Fetch events via the Mojo endpoints. // // TODO(kinuko): Implement self-killing timer, that does something similar to -// what ServiceWorkerVersion::StopWorkerIfIdle does in the browser process in -// non-S13n code. +// what ServiceWorkerVersion::StopWorkerIfIdle did in the browser process in +// the non-S13n codepath. class ControllerServiceWorkerImpl : public blink::mojom::ControllerServiceWorker { public:
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc index 88e444a..c2b72a6 100644 --- a/content/renderer/service_worker/service_worker_context_client.cc +++ b/content/renderer/service_worker/service_worker_context_client.cc
@@ -264,12 +264,10 @@ // Inflight navigation preload requests. base::IDMap<std::unique_ptr<NavigationPreloadRequest>> preload_requests; - // S13nServiceWorker // Timer triggered when the service worker considers it should be stopped or // an event should be aborted. std::unique_ptr<ServiceWorkerTimeoutTimer> timeout_timer; - // S13nServiceWorker // |controller_impl| should be destroyed before |timeout_timer| since the // pipe needs to be disconnected before callbacks passed by // DispatchSomeEvent() get destructed, which may be stored in |timeout_timer| @@ -1544,7 +1542,6 @@ .To<blink::WebServiceWorkerObjectInfo>()); } -// S13nServiceWorker void ServiceWorkerContextClient::DispatchFetchEvent( blink::mojom::DispatchFetchEventParamsPtr params, blink::mojom::ServiceWorkerFetchResponseCallbackPtr response_callback,
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h index 9621091d..440ebcfb 100644 --- a/content/renderer/service_worker/service_worker_context_client.h +++ b/content/renderer/service_worker/service_worker_context_client.h
@@ -427,7 +427,6 @@ // startup completes. blink::mojom::EmbeddedWorkerStartTimingPtr start_timing_; - // S13nServiceWorker: // A URLLoaderFactory instance used for subresource loading. scoped_refptr<HostChildURLLoaderFactoryBundle> loader_factories_;
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc index 31af349..3742531 100644 --- a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc +++ b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc
@@ -110,11 +110,7 @@ request.SetSkipServiceWorker(true); } - // Inject this frame's fetch window id into the request. This is really only - // needed for subresource requests in S13nServiceWorker. For main resource - // requests or non-S13nSW case, the browser process sets the id on the - // request when dispatching the fetch event to the service worker. But it - // doesn't hurt to set it always. + // Inject this frame's fetch window id into the request. if (context()) request.SetFetchWindowId(context()->fetch_request_window_id()); }
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_frame.h b/content/renderer/service_worker/service_worker_network_provider_for_frame.h index 3338fc2..c70b045 100644 --- a/content/renderer/service_worker/service_worker_network_provider_for_frame.h +++ b/content/renderer/service_worker/service_worker_network_provider_for_frame.h
@@ -23,7 +23,6 @@ public: // Creates a network provider for |frame|. // - // For S13nServiceWorker: // |controller_info| contains the endpoint and object info that is needed to // set up the controller service worker for the client. // |fallback_loader_factory| is a default loader factory for fallback
diff --git a/content/renderer/service_worker/service_worker_provider_context.h b/content/renderer/service_worker/service_worker_provider_context.h index 835b6dd..c58cfc0 100644 --- a/content/renderer/service_worker/service_worker_provider_context.h +++ b/content/renderer/service_worker/service_worker_provider_context.h
@@ -69,10 +69,9 @@ // the content::ServiceWorkerProviderHost that notifies of changes to the // registration's and workers' status. |request| is bound with |binding_|. // - // |controller_info| contains the endpoint (which is non-null only when - // S13nServiceWorker is enabled) and object info that is needed to set up the - // controller service worker for the context. - // For S13nServiceWorker: + // |controller_info| contains the endpoint and object info that is needed to + // set up the controller service worker for the context. + // // |fallback_loader_factory| is a default loader factory for fallback // requests, and is used when we create a subresource loader for controllees. // This is non-null only if the provider is created for controllees, and if @@ -101,7 +100,6 @@ // any, otherwise returns nullptr. blink::mojom::ServiceWorkerObjectInfoPtr TakeController(); - // S13nServiceWorker: // Returns URLLoaderFactory for loading subresources with the controller // ServiceWorker, or nullptr if no controller is attached. network::mojom::URLLoaderFactory* GetSubresourceLoaderFactory(); @@ -109,7 +107,6 @@ // Returns the feature usage of the controller service worker. const std::set<blink::mojom::WebFeature>& used_features() const; - // S13nServiceWorker: // The Client#id value of the client. const std::string& client_id() const; @@ -131,7 +128,6 @@ void CloneWorkerClientRegistry( blink::mojom::ServiceWorkerWorkerClientRegistryRequest request) override; - // S13nServiceWorker: // Returns a ServiceWorkerContainerHostPtrInfo to this context's container // host. This can return null after OnNetworkProviderDestroyed() is called // (in which case |this| will be destroyed soon). @@ -194,7 +190,6 @@ blink::TransferableMessage message) override; void CountFeature(blink::mojom::WebFeature feature) override; - // S13nServiceWorker: // A convenient utility method to tell if a subresource loader factory // can be created for this context. bool CanCreateSubresourceLoaderFactory() const;
diff --git a/content/renderer/service_worker/service_worker_provider_context_unittest.cc b/content/renderer/service_worker/service_worker_provider_context_unittest.cc index 0a7bf9f1..cf3722e 100644 --- a/content/renderer/service_worker/service_worker_provider_context_unittest.cc +++ b/content/renderer/service_worker/service_worker_provider_context_unittest.cc
@@ -126,8 +126,8 @@ std::set<blink::mojom::WebFeature> used_features_; }; -// S13nServiceWorker: a fake URLLoaderFactory implementation that basically -// does nothing but records the requests. +// A fake URLLoaderFactory implementation that basically does nothing but +// records the requests. class FakeURLLoaderFactory final : public network::mojom::URLLoaderFactory { public: FakeURLLoaderFactory() = default; @@ -173,8 +173,8 @@ DISALLOW_COPY_AND_ASSIGN(FakeURLLoaderFactory); }; -// S13nServiceWorker: a fake ControllerServiceWorker implementation that -// basically does nothing but records DispatchFetchEvent calls. +// A fake ControllerServiceWorker implementation that basically does nothing but +// records DispatchFetchEvent calls. class FakeControllerServiceWorker : public blink::mojom::ControllerServiceWorker { public: @@ -264,7 +264,7 @@ public: ServiceWorkerProviderContextTest() = default; - void EnableS13nServiceWorker() { + void EnableNetworkService() { scoped_feature_list_.InitAndEnableFeature( network::features::kNetworkService); network::mojom::URLLoaderFactoryPtr fake_loader_factory; @@ -294,8 +294,6 @@ protected: base::test::ScopedTaskEnvironment task_environment; - - // S13nServiceWorker: base::test::ScopedFeatureList scoped_feature_list_; FakeURLLoaderFactory fake_loader_factory_; scoped_refptr<network::SharedURLLoaderFactory> loader_factory_; @@ -414,10 +412,10 @@ EXPECT_TRUE(client->was_set_controller_called()); } -// S13nServiceWorker: Test that SetController correctly sets (or resets) -// the controller service worker for clients. +// Test that SetController correctly sets (or resets) the controller service +// worker for clients. TEST_F(ServiceWorkerProviderContextTest, SetControllerServiceWorker) { - EnableS13nServiceWorker(); + EnableNetworkService(); const int kProviderId = 10; // Make the ServiceWorkerContainerHost implementation and @@ -608,7 +606,7 @@ } TEST_F(ServiceWorkerProviderContextTest, ControllerWithoutFetchHandler) { - EnableS13nServiceWorker(); + EnableNetworkService(); const int kProviderId = 10; auto object_host = std::make_unique<MockServiceWorkerObjectHost>(200 /* version_id */);
diff --git a/content/renderer/service_worker/service_worker_provider_state_for_client.h b/content/renderer/service_worker/service_worker_provider_state_for_client.h index 9d0d216..d07d11c 100644 --- a/content/renderer/service_worker/service_worker_provider_state_for_client.h +++ b/content/renderer/service_worker/service_worker_provider_state_for_client.h
@@ -36,16 +36,13 @@ // Keeps version id of the current controller service worker object. int64_t controller_version_id = blink::mojom::kInvalidServiceWorkerVersionId; - // S13nServiceWorker: // Used to intercept requests from the controllee and dispatch them // as events to the controller ServiceWorker. network::mojom::URLLoaderFactoryPtr subresource_loader_factory; - // S13nServiceWorker: // Used when we create |subresource_loader_factory|. scoped_refptr<network::SharedURLLoaderFactory> fallback_loader_factory; - // S13nServiceWorker: // The Client#id value of the client. std::string client_id; @@ -75,7 +72,6 @@ mojo::BindingSet<blink::mojom::ServiceWorkerWorkerClientRegistry> worker_client_registry_bindings; - // S13nServiceWorker // Used in |subresource_loader_factory| to get the connection to the // controller service worker. //
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.h b/content/renderer/service_worker/service_worker_subresource_loader.h index 1fe2aed..9ada5a12 100644 --- a/content/renderer/service_worker/service_worker_subresource_loader.h +++ b/content/renderer/service_worker/service_worker_subresource_loader.h
@@ -30,7 +30,6 @@ class ControllerServiceWorkerConnector; -// S13nServiceWorker: // A custom URLLoader implementation used by Service Worker controllees // for loading subresources via the controller Service Worker. // Currently an instance of this class is created and used only on @@ -198,7 +197,6 @@ DISALLOW_COPY_AND_ASSIGN(ServiceWorkerSubresourceLoader); }; -// S13nServiceWorker: // A custom URLLoaderFactory implementation used by Service Worker controllees // for loading subresources via the controller Service Worker. // Self destroys when no more bindings exist.
diff --git a/content/test/data/accessibility/event/text-changed-contenteditable-expected-auralinux.txt b/content/test/data/accessibility/event/text-changed-contenteditable-expected-auralinux.txt new file mode 100644 index 0000000..1d49e7e7 --- /dev/null +++ b/content/test/data/accessibility/event/text-changed-contenteditable-expected-auralinux.txt
@@ -0,0 +1,24 @@ +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +STATE-CHANGE:DEFUNCT:TRUE role=ROLE_INVALID name='(null)' DEFUNCT +TEXT-INSERT (start=0 length=16 'Before Div After') role=ROLE_SECTION name='(null)' EDITABLE,ENABLED,FOCUSABLE,MULTI-LINE,SENSITIVE,SHOWING,VISIBLE,SELECTABLE-TEXT +TEXT-INSERT (start=0 length=22 'Before Paragraph After') role=ROLE_PARAGRAPH name='(null)' EDITABLE,ENABLED,FOCUSABLE,MULTI-LINE,SENSITIVE,SHOWING,VISIBLE,SELECTABLE-TEXT +TEXT-INSERT (start=0 length=9 'Modified ') role=ROLE_PARAGRAPH name='(null)' EDITABLE,ENABLED,FOCUSABLE,MULTI-LINE,SENSITIVE,SHOWING,VISIBLE,SELECTABLE-TEXT +TEXT-INSERT (start=0 length=9 'Modified ') role=ROLE_SECTION name='(null)' EDITABLE,ENABLED,FOCUSABLE,MULTI-LINE,SENSITIVE,SHOWING,VISIBLE,SELECTABLE-TEXT +TEXT-REMOVE (start=0 length=3 'Div') role=ROLE_SECTION name='(null)' EDITABLE,ENABLED,FOCUSABLE,MULTI-LINE,SENSITIVE,SHOWING,VISIBLE,SELECTABLE-TEXT +TEXT-REMOVE (start=0 length=3 'Div') role=ROLE_SECTION name='(null)' EDITABLE,ENABLED,FOCUSABLE,MULTI-LINE,SENSITIVE,SHOWING,VISIBLE,SELECTABLE-TEXT +TEXT-REMOVE (start=0 length=9 'Paragraph') role=ROLE_PARAGRAPH name='(null)' EDITABLE,ENABLED,FOCUSABLE,MULTI-LINE,SENSITIVE,SHOWING,VISIBLE,SELECTABLE-TEXT +TEXT-REMOVE (start=0 length=9 'Paragraph') role=ROLE_PARAGRAPH name='(null)' EDITABLE,ENABLED,FOCUSABLE,MULTI-LINE,SENSITIVE,SHOWING,VISIBLE,SELECTABLE-TEXT
diff --git a/content/test/data/accessibility/event/text-changed-contenteditable.html b/content/test/data/accessibility/event/text-changed-contenteditable.html new file mode 100644 index 0000000..db0f3248 --- /dev/null +++ b/content/test/data/accessibility/event/text-changed-contenteditable.html
@@ -0,0 +1,21 @@ +<!DOCTYPE html> +<html> +<body> +<p id="p1" contenteditable>Paragraph</p> +<p id="p2" contenteditable>Paragraph</p> +<p id="p3" contenteditable>Paragraph</p> +<div id="d1" contenteditable>Div</div> +<div id="d2" contenteditable>Div</div> +<div id="d3" contenteditable>Div</div> +<script> + function go() { + document.querySelector('#p1').textContent = 'Modified Paragraph'; + document.querySelector('#p2').textContent = ''; + document.querySelector('#p3').textContent = 'Before Paragraph After'; + document.querySelector('#d1').textContent = 'Modified Div'; + document.querySelector('#d2').textContent = ''; + document.querySelector('#d3').textContent = 'Before Div After'; + } +</script> +</body> +</html>
diff --git a/docs/clangd.md b/docs/clangd.md new file mode 100644 index 0000000..e8bfc29 --- /dev/null +++ b/docs/clangd.md
@@ -0,0 +1,62 @@ +# Clangd + +## Introduction + +[clangd](https://clang.llvm.org/extra/clangd/) is a clang-based [language server](http://langserver.org/). +It brings IDE features (e.g. diagnostics, code completion, code navigations) to +your editor. + +## Getting clangd + +See [instructions](https://clang.llvm.org/extra/clangd/Installation.html#installing-clangd). + +**Googlers:** clangd has been installed on your glinux by default, just use +`/usr/bin/clangd`. + +Alternative: use the following command to build clangd from LLVM source, and you +will get the binary at +`out/Release/tools/clang/third_party/llvm/build/bin/clangd`. + +``` +tools/clang/scripts/build_clang_tools_extra.py --fetch out/Release clangd +``` + +## Setting Up + +1. Build chrome normally. This step is required to make sure we have all +generated files. + +``` +ninja -C out/Release chrome +``` + +2. Generate the compilation database, clangd needs it to know how to build a +source file. + +``` +tools/clang/scripts/generate_compdb.py -p out/Release > compile_commands.json +``` + +Note: the compilation database is not re-generated automatically, you'd need to +regenerate it manually when you have new files checked in. + +3. Use clangd in your favourite editor, see detailed [instructions]( +https://clang.llvm.org/extra/clangd/Installation.html#getting-started-with-clangd). + +## Index + +By default, clangd only knows the files you are currently editing. To provide +project-wide code navigations (e.g. find references), clangd neesds a +project-wide index. + +You can pass an **experimental** `--background-index` command line argument to +clangd, clangd will incrementally build an index of Chromium in the background. +Note: the first index time may take hours (for reference, it took 2~3 hours on +a 48-core, 64GB machine). + +A full index of Chromium (including v8, blink) takes ~550 MB disk space and ~2.7 +GB memory in clangd. + +## Questions + +If you have any questions, reach out to clangd-dev@lists.llvm.org.
diff --git a/infra/config/cr-buildbucket.cfg b/infra/config/cr-buildbucket.cfg index bbda8344..3345a58 100644 --- a/infra/config/cr-buildbucket.cfg +++ b/infra/config/cr-buildbucket.cfg
@@ -1379,6 +1379,11 @@ } builders { + name: "Linux FYI SkiaRenderer Vulkan (NVIDIA)" + mixins: "linux-gpu-fyi-ci" + } + + builders { name: "Linux FYI Release (Intel HD 630)" mixins: "linux-gpu-fyi-ci" }
diff --git a/infra/config/luci-milo.cfg b/infra/config/luci-milo.cfg index 776dd4ed..79a77ad 100644 --- a/infra/config/luci-milo.cfg +++ b/infra/config/luci-milo.cfg
@@ -3263,6 +3263,11 @@ short_name: "dqp" } builders { + name: "buildbucket/luci.chromium.ci/Linux FYI SkiaRenderer Vulkan (NVIDIA)" + category: "Linux|Nvidia" + short_name: "skv" + } + builders { name: "buildbucket/luci.chromium.ci/Linux FYI GPU TSAN Release" category: "Linux" short_name: "tsn"
diff --git a/infra/config/luci-scheduler.cfg b/infra/config/luci-scheduler.cfg index 72b78ae..5c6d9817 100644 --- a/infra/config/luci-scheduler.cfg +++ b/infra/config/luci-scheduler.cfg
@@ -1548,6 +1548,17 @@ } job { + id: "Linux FYI SkiaRenderer Vulkan (NVIDIA)" + # Triggered by "GPU FYI Linux Builder". + acl_sets: "triggered-by-parent-builders" + buildbucket: { + server: "cr-buildbucket.appspot.com" + bucket: "luci.chromium.ci" + builder: "Linux FYI SkiaRenderer Vulkan (NVIDIA)" + } +} + +job { id: "Optional Linux Release (Intel HD 630)" # Triggered by "GPU FYI Linux Builder". acl_sets: "triggered-by-parent-builders"
diff --git a/ios/chrome/browser/passwords/password_controller_unittest.mm b/ios/chrome/browser/passwords/password_controller_unittest.mm index d360d3fb..368072f 100644 --- a/ios/chrome/browser/passwords/password_controller_unittest.mm +++ b/ios/chrome/browser/passwords/password_controller_unittest.mm
@@ -20,6 +20,7 @@ #include "components/autofill/core/common/password_form_fill_data.h" #include "components/password_manager/core/browser/log_manager.h" #include "components/password_manager/core/browser/mock_password_store.h" +#include "components/password_manager/core/browser/new_password_form_manager.h" #include "components/password_manager/core/browser/password_store_consumer.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" #include "components/password_manager/core/common/password_manager_pref_names.h" @@ -203,6 +204,14 @@ void SetUp() override { ChromeWebTest::SetUp(); + + // When waiting for predictions is on, it makes tests more complicated. + // Disable wating, since most tests have nothing to do with predictions. All + // tests that test working with prediction should explicitly turn + // predictions on. + password_manager::NewPasswordFormManager:: + set_wait_for_server_predictions_for_filling(false); + passwordController_ = CreatePasswordController(web_state(), store_.get(), &weak_client_); @autoreleasepool { @@ -1188,8 +1197,10 @@ password_manager::PasswordStore::FormDigest expected_form_digest( autofill::PasswordForm::SCHEME_HTML, "https://chromium.test/", GURL("https://chromium.test/")); + // TODO(crbug.com/949519): replace WillRepeatedly with WillOnce when the old + // parser is gone. EXPECT_CALL(*store_, GetLogins(expected_form_digest, _)) - .WillOnce(testing::Invoke( + .WillRepeatedly(testing::Invoke( [&get_logins_called]( const password_manager::PasswordStore::FormDigest&, password_manager::PasswordStoreConsumer*) { @@ -1315,8 +1326,10 @@ if (store_has_credentials) { PasswordForm form(CreatePasswordForm(BaseUrl().c_str(), "user", "pw")); + // TODO(crbug.com/949519): replace WillRepeatedly with WillOnce when the + // old parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(form))); } else { EXPECT_CALL(*store_, GetLogins(_, _)) .WillRepeatedly(WithArg<1>(InvokeEmptyConsumerWithForms())); @@ -1357,8 +1370,10 @@ __block BOOL completion_handler_called = NO; PasswordForm form(CreatePasswordForm(BaseUrl().c_str(), "user", "pw")); + // TODO(crbug.com/949519): replace WillRepeatedly with WillOnce when the old + // parser is gone. EXPECT_CALL(*store_, GetLogins(_, _)) - .WillOnce(WithArg<1>(InvokeConsumer(form))); + .WillRepeatedly(WithArg<1>(InvokeConsumer(form))); std::string mainFrameID = web::GetMainWebFrameId(web_state()); [passwordController_ checkIfSuggestionsAvailableForForm:@"dynamic_form"
diff --git a/ios/chrome/browser/search_engines/search_engines_util.cc b/ios/chrome/browser/search_engines/search_engines_util.cc index 5adec2f..54fccbb 100644 --- a/ios/chrome/browser/search_engines/search_engines_util.cc +++ b/ios/chrome/browser/search_engines/search_engines_util.cc
@@ -29,26 +29,32 @@ DCHECK(service); DCHECK(service->loaded()); std::vector<TemplateURL*> old_engines = service->GetTemplateURLs(); - size_t default_engine; + size_t default_engine_index; std::vector<std::unique_ptr<TemplateURLData>> new_engines = TemplateURLPrepopulateData::GetPrepopulatedEngines(nullptr, - &default_engine); - DCHECK(default_engine == 0); + &default_engine_index); + DCHECK(default_engine_index == 0); DCHECK(new_engines[0]->prepopulate_id == kGoogleEnginePrepopulatedId); // The aim is to replace the old search engines with the new ones. // It is not possible to remove all of them, because removing the current // selected engine is not allowed. // It is not possible to add all the new ones first, because the service gets // confused when a prepopulated engine is there more than once. - // Instead, this will in a first pass makes google as the default engine. In - // a second pass, it will remove all other search engines. At last, in a third - // pass, it will add all new engines but google. - for (auto* engine : old_engines) { - if (engine->prepopulate_id() == kGoogleEnginePrepopulatedId) - service->SetUserSelectedDefaultSearchProvider(engine); + // Instead, this will in a first pass make Google as the default engine if + // the currently selected engine is neither Google nor custom engine. Then it + // will remove all prepopulated search engines except Google. At last, in a + // third pass, it will add all new engines except Google. + const TemplateURL* default_engine = service->GetDefaultSearchProvider(); + if (default_engine->prepopulate_id() > kGoogleEnginePrepopulatedId) { + for (auto* engine : old_engines) { + if (engine->prepopulate_id() == kGoogleEnginePrepopulatedId) { + service->SetUserSelectedDefaultSearchProvider(engine); + break; + } + } } for (auto* engine : old_engines) { - if (engine->prepopulate_id() != kGoogleEnginePrepopulatedId) + if (engine->prepopulate_id() > kGoogleEnginePrepopulatedId) service->Remove(engine); } for (const auto& engine : new_engines) {
diff --git a/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm b/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm index c80d03fe..d464537 100644 --- a/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm +++ b/ios/chrome/browser/ui/autofill/save_card_infobar_view.mm
@@ -12,7 +12,6 @@ #import "ios/chrome/browser/ui/infobars/infobar_constants.h" #import "ios/chrome/browser/ui/util/label_link_controller.h" #import "ios/chrome/browser/ui/util/named_guide.h" -#include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" #import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" @@ -226,11 +225,7 @@ - (void)setupSubviews { [self setAccessibilityViewIsModal:YES]; - if (IsUIRefreshPhase1Enabled()) { - self.backgroundColor = UIColorFromRGB(kInfobarBackgroundColor); - } else { - self.backgroundColor = [UIColor whiteColor]; - } + self.backgroundColor = UIColorFromRGB(kInfobarBackgroundColor); id<LayoutGuideProvider> safeAreaLayoutGuide = self.safeAreaLayoutGuide; // Add the icon. The icon is fixed to the top leading corner of the infobar.
diff --git a/ios/chrome/browser/ui/elements/BUILD.gn b/ios/chrome/browser/ui/elements/BUILD.gn index 2af5b38..0213e73 100644 --- a/ios/chrome/browser/ui/elements/BUILD.gn +++ b/ios/chrome/browser/ui/elements/BUILD.gn
@@ -5,6 +5,8 @@ source_set("elements") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ + "extended_touch_target_button.h", + "extended_touch_target_button.mm", "selector_coordinator.h", "selector_coordinator.mm", "selector_picker_presentation_controller.h",
diff --git a/ios/chrome/browser/ui/location_bar/extended_touch_target_button.h b/ios/chrome/browser/ui/elements/extended_touch_target_button.h similarity index 63% rename from ios/chrome/browser/ui/location_bar/extended_touch_target_button.h rename to ios/chrome/browser/ui/elements/extended_touch_target_button.h index bd5de47..04fad4f 100644 --- a/ios/chrome/browser/ui/location_bar/extended_touch_target_button.h +++ b/ios/chrome/browser/ui/elements/extended_touch_target_button.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef IOS_CHROME_BROWSER_UI_LOCATION_BAR_EXTENDED_TOUCH_TARGET_BUTTON_H_ -#define IOS_CHROME_BROWSER_UI_LOCATION_BAR_EXTENDED_TOUCH_TARGET_BUTTON_H_ +#ifndef IOS_CHROME_BROWSER_UI_ELEMENTS_EXTENDED_TOUCH_TARGET_BUTTON_H_ +#define IOS_CHROME_BROWSER_UI_ELEMENTS_EXTENDED_TOUCH_TARGET_BUTTON_H_ #import <UIKit/UIKit.h> @@ -12,4 +12,4 @@ @interface ExtendedTouchTargetButton : UIButton @end -#endif // IOS_CHROME_BROWSER_UI_LOCATION_BAR_EXTENDED_TOUCH_TARGET_BUTTON_H_ +#endif // IOS_CHROME_BROWSER_UI_ELEMENTS_EXTENDED_TOUCH_TARGET_BUTTON_H_
diff --git a/ios/chrome/browser/ui/location_bar/extended_touch_target_button.mm b/ios/chrome/browser/ui/elements/extended_touch_target_button.mm similarity index 92% rename from ios/chrome/browser/ui/location_bar/extended_touch_target_button.mm rename to ios/chrome/browser/ui/elements/extended_touch_target_button.mm index 06707976..a8504ac 100644 --- a/ios/chrome/browser/ui/location_bar/extended_touch_target_button.mm +++ b/ios/chrome/browser/ui/elements/extended_touch_target_button.mm
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#import "ios/chrome/browser/ui/location_bar/extended_touch_target_button.h" +#import "ios/chrome/browser/ui/elements/extended_touch_target_button.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support."
diff --git a/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm b/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm index d8c6d167..e08aa41 100644 --- a/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm +++ b/ios/chrome/browser/ui/infobars/confirm_infobar_view.mm
@@ -17,7 +17,6 @@ #import "ios/chrome/browser/ui/infobars/infobar_constants.h" #import "ios/chrome/browser/ui/util/label_link_controller.h" #import "ios/chrome/browser/ui/util/named_guide.h" -#include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #include "ios/chrome/grit/ios_theme_resources.h" #import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" @@ -771,11 +770,7 @@ } - (void)resetBackground { - if (IsUIRefreshPhase1Enabled()) { - self.backgroundColor = UIColorFromRGB(kInfobarBackgroundColor); - } else { - self.backgroundColor = [UIColor whiteColor]; - } + self.backgroundColor = UIColorFromRGB(kInfobarBackgroundColor); CGFloat shadowY = 0; shadowY = -[shadow_ image].size.height; // Shadow above the infobar. [shadow_ setFrame:CGRectMake(0, shadowY, self.bounds.size.width,
diff --git a/ios/chrome/browser/ui/location_bar/BUILD.gn b/ios/chrome/browser/ui/location_bar/BUILD.gn index 7671f33e..40702c59 100644 --- a/ios/chrome/browser/ui/location_bar/BUILD.gn +++ b/ios/chrome/browser/ui/location_bar/BUILD.gn
@@ -5,8 +5,6 @@ source_set("location_bar") { configs += [ "//build/config/compiler:enable_arc" ] sources = [ - "extended_touch_target_button.h", - "extended_touch_target_button.mm", "location_bar_consumer.h", "location_bar_coordinator.h", "location_bar_coordinator.mm", @@ -47,6 +45,7 @@ "//ios/chrome/browser/ui", "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/elements", "//ios/chrome/browser/ui/fullscreen", "//ios/chrome/browser/ui/fullscreen:ui", "//ios/chrome/browser/ui/infobars:feature_flags",
diff --git a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm index 5cca7773..103dc1c 100644 --- a/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm +++ b/ios/chrome/browser/ui/location_bar/location_bar_steady_view.mm
@@ -5,8 +5,8 @@ #import "ios/chrome/browser/ui/location_bar/location_bar_steady_view.h" #include "components/strings/grit/components_strings.h" +#import "ios/chrome/browser/ui/elements/extended_touch_target_button.h" #import "ios/chrome/browser/ui/infobars/infobar_feature.h" -#import "ios/chrome/browser/ui/location_bar/extended_touch_target_button.h" #import "ios/chrome/browser/ui/omnibox/omnibox_constants.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" #import "ios/chrome/browser/ui/util/dynamic_type_util.h"
diff --git a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn index a69ac85..71209a57 100644 --- a/ios/chrome/browser/ui/omnibox/popup/BUILD.gn +++ b/ios/chrome/browser/ui/omnibox/popup/BUILD.gn
@@ -68,6 +68,7 @@ "//ios/chrome/app/strings:ios_strings_grit", "//ios/chrome/app/theme", "//ios/chrome/browser/ui/commands", + "//ios/chrome/browser/ui/elements", "//ios/chrome/browser/ui/omnibox:omnibox_popup_shared", "//ios/chrome/browser/ui/toolbar/buttons", "//ios/chrome/browser/ui/toolbar/public",
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.h b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.h index 0fa9792..c12c282bb 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.h +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.h
@@ -8,6 +8,7 @@ #import <UIKit/UIKit.h> @protocol AutocompleteSuggestion; +@protocol ImageRetriever; @class OmniboxPopupRowCell; namespace { @@ -33,6 +34,8 @@ @property(nonatomic, weak) id<OmniboxPopupRowCellDelegate> delegate; +@property(nonatomic, weak) id<ImageRetriever> imageRetriever; + @end #endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_ROW_CELL_H_
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm index 2cb3127..4db7a8f 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_row_cell.mm
@@ -7,13 +7,16 @@ #include "base/feature_list.h" #include "base/logging.h" #include "components/omnibox/common/omnibox_features.h" +#import "ios/chrome/browser/ui/elements/extended_touch_target_button.h" #import "ios/chrome/browser/ui/omnibox/popup/autocomplete_suggestion.h" +#import "ios/chrome/browser/ui/omnibox/popup/image_retriever.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_truncating_label.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #include "ios/chrome/grit/ios_strings.h" #include "ios/chrome/grit/ios_theme_resources.h" #include "ui/base/l10n/l10n_util.h" +#include "url/gurl.h" #if !defined(__has_feature) || !__has_feature(objc_arc) #error "This file requires ARC support." @@ -24,10 +27,9 @@ const CGFloat kLeadingMarginIpad = 183; const CGFloat kTextTopMargin = 6; const CGFloat kTextLeadingMargin = 10; -const CGFloat kTextTrailingMargin = -12; const CGFloat kImageViewSize = 28; const CGFloat kImageViewCornerRadius = 7; -const CGFloat kTrailingButtonSize = 48; +const CGFloat kTrailingButtonSize = 24; const CGFloat kTrailingButtonTrailingMargin = 4; NSString* const kOmniboxPopupRowSwitchTabAccessibilityIdentifier = @@ -53,8 +55,11 @@ @property(nonatomic, strong) UILabel* detailAnswerLabel; // Image view for the leading image (only appears on iPad). @property(nonatomic, strong) UIImageView* leadingImageView; -// Trailing button for appending suggestion into omnibox. -@property(nonatomic, strong) UIButton* trailingButton; +// Trailing button for appending suggestion into omnibox or switching to open +// tab. +@property(nonatomic, strong) ExtendedTouchTargetButton* trailingButton; +// Trailing image view for images from suggestions (e.g. weather). +@property(nonatomic, strong) UIImageView* answerImageView; @end @@ -88,15 +93,20 @@ _leadingImageView.contentMode = UIViewContentModeCenter; _leadingImageView.layer.cornerRadius = kImageViewCornerRadius; - _trailingButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _trailingButton = + [ExtendedTouchTargetButton buttonWithType:UIButtonTypeCustom]; _trailingButton.translatesAutoresizingMaskIntoConstraints = NO; [_trailingButton addTarget:self action:@selector(trailingButtonTapped) forControlEvents:UIControlEventTouchUpInside]; - [_trailingButton setContentMode:UIViewContentModeRight]; - // The trailing button also shows answer images. In that case, the - // button will be disabled, but the image shouldn't be dimmed. - _trailingButton.adjustsImageWhenDisabled = NO; + + _answerImageView = [[UIImageView alloc] initWithImage:nil]; + _answerImageView.translatesAutoresizingMaskIntoConstraints = NO; + [_answerImageView + setContentHuggingPriority:UILayoutPriorityDefaultHigh + forAxis:UILayoutConstraintAxisHorizontal]; + [_answerImageView setContentHuggingPriority:UILayoutPriorityDefaultHigh + forAxis:UILayoutConstraintAxisVertical]; _incognito = NO; @@ -135,7 +145,7 @@ constraintEqualToAnchor:self.leadingImageView.trailingAnchor constant:kTextLeadingMargin], // Use greater than or equal constraints because there may be a trailing - // button here. + // view here. [self.contentView.trailingAnchor constraintGreaterThanOrEqualToAnchor:self.textStackView.trailingAnchor], // Top space should be at least the given top margin, but can be more if @@ -146,24 +156,42 @@ [self.textStackView.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor], ]]; + + // If optional views have internal constraints (height is constant, etc.), + // set those up here. + [NSLayoutConstraint activateConstraints:@[ + [self.trailingButton.heightAnchor + constraintEqualToConstant:kTrailingButtonSize], + [self.trailingButton.widthAnchor + constraintEqualToAnchor:self.trailingButton.heightAnchor], + ]]; } // Add the trailing button as a subview and setup its constraints. - (void)setupTrailingButtonLayout { [self.contentView addSubview:self.trailingButton]; [NSLayoutConstraint activateConstraints:@[ - [self.trailingButton.heightAnchor - constraintEqualToConstant:kTrailingButtonSize], - [self.trailingButton.widthAnchor - constraintEqualToConstant:kTrailingButtonSize], [self.trailingButton.centerYAnchor constraintEqualToAnchor:self.contentView.centerYAnchor], [self.contentView.trailingAnchor constraintEqualToAnchor:self.trailingButton.trailingAnchor constant:kTrailingButtonTrailingMargin], [self.trailingButton.leadingAnchor - constraintEqualToAnchor:self.textStackView.trailingAnchor - constant:kTextTrailingMargin], + constraintEqualToAnchor:self.textStackView.trailingAnchor], + ]]; +} + +// Add the answer image view as a subview and setup its constraints. +- (void)setupAnswerImageViewLayout { + [self.contentView addSubview:self.answerImageView]; + [NSLayoutConstraint activateConstraints:@[ + [self.answerImageView.centerYAnchor + constraintEqualToAnchor:self.contentView.centerYAnchor], + [self.contentView.trailingAnchor + constraintEqualToAnchor:self.answerImageView.trailingAnchor + constant:kTrailingButtonTrailingMargin], + [self.answerImageView.leadingAnchor + constraintEqualToAnchor:self.textStackView.trailingAnchor], ]]; } @@ -181,6 +209,8 @@ // Remove optional views. [self.trailingButton setImage:nil forState:UIControlStateNormal]; [self.trailingButton removeFromSuperview]; + self.answerImageView.image = nil; + [self.answerImageView removeFromSuperview]; [self.detailTruncatingLabel removeFromSuperview]; [self.detailAnswerLabel removeFromSuperview]; @@ -216,11 +246,17 @@ } } - if (self.suggestion.hasImage || self.suggestion.isAppendable || - self.suggestion.isTabMatch) { + [self setupLeadingImageView]; + + if (self.suggestion.hasImage) { + [self setupAnswerImageView]; + } else if (self.suggestion.isAppendable || self.suggestion.isTabMatch) { [self setupTrailingButton]; } +} +// Populate the leading image view with the correct icon and color. +- (void)setupLeadingImageView { self.leadingImageView.image = self.suggestion.suggestionTypeIcon; self.leadingImageView.backgroundColor = self.incognito ? [UIColor colorWithWhite:1 alpha:0.05] @@ -230,16 +266,28 @@ : [UIColor colorWithWhite:0 alpha:0.33]; } +// Setup the answer image view. This includes both setting up its layout and +// populating the image correctly. +- (void)setupAnswerImageView { + [self setupAnswerImageViewLayout]; + __weak OmniboxPopupRowCell* weakSelf = self; + GURL imageURL = self.suggestion.imageURL; + [self.imageRetriever fetchImage:imageURL + completion:^(UIImage* image) { + // Make sure cell is still displaying the same + // suggestion. + if (weakSelf.suggestion.imageURL != imageURL) { + return; + } + weakSelf.answerImageView.image = image; + }]; +} + +// Setup the trailing button. This includes both setting up the button's layout +// and popuplating it with the correct image and color. - (void)setupTrailingButton { [self setupTrailingButtonLayout]; - // If there's an image, put it in the button, but disable interaction. - if (self.suggestion.hasImage) { - self.trailingButton.enabled = NO; - [self.trailingButton setImage:nil forState:UIControlStateNormal]; - return; - } - // Show append button for search history/search suggestions or // switch-to-open-tab as the right control element (aka an accessory element // of a table view cell). @@ -276,7 +324,6 @@ trailingButtonImage = [trailingButtonImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - self.trailingButton.enabled = YES; [self.trailingButton setImage:trailingButtonImage forState:UIControlStateNormal]; if (base::FeatureList::IsEnabled(omnibox::kOmniboxTabSwitchSuggestions)) {
diff --git a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm index 7208d8e..a984dd68 100644 --- a/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm +++ b/ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.mm
@@ -65,6 +65,7 @@ [cell setupWithAutocompleteSuggestion:self.currentResult[indexPath.row] incognito:self.incognito]; cell.delegate = self; + cell.imageRetriever = self.imageRetriever; return cell; }
diff --git a/ios/chrome/browser/ui/settings/BUILD.gn b/ios/chrome/browser/ui/settings/BUILD.gn index c088c07..c50247b 100644 --- a/ios/chrome/browser/ui/settings/BUILD.gn +++ b/ios/chrome/browser/ui/settings/BUILD.gn
@@ -126,6 +126,7 @@ "//ios/chrome/browser/browser_state:browser_state_impl", "//ios/chrome/browser/browsing_data", "//ios/chrome/browser/content_settings", + "//ios/chrome/browser/favicon", "//ios/chrome/browser/feature_engagement", "//ios/chrome/browser/history", "//ios/chrome/browser/mailto:feature_flags", @@ -170,6 +171,7 @@ "//ios/chrome/browser/voice", "//ios/chrome/browser/web:web", "//ios/chrome/common", + "//ios/chrome/common/favicon", "//ios/public/provider/chrome/browser", "//ios/public/provider/chrome/browser/images", "//ios/public/provider/chrome/browser/mailto",
diff --git a/ios/chrome/browser/ui/settings/cells/BUILD.gn b/ios/chrome/browser/ui/settings/cells/BUILD.gn index b9ebeb3..88f3b8e9 100644 --- a/ios/chrome/browser/ui/settings/cells/BUILD.gn +++ b/ios/chrome/browser/ui/settings/cells/BUILD.gn
@@ -18,6 +18,8 @@ "copied_to_chrome_item.mm", "passphrase_error_item.h", "passphrase_error_item.mm", + "search_engine_item.h", + "search_engine_item.mm", "settings_image_detail_text_cell.h", "settings_image_detail_text_cell.mm", "settings_image_detail_text_item.h", @@ -45,6 +47,7 @@ "//ios/chrome/app/strings", "//ios/chrome/browser/browsing_data", "//ios/chrome/browser/ui", + "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/collection_view/cells", "//ios/chrome/browser/ui/colors", "//ios/chrome/browser/ui/icons", @@ -79,6 +82,7 @@ "clear_browsing_data_item_unittest.mm", "copied_to_chrome_item_unittest.mm", "passphrase_error_item_unittest.mm", + "search_engine_item_unittest.mm", "settings_multiline_detail_item_unittest.mm", "version_item_unittest.mm", ] @@ -95,9 +99,11 @@ "//ios/chrome/browser/browser_state:test_support", "//ios/chrome/browser/browsing_data", "//ios/chrome/browser/browsing_data:counters", + "//ios/chrome/browser/ui:feature_flags", "//ios/chrome/browser/ui/collection_view/cells", "//ios/chrome/browser/ui/collection_view/cells:test_support", "//ios/chrome/browser/ui/table_view:styler", + "//ios/chrome/browser/ui/table_view/cells", "//ios/web/public/test:test", "//testing/gtest", "//ui/base",
diff --git a/ios/chrome/browser/ui/settings/cells/search_engine_item.h b/ios/chrome/browser/ui/settings/cells/search_engine_item.h new file mode 100644 index 0000000..d5835b5 --- /dev/null +++ b/ios/chrome/browser/ui/settings/cells/search_engine_item.h
@@ -0,0 +1,30 @@ +// 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. + +#ifndef IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_SEARCH_ENGINE_ITEM_H_ +#define IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_SEARCH_ENGINE_ITEM_H_ + +#import <UIKit/UIKit.h> + +#import "ios/chrome/browser/ui/table_view/cells/table_view_item.h" + +class GURL; + +// SearchEngineItem contains the model data for a TableViewURLCell. +@interface SearchEngineItem : TableViewItem + +// The text for the title. +@property(nonatomic, readwrite, copy) NSString* text; +// The text for the subtitle. +@property(nonatomic, readwrite, copy) NSString* detailText; +// The URL to fetch the favicon. This can be the favicon's URL, or a "fake" web +// page URL created by filling empty query word into the search engine's +// searchable URL template(e.g. "http://www.google.com/?q="). +@property(nonatomic, assign) GURL URL; +// Identifier to match a URLItem with its URLCell. +@property(nonatomic, readonly, copy) NSString* uniqueIdentifier; + +@end + +#endif // IOS_CHROME_BROWSER_UI_SETTINGS_CELLS_SEARCH_ENGINE_ITEM_H_
diff --git a/ios/chrome/browser/ui/settings/cells/search_engine_item.mm b/ios/chrome/browser/ui/settings/cells/search_engine_item.mm new file mode 100644 index 0000000..dabaa8b --- /dev/null +++ b/ios/chrome/browser/ui/settings/cells/search_engine_item.mm
@@ -0,0 +1,86 @@ +// 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. + +#import "ios/chrome/browser/ui/settings/cells/search_engine_item.h" + +#include "base/mac/foundation_util.h" +#include "base/strings/sys_string_conversions.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_cells_constants.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" +#include "ios/chrome/browser/ui/ui_feature_flags.h" +#include "ios/chrome/browser/ui/util/uikit_ui_util.h" +#include "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +#pragma mark - SearchEngineItem + +@interface SearchEngineItem () + +// Redefined as read write. +@property(nonatomic, readwrite, copy) NSString* uniqueIdentifier; + +@end + +@implementation SearchEngineItem + +- (instancetype)initWithType:(NSInteger)type { + self = [super initWithType:type]; + if (self) { + // TODO(crbug.com/910525): Remove usage of TableViewDetailTextCell after the + // feature is launched. + if (base::FeatureList::IsEnabled(kDisplaySearchEngineFavicon)) { + self.cellClass = TableViewURLCell.class; + } else { + self.cellClass = TableViewDetailTextCell.class; + } + } + return self; +} + +- (void)configureCell:(TableViewCell*)tableCell + withStyler:(ChromeTableViewStyler*)styler { + [super configureCell:tableCell withStyler:styler]; + + self.uniqueIdentifier = base::SysUTF8ToNSString(self.URL.host()); + + // TODO(crbug.com/910525): Remove usage of TableViewDetailTextCell after the + // feature is launched. + if (base::FeatureList::IsEnabled(kDisplaySearchEngineFavicon)) { + TableViewURLCell* cell = + base::mac::ObjCCastStrict<TableViewURLCell>(tableCell); + + cell.titleLabel.text = self.text; + cell.URLLabel.text = self.detailText; + cell.cellUniqueIdentifier = self.uniqueIdentifier; + cell.accessibilityTraits |= UIAccessibilityTraitButton; + + if (styler.cellTitleColor) + cell.titleLabel.textColor = styler.cellTitleColor; + + [cell configureUILayout]; + } else { + TableViewDetailTextCell* cell = + base::mac::ObjCCastStrict<TableViewDetailTextCell>(tableCell); + + cell.textLabel.text = self.text; + cell.detailTextLabel.text = self.detailText; + cell.accessibilityTraits |= UIAccessibilityTraitButton; + + if (styler.cellTitleColor) { + cell.textLabel.textColor = styler.cellTitleColor; + } else { + cell.textLabel.textColor = + UIColorFromRGB(kTableViewTextLabelColorLightGrey); + } + cell.detailTextLabel.textColor = + UIColorFromRGB(kTableViewSecondaryLabelLightGrayTextColor); + } +} + +@end
diff --git a/ios/chrome/browser/ui/settings/cells/search_engine_item_unittest.mm b/ios/chrome/browser/ui/settings/cells/search_engine_item_unittest.mm new file mode 100644 index 0000000..de2aac1 --- /dev/null +++ b/ios/chrome/browser/ui/settings/cells/search_engine_item_unittest.mm
@@ -0,0 +1,72 @@ +// 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. + +#import "ios/chrome/browser/ui/settings/cells/search_engine_item.h" + +#include "base/mac/foundation_util.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h" +#import "ios/chrome/browser/ui/table_view/chrome_table_view_styler.h" +#include "ios/chrome/browser/ui/ui_feature_flags.h" +#include "net/base/mac/url_conversions.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/gtest_mac.h" +#include "testing/platform_test.h" +#include "url/gurl.h" + +#if !defined(__has_feature) || !__has_feature(objc_arc) +#error "This file requires ARC support." +#endif + +namespace { +using SearchEngineItemTest = PlatformTest; +} // namespace + +// Tests that the UILabels are set properly after a call to |configureCell:|. +TEST_F(SearchEngineItemTest, BasicProperties) { + NSString* text = @"Title text"; + NSString* detailText = @"www.google.com"; + GURL URL = net::GURLWithNSURL([NSURL URLWithString:detailText]); + + SearchEngineItem* item = [[SearchEngineItem alloc] initWithType:0]; + item.text = text; + item.detailText = detailText; + item.URL = URL; + item.accessoryType = UITableViewCellAccessoryCheckmark; + + id cell = [[[item cellClass] alloc] init]; + // TODO(crbug.com/910525): Remove usage of TableViewDetailTextCell after the + // feature is launched. + if (base::FeatureList::IsEnabled(kDisplaySearchEngineFavicon)) { + ASSERT_TRUE([cell isMemberOfClass:[TableViewURLCell class]]); + + TableViewURLCell* URLCell = + base::mac::ObjCCastStrict<TableViewURLCell>(cell); + EXPECT_FALSE(URLCell.titleLabel.text); + EXPECT_FALSE(URLCell.URLLabel.text); + EXPECT_EQ(item.uniqueIdentifier, URLCell.cellUniqueIdentifier); + EXPECT_EQ(UITableViewCellAccessoryNone, URLCell.accessoryType); + + ChromeTableViewStyler* styler = [[ChromeTableViewStyler alloc] init]; + [item configureCell:URLCell withStyler:styler]; + EXPECT_NSEQ(text, URLCell.titleLabel.text); + EXPECT_NSEQ(detailText, URLCell.URLLabel.text); + EXPECT_EQ(item.uniqueIdentifier, URLCell.cellUniqueIdentifier); + EXPECT_EQ(UITableViewCellAccessoryCheckmark, URLCell.accessoryType); + } else { + ASSERT_TRUE([cell isMemberOfClass:[TableViewDetailTextCell class]]); + + TableViewDetailTextCell* textCell = + base::mac::ObjCCastStrict<TableViewDetailTextCell>(cell); + EXPECT_FALSE(textCell.textLabel.text); + EXPECT_FALSE(textCell.detailTextLabel.text); + EXPECT_EQ(UITableViewCellAccessoryNone, textCell.accessoryType); + + ChromeTableViewStyler* styler = [[ChromeTableViewStyler alloc] init]; + [item configureCell:textCell withStyler:styler]; + EXPECT_NSEQ(text, textCell.textLabel.text); + EXPECT_NSEQ(detailText, textCell.detailTextLabel.text); + EXPECT_EQ(UITableViewCellAccessoryCheckmark, textCell.accessoryType); + } +}
diff --git a/ios/chrome/browser/ui/settings/search_engine_table_view_controller.mm b/ios/chrome/browser/ui/settings/search_engine_table_view_controller.mm index 0c3de9da..9876650 100644 --- a/ios/chrome/browser/ui/settings/search_engine_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/search_engine_table_view_controller.mm
@@ -12,11 +12,15 @@ #include "components/search_engines/template_url_service.h" #include "components/search_engines/template_url_service_observer.h" #include "ios/chrome/browser/browser_state/chrome_browser_state.h" +#import "ios/chrome/browser/favicon/favicon_loader.h" +#include "ios/chrome/browser/favicon/ios_chrome_favicon_loader_factory.h" #import "ios/chrome/browser/search_engines/search_engine_observer_bridge.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" -#import "ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.h" +#import "ios/chrome/browser/ui/settings/cells/search_engine_item.h" #import "ios/chrome/browser/ui/table_view/cells/table_view_text_header_footer_item.h" +#import "ios/chrome/browser/ui/table_view/cells/table_view_url_item.h" #include "ios/chrome/browser/ui/ui_feature_flags.h" +#import "ios/chrome/common/favicon/favicon_view.h" #include "ios/chrome/grit/ios_strings.h" #include "ui/base/l10n/l10n_util_mac.h" @@ -25,18 +29,19 @@ #endif namespace { - typedef NS_ENUM(NSInteger, SectionIdentifier) { - SectionIdentifierPriorSearchEngines = kSectionIdentifierEnumZero, - SectionIdentifierCustomSearchEngines, + SectionIdentifierFirstList = kSectionIdentifierEnumZero, + SectionIdentifierSecondList, }; typedef NS_ENUM(NSInteger, ItemType) { - ItemTypePriorSearchEnginesEngine = kItemTypeEnumZero, - ItemTypeCustomSearchEnginesEngineHeader, - ItemTypeCustomSearchEnginesEngine, + ItemTypePrepopulatedEngine = kItemTypeEnumZero, + ItemTypeHeader, + ItemTypeCustomEngine, }; +const CGFloat kTableViewSeparatorLeadingInset = 56; +const CGFloat kTableViewSeparatorTrailingInset = 16; constexpr base::TimeDelta kMaxVisitAge = base::TimeDelta::FromDays(2); const size_t kMaxcustomSearchEngines = 3; const char kUmaSelectDefaultSearchEngine[] = @@ -55,10 +60,13 @@ // The first list in the page which contains prepopulted search engines and // search engines that are created by policy, and possibly one custom search // engine if it's selected as default search engine. - std::vector<TemplateURL*> _priorSearchEngines; + std::vector<TemplateURL*> _firstList; // The second list in the page which contains all remaining custom search // engines. - std::vector<TemplateURL*> _customSearchEngines; + std::vector<TemplateURL*> _secondList; + // FaviconLoader is a keyed service that uses LargeIconService to retrieve + // favicon images. + FaviconLoader* _faviconLoader; } #pragma mark Initialization @@ -76,6 +84,8 @@ _observer = std::make_unique<SearchEngineObserverBridge>(self, _templateURLService); _templateURLService->Load(); + _faviconLoader = + IOSChromeFaviconLoaderFactory::GetForBrowserState(browserState); [self setTitle:l10n_util::GetNSString(IDS_IOS_SEARCH_ENGINE_SETTING_TITLE)]; } return self; @@ -86,6 +96,12 @@ - (void)viewDidLoad { [super viewDidLoad]; + if (base::FeatureList::IsEnabled(kDisplaySearchEngineFavicon)) { + self.tableView.separatorInset = + UIEdgeInsetsMake(0, kTableViewSeparatorLeadingInset, 0, + kTableViewSeparatorTrailingInset); + } + [self loadModel]; } @@ -97,44 +113,30 @@ [self loadSearchEngines]; // Add prior search engines. - if (_priorSearchEngines.size() > 0) { - [model addSectionWithIdentifier:SectionIdentifierPriorSearchEngines]; + if (_firstList.size() > 0) { + [model addSectionWithIdentifier:SectionIdentifierFirstList]; - for (TemplateURL* url : _priorSearchEngines) { - TableViewDetailTextItem* engine = [[TableViewDetailTextItem alloc] - initWithType:ItemTypePriorSearchEnginesEngine]; - engine.text = base::SysUTF16ToNSString(url->short_name()); - engine.detailText = base::SysUTF16ToNSString(url->keyword()); - if (url == _templateURLService->GetDefaultSearchProvider()) { - [engine setAccessoryType:UITableViewCellAccessoryCheckmark]; - } - [model addItem:engine - toSectionWithIdentifier:SectionIdentifierPriorSearchEngines]; + for (const TemplateURL* templateURL : _firstList) { + [model addItem:[self createSearchEngineItemFromTemplateURL:templateURL] + toSectionWithIdentifier:SectionIdentifierFirstList]; } } // Add custom search engines. - if (_customSearchEngines.size() > 0) { - [model addSectionWithIdentifier:SectionIdentifierCustomSearchEngines]; + if (_secondList.size() > 0) { + [model addSectionWithIdentifier:SectionIdentifierSecondList]; TableViewTextHeaderFooterItem* header = - [[TableViewTextHeaderFooterItem alloc] - initWithType:ItemTypeCustomSearchEnginesEngineHeader]; + [[TableViewTextHeaderFooterItem alloc] initWithType:ItemTypeHeader]; header.text = l10n_util::GetNSString( IDS_IOS_SEARCH_ENGINE_SETTING_CUSTOM_SECTION_HEADER); [model setHeader:header - forSectionWithIdentifier:SectionIdentifierCustomSearchEngines]; + forSectionWithIdentifier:SectionIdentifierSecondList]; - for (TemplateURL* url : _customSearchEngines) { - TableViewDetailTextItem* engine = [[TableViewDetailTextItem alloc] - initWithType:ItemTypeCustomSearchEnginesEngine]; - engine.text = base::SysUTF16ToNSString(url->short_name()); - engine.detailText = base::SysUTF16ToNSString(url->keyword()); - if (url == _templateURLService->GetDefaultSearchProvider()) { - [engine setAccessoryType:UITableViewCellAccessoryCheckmark]; - } - [model addItem:engine - toSectionWithIdentifier:SectionIdentifierCustomSearchEngines]; + for (const TemplateURL* templateURL : _secondList) { + DCHECK(templateURL->prepopulate_id() == 0); + [model addItem:[self createSearchEngineItemFromTemplateURL:templateURL] + toSectionWithIdentifier:SectionIdentifierSecondList]; } } } @@ -146,100 +148,147 @@ [super tableView:tableView didSelectRowAtIndexPath:indexPath]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; TableViewModel* model = self.tableViewModel; - - // Only handle taps on search engine items. TableViewItem* selectedItem = [model itemAtIndexPath:indexPath]; - if (selectedItem.type != ItemTypePriorSearchEnginesEngine && - selectedItem.type != ItemTypeCustomSearchEnginesEngine) { - return; - } + + // Only search engine items can be selected. + DCHECK(selectedItem.type == ItemTypePrepopulatedEngine || + selectedItem.type == ItemTypeCustomEngine); // Do nothing if the tapped engine was already the default. - TableViewDetailTextItem* selectedTextItem = - base::mac::ObjCCastStrict<TableViewDetailTextItem>(selectedItem); + SearchEngineItem* selectedTextItem = + base::mac::ObjCCastStrict<SearchEngineItem>(selectedItem); if (selectedTextItem.accessoryType == UITableViewCellAccessoryCheckmark) { + [tableView deselectRowAtIndexPath:indexPath animated:YES]; return; } - NSMutableArray* modifiedItems = [NSMutableArray array]; - // Iterate through the engines and remove the checkmark from any that have it. - if ([model - hasSectionForSectionIdentifier:SectionIdentifierPriorSearchEngines]) { + if ([model hasSectionForSectionIdentifier:SectionIdentifierFirstList]) { for (TableViewItem* item in - [model itemsInSectionWithIdentifier: - SectionIdentifierPriorSearchEngines]) { - if (item.type != ItemTypePriorSearchEnginesEngine) { - continue; - } - TableViewDetailTextItem* textItem = - base::mac::ObjCCastStrict<TableViewDetailTextItem>(item); + [model itemsInSectionWithIdentifier:SectionIdentifierFirstList]) { + SearchEngineItem* textItem = + base::mac::ObjCCastStrict<SearchEngineItem>(item); if (textItem.accessoryType == UITableViewCellAccessoryCheckmark) { textItem.accessoryType = UITableViewCellAccessoryNone; - [modifiedItems addObject:textItem]; + UITableViewCell* cell = + [tableView cellForRowAtIndexPath:[model indexPathForItem:item]]; + cell.accessoryType = UITableViewCellAccessoryNone; } } } - if ([model hasSectionForSectionIdentifier: - SectionIdentifierCustomSearchEngines]) { + if ([model hasSectionForSectionIdentifier:SectionIdentifierSecondList]) { for (TableViewItem* item in - [model itemsInSectionWithIdentifier: - SectionIdentifierCustomSearchEngines]) { - if (item.type != ItemTypeCustomSearchEnginesEngine) { - continue; - } - TableViewDetailTextItem* textItem = - base::mac::ObjCCastStrict<TableViewDetailTextItem>(item); + [model itemsInSectionWithIdentifier:SectionIdentifierSecondList]) { + DCHECK(item.type == ItemTypeCustomEngine); + SearchEngineItem* textItem = + base::mac::ObjCCastStrict<SearchEngineItem>(item); if (textItem.accessoryType == UITableViewCellAccessoryCheckmark) { textItem.accessoryType = UITableViewCellAccessoryNone; - [modifiedItems addObject:textItem]; + UITableViewCell* cell = + [tableView cellForRowAtIndexPath:[model indexPathForItem:item]]; + cell.accessoryType = UITableViewCellAccessoryNone; } } } // Show the checkmark on the new default engine. - TableViewDetailTextItem* newDefaultEngine = - base::mac::ObjCCastStrict<TableViewDetailTextItem>( + + SearchEngineItem* newDefaultEngine = + base::mac::ObjCCastStrict<SearchEngineItem>( [model itemAtIndexPath:indexPath]); newDefaultEngine.accessoryType = UITableViewCellAccessoryCheckmark; - [modifiedItems addObject:newDefaultEngine]; + UITableViewCell* cell = [tableView cellForRowAtIndexPath:indexPath]; + cell.accessoryType = UITableViewCellAccessoryCheckmark; // Set the new engine as the default. - if (selectedItem.type == ItemTypePriorSearchEnginesEngine) - [self setDefaultToPriorSearchEngineAtIndex: - [model indexInItemTypeForIndexPath:indexPath]]; - else - [self setDefaultToCustomSearchEngineAtIndex: - [model indexInItemTypeForIndexPath:indexPath]]; - - [self reconfigureCellsForItems:modifiedItems]; + _updatingBackend = YES; + if (indexPath.section == + [model sectionForSectionIdentifier:SectionIdentifierFirstList]) { + _templateURLService->SetUserSelectedDefaultSearchProvider( + _firstList[indexPath.row]); + } else { + _templateURLService->SetUserSelectedDefaultSearchProvider( + _secondList[indexPath.row]); + } + [self recordUmaOfDefaultSearchEngine]; + _updatingBackend = NO; } -#pragma mark Internal methods +#pragma mark - UITableViewDataSource + +- (UITableViewCell*)tableView:(UITableView*)tableView + cellForRowAtIndexPath:(NSIndexPath*)indexPath { + UITableViewCell* cell = [super tableView:tableView + cellForRowAtIndexPath:indexPath]; + TableViewItem* item = [self.tableViewModel itemAtIndexPath:indexPath]; + DCHECK(item.type == ItemTypePrepopulatedEngine || + item.type == ItemTypeCustomEngine); + if (base::FeatureList::IsEnabled(kDisplaySearchEngineFavicon)) { + SearchEngineItem* engineItem = + base::mac::ObjCCastStrict<SearchEngineItem>(item); + TableViewURLCell* urlCell = + base::mac::ObjCCastStrict<TableViewURLCell>(cell); + + FaviconAttributes* cachedAttributes = nil; + if (item.type == ItemTypePrepopulatedEngine) { + cachedAttributes = _faviconLoader->FaviconForPageUrl( + engineItem.URL, kFaviconPreferredSize, kFaviconMinSize, + /*fallback_to_google_server=*/YES, ^(FaviconAttributes* attributes) { + // Only set favicon if the cell hasn't been reused. + if (urlCell.cellUniqueIdentifier == engineItem.uniqueIdentifier) { + DCHECK(attributes); + [urlCell.faviconView configureWithAttributes:attributes]; + } + }); + } else { + cachedAttributes = _faviconLoader->FaviconForIconUrl( + engineItem.URL, kFaviconPreferredSize, kFaviconMinSize, + ^(FaviconAttributes* attributes) { + // Only set favicon if the cell hasn't been reused. + if (urlCell.cellUniqueIdentifier == engineItem.uniqueIdentifier) { + DCHECK(attributes); + [urlCell.faviconView configureWithAttributes:attributes]; + } + }); + } + DCHECK(cachedAttributes); + [urlCell.faviconView configureWithAttributes:cachedAttributes]; + } + return cell; +} + +#pragma mark - SearchEngineObserving + +- (void)searchEngineChanged { + if (!_updatingBackend) + [self reloadData]; +} + +#pragma mark - Private methods // Loads all TemplateURLs from TemplateURLService and classifies them into -// |_priorSearchEngines| and |_customSearchEngines|. If a TemplateURL is +// |_firstList| and |_secondList|. If a TemplateURL is // prepopulated, created by policy or the default search engine, it will get // into the first list, otherwise the second list. - (void)loadSearchEngines { std::vector<TemplateURL*> urls = _templateURLService->GetTemplateURLs(); - _priorSearchEngines.clear(); - _priorSearchEngines.reserve(urls.size()); - _customSearchEngines.clear(); - _customSearchEngines.reserve(urls.size()); + _firstList.clear(); + _firstList.reserve(urls.size()); + _secondList.clear(); + _secondList.reserve(urls.size()); // Classify TemplateURLs. for (TemplateURL* url : urls) { if (_templateURLService->IsPrepopulatedOrCreatedByPolicy(url) || url == _templateURLService->GetDefaultSearchProvider()) - _priorSearchEngines.push_back(url); + _firstList.push_back(url); else - _customSearchEngines.push_back(url); + _secondList.push_back(url); } // Sort |fixedCutomeSearchEngines_| by TemplateURL's prepopulate_id. If // prepopulated_id == 0, it's a custom search engine and should be put in the // end of the list. - std::sort(_priorSearchEngines.begin(), _priorSearchEngines.end(), + std::sort(_firstList.begin(), _firstList.end(), [](const TemplateURL* lhs, const TemplateURL* rhs) { if (lhs->prepopulate_id() == 0) return false; @@ -248,11 +297,10 @@ return lhs->prepopulate_id() < rhs->prepopulate_id(); }); - // Partially sort |_customSearchEngines| by TemplateURL's last_visited time. - auto begin = _customSearchEngines.begin(); - auto end = _customSearchEngines.end(); - auto pivot = - begin + std::min(kMaxcustomSearchEngines, _customSearchEngines.size()); + // Partially sort |_secondList| by TemplateURL's last_visited time. + auto begin = _secondList.begin(); + auto end = _secondList.end(); + auto pivot = begin + std::min(kMaxcustomSearchEngines, _secondList.size()); std::partial_sort(begin, pivot, end, [](const TemplateURL* lhs, const TemplateURL* rhs) { return lhs->last_visited() > rhs->last_visited(); @@ -263,29 +311,33 @@ auto cutBegin = std::find_if(begin, pivot, [cutoff](const TemplateURL* url) { return url->last_visited() < cutoff; }); - _customSearchEngines.erase(cutBegin, end); + _secondList.erase(cutBegin, end); } -// Sets the search engine at |index| in prior section as default search engine. -- (void)setDefaultToPriorSearchEngineAtIndex:(NSUInteger)index { - DCHECK_GE(index, 0U); - DCHECK_LT(index, _priorSearchEngines.size()); - _updatingBackend = YES; - _templateURLService->SetUserSelectedDefaultSearchProvider( - _priorSearchEngines[index]); - [self recordUmaOfDefaultSearchEngine]; - _updatingBackend = NO; -} - -// Sets the search engine at |index| in custom section as default search engine. -- (void)setDefaultToCustomSearchEngineAtIndex:(NSUInteger)index { - DCHECK_GE(index, 0U); - DCHECK_LT(index, _customSearchEngines.size()); - _updatingBackend = YES; - _templateURLService->SetUserSelectedDefaultSearchProvider( - _customSearchEngines[index]); - [self recordUmaOfDefaultSearchEngine]; - _updatingBackend = NO; +// Creates a SearchEngineItem for |templateURL|. +- (SearchEngineItem*)createSearchEngineItemFromTemplateURL: + (const TemplateURL*)templateURL { + SearchEngineItem* item = nil; + if (templateURL->prepopulate_id() > 0) { + item = [[SearchEngineItem alloc] initWithType:ItemTypePrepopulatedEngine]; + // Fake up a page URL for favicons of prepopulated search engines, since + // favicons may be fetched from Google server which doesn't suppoprt + // icon URL. + std::string emptyPageUrl = templateURL->url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(base::string16()), + _templateURLService->search_terms_data()); + item.URL = GURL(emptyPageUrl); + } else { + item = [[SearchEngineItem alloc] initWithType:ItemTypeCustomEngine]; + // Use icon URL for favicons of custom search engines. + item.URL = templateURL->favicon_url(); + } + item.text = base::SysUTF16ToNSString(templateURL->short_name()); + item.detailText = base::SysUTF16ToNSString(templateURL->keyword()); + if (templateURL == _templateURLService->GetDefaultSearchProvider()) { + [item setAccessoryType:UITableViewCellAccessoryCheckmark]; + } + return item; } // Records the type of the selected default search engine. @@ -297,9 +349,4 @@ SEARCH_ENGINE_MAX); } -- (void)searchEngineChanged { - if (!_updatingBackend) - [self reloadData]; -} - @end
diff --git a/ios/chrome/browser/ui/settings/search_engine_table_view_controller_unittest.mm b/ios/chrome/browser/ui/settings/search_engine_table_view_controller_unittest.mm index beefa3f..3a1d739 100644 --- a/ios/chrome/browser/ui/settings/search_engine_table_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/settings/search_engine_table_view_controller_unittest.mm
@@ -17,7 +17,7 @@ #include "components/sync_preferences/testing_pref_service_syncable.h" #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" #include "ios/chrome/browser/search_engines/template_url_service_factory.h" -#import "ios/chrome/browser/ui/table_view/cells/table_view_detail_text_item.h" +#import "ios/chrome/browser/ui/settings/cells/search_engine_item.h" #import "ios/chrome/browser/ui/table_view/chrome_table_view_controller_test.h" #include "ios/web/public/test/test_web_thread_bundle.h" #include "testing/gtest/include/gtest/gtest.h" @@ -35,6 +35,24 @@ const char kUmaSelectDefaultSearchEngine[] = "Search.iOS.SelectDefaultSearchEngine"; +// Prepopulated search engines. +const std::string kEngineP1Name = "prepopulated-1"; +const GURL kEngineP1Url = GURL("https://p1.com?q={searchTerms}"); +const std::string kEngineP2Name = "prepopulated-2"; +const GURL kEngineP2Url = GURL("https://p2.com?q={searchTerms}"); +const std::string kEngineP3Name = "prepopulated-3"; +const GURL kEngineP3Url = GURL("https://p3.com?q={searchTerms}"); + +// Custom search engines. +const std::string kEngineC1Name = "custom-1"; +const GURL kEngineC1Url = GURL("https://c1.com?q={searchTerms}"); +const std::string kEngineC2Name = "custom-2"; +const GURL kEngineC2Url = GURL("https://c2.com?q={searchTerms}"); +const std::string kEngineC3Name = "custom-3"; +const GURL kEngineC3Url = GURL("https://c3.com?q={searchTerms}"); +const std::string kEngineC4Name = "custom-4"; +const GURL kEngineC4Url = GURL("https://c4.com?q={searchTerms}"); + class SearchEngineTableViewControllerTest : public ChromeTableViewControllerTest { protected: @@ -57,14 +75,20 @@ } // Adds a prepopulated search engine to TemplateURLService. + // |prepopulate_id| should be big enough (>1000) to avoid collision with real + // prepopulated search engines. The collision happens when + // TemplateURLService::SetUserSelectedDefaultSearchProvider is called, in the + // callback of PrefService the DefaultSearchManager will update the searchable + // URL of default search engine from prepopulated search engines list. TemplateURL* AddPriorSearchEngine(const std::string& short_name, - const std::string& keyword, + const GURL& searchable_url, int prepopulate_id, bool set_default) { TemplateURLData data; data.SetShortName(base::ASCIIToUTF16(short_name)); - data.SetURL("https://chromium.test/index.php?q={searchTerms}"); - data.SetKeyword(base::ASCIIToUTF16(keyword)); + data.SetKeyword(base::ASCIIToUTF16(short_name)); + data.SetURL(searchable_url.possibly_invalid_spec()); + data.favicon_url = TemplateURL::GenerateFaviconURL(searchable_url); data.prepopulate_id = prepopulate_id; TemplateURL* url = template_url_service_->Add(std::make_unique<TemplateURL>(data)); @@ -75,13 +99,14 @@ // Adds a custom search engine to TemplateURLService. TemplateURL* AddCustomSearchEngine(const std::string& short_name, - const std::string& keyword, + const GURL& searchable_url, base::Time last_visited_time, bool set_default) { TemplateURLData data; data.SetShortName(base::ASCIIToUTF16(short_name)); - data.SetURL("https://chromium.test/index.php?q={searchTerms}"); - data.SetKeyword(base::ASCIIToUTF16(keyword)); + data.SetKeyword(base::ASCIIToUTF16(short_name)); + data.SetURL(searchable_url.possibly_invalid_spec()); + data.favicon_url = TemplateURL::GenerateFaviconURL(searchable_url); data.last_visited = last_visited_time; TemplateURL* url = template_url_service_->Add(std::make_unique<TemplateURL>(data)); @@ -90,15 +115,77 @@ return url; } - // Checks if a text cell in the TableView has a check mark. - void CheckTextCellChecked(bool expect_checked, int section, int item) { - TableViewDetailTextItem* text_item = - base::mac::ObjCCastStrict<TableViewDetailTextItem>( - GetTableViewItem(section, item)); - ASSERT_TRUE(text_item); - EXPECT_EQ(expect_checked ? UITableViewCellAccessoryCheckmark - : UITableViewCellAccessoryNone, - text_item.accessoryType); + void CheckItem(NSString* expected_text, + NSString* expected_detail_text, + const GURL& expected_url, + bool expected_checked, + int section, + int row) { + SearchEngineItem* item = base::mac::ObjCCastStrict<SearchEngineItem>( + GetTableViewItem(section, row)); + EXPECT_NSEQ(expected_text, item.text); + EXPECT_NSEQ(expected_detail_text, item.detailText); + EXPECT_EQ(expected_url, item.URL); + EXPECT_EQ(expected_checked ? UITableViewCellAccessoryCheckmark + : UITableViewCellAccessoryNone, + item.accessoryType); + } + + // Checks a SearchEngineItem with data from a fabricated TemplateURL. The + // SearchEngineItem in the |row| of |section| should contain a title and a + // subtitle that are equal to |expected_text| and an URL which can be + // generated by filling empty query word into |expected_searchable_url|. If + // |expected_checked| is true, the SearchEngineItem should have a + // UITableViewCellAccessoryCheckmark. + void CheckPrepopulatedItem(const std::string& expected_text, + const GURL& expected_searchable_url, + bool expected_checked, + int section, + int row) { + TemplateURLData data; + data.SetURL(expected_searchable_url.possibly_invalid_spec()); + const std::string expected_url = + TemplateURL(data).url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(base::string16()), + template_url_service_->search_terms_data()); + CheckItem(base::SysUTF8ToNSString(expected_text), + base::SysUTF8ToNSString(expected_text), GURL(expected_url), + expected_checked, section, row); + } + + // Checks a SearchEngineItem with data from a fabricated TemplateURL. The + // SearchEngineItem in the |row| of |section| should contain a title and a + // subtitle that are equal to |expected_text| and an URL + // which can be generated from |expected_searchable_url| by + // TemplateURL::GenerateFaviconURL. If |expected_checked| is true, the + // SearchEngineItem should have a UITableViewCellAccessoryCheckmark. + void CheckCustomItem(const std::string& expected_text, + const GURL& expected_searchable_url, + bool expected_checked, + int section, + int row) { + CheckItem(base::SysUTF8ToNSString(expected_text), + base::SysUTF8ToNSString(expected_text), + TemplateURL::GenerateFaviconURL(expected_searchable_url), + expected_checked, section, row); + } + + // Checks a SearchEngineItem with data from a real prepopulated + // TemplateURL. The SearchEngineItem in the |row| of |section| should + // contain a title equal to |expected_text|, a subtitle equal to + // |expected_detail_text|, and an URL equal to |expected_favicon_url|. If + // |expected_checked| is true, the SearchEngineItem should have a + // UITableViewCellAccessoryCheckmark. + void CheckRealItem(const TemplateURL* turl, + bool expected_checked, + int section, + int row) { + CheckItem(base::SysUTF16ToNSString(turl->short_name()), + base::SysUTF16ToNSString(turl->keyword()), + GURL(turl->url_ref().ReplaceSearchTerms( + TemplateURLRef::SearchTermsArgs(base::string16()), + template_url_service_->search_terms_data())), + expected_checked, section, row); } web::TestWebThreadBundle thread_bundle_; @@ -118,20 +205,20 @@ // and a prepopulated search engine is selected as default. TEST_F(SearchEngineTableViewControllerTest, TestUrlsLoadedWithPrepopulatedSearchEngineAsDefault) { - AddPriorSearchEngine("prepopulated-3", "p3.com", 3, false); - AddPriorSearchEngine("prepopulated-1", "p1.com", 1, false); - AddPriorSearchEngine("prepopulated-2", "p2.com", 2, true); + AddPriorSearchEngine(kEngineP3Name, kEngineP3Url, 1003, false); + AddPriorSearchEngine(kEngineP1Name, kEngineP1Url, 1001, false); + AddPriorSearchEngine(kEngineP2Name, kEngineP2Url, 1002, true); - AddCustomSearchEngine("custom-4", "c4.com", + AddCustomSearchEngine(kEngineC4Name, kEngineC4Url, base::Time::Now() - base::TimeDelta::FromDays(10), false); - AddCustomSearchEngine("custom-1", "c1.com", + AddCustomSearchEngine(kEngineC1Name, kEngineC1Url, base::Time::Now() - base::TimeDelta::FromSeconds(10), false); - AddCustomSearchEngine("custom-3", "c3.com", + AddCustomSearchEngine(kEngineC3Name, kEngineC3Url, base::Time::Now() - base::TimeDelta::FromHours(10), false); - AddCustomSearchEngine("custom-2", "c2.com", + AddCustomSearchEngine(kEngineC2Name, kEngineC2Url, base::Time::Now() - base::TimeDelta::FromMinutes(10), false); @@ -140,40 +227,34 @@ ASSERT_EQ(2, NumberOfSections()); ASSERT_EQ(3, NumberOfItemsInSection(0)); - CheckTextCellTextAndDetailText(@"prepopulated-1", @"p1.com", 0, 0); - CheckTextCellChecked(false, 0, 0); - CheckTextCellTextAndDetailText(@"prepopulated-2", @"p2.com", 0, 1); - CheckTextCellChecked(true, 0, 1); - CheckTextCellTextAndDetailText(@"prepopulated-3", @"p3.com", 0, 2); - CheckTextCellChecked(false, 0, 2); + CheckPrepopulatedItem(kEngineP1Name, kEngineP1Url, false, 0, 0); + CheckPrepopulatedItem(kEngineP2Name, kEngineP2Url, true, 0, 1); + CheckPrepopulatedItem(kEngineP3Name, kEngineP3Url, false, 0, 2); ASSERT_EQ(3, NumberOfItemsInSection(1)); - CheckTextCellTextAndDetailText(@"custom-1", @"c1.com", 1, 0); - CheckTextCellChecked(false, 1, 0); - CheckTextCellTextAndDetailText(@"custom-2", @"c2.com", 1, 1); - CheckTextCellChecked(false, 1, 1); - CheckTextCellTextAndDetailText(@"custom-3", @"c3.com", 1, 2); - CheckTextCellChecked(false, 1, 2); + CheckCustomItem(kEngineC1Name, kEngineC1Url, false, 1, 0); + CheckCustomItem(kEngineC2Name, kEngineC2Url, false, 1, 1); + CheckCustomItem(kEngineC3Name, kEngineC3Url, false, 1, 2); } // Tests that items are displayed correctly when TemplateURLService is filled // and a custom search engine is selected as default. TEST_F(SearchEngineTableViewControllerTest, TestUrlsLoadedWithCustomSearchEngineAsDefault) { - AddPriorSearchEngine("prepopulated-3", "p3.com", 3, false); - AddPriorSearchEngine("prepopulated-1", "p1.com", 1, false); - AddPriorSearchEngine("prepopulated-2", "p2.com", 2, false); + AddPriorSearchEngine(kEngineP3Name, kEngineP3Url, 1003, false); + AddPriorSearchEngine(kEngineP1Name, kEngineP1Url, 1001, false); + AddPriorSearchEngine(kEngineP2Name, kEngineP2Url, 1002, false); - AddCustomSearchEngine("custom-4", "c4.com", + AddCustomSearchEngine(kEngineC4Name, kEngineC4Url, base::Time::Now() - base::TimeDelta::FromDays(10), false); - AddCustomSearchEngine("custom-1", "c1.com", + AddCustomSearchEngine(kEngineC1Name, kEngineC1Url, base::Time::Now() - base::TimeDelta::FromSeconds(10), false); - AddCustomSearchEngine("custom-3", "c3.com", + AddCustomSearchEngine(kEngineC3Name, kEngineC3Url, base::Time::Now() - base::TimeDelta::FromHours(10), false); - AddCustomSearchEngine("custom-2", "c2.com", + AddCustomSearchEngine(kEngineC2Name, kEngineC2Url, base::Time::Now() - base::TimeDelta::FromMinutes(10), true); @@ -182,62 +263,50 @@ ASSERT_EQ(2, NumberOfSections()); ASSERT_EQ(4, NumberOfItemsInSection(0)); - CheckTextCellTextAndDetailText(@"prepopulated-1", @"p1.com", 0, 0); - CheckTextCellChecked(false, 0, 0); - CheckTextCellTextAndDetailText(@"prepopulated-2", @"p2.com", 0, 1); - CheckTextCellChecked(false, 0, 1); - CheckTextCellTextAndDetailText(@"prepopulated-3", @"p3.com", 0, 2); - CheckTextCellChecked(false, 0, 2); - CheckTextCellTextAndDetailText(@"custom-2", @"c2.com", 0, 3); - CheckTextCellChecked(true, 0, 3); + CheckPrepopulatedItem(kEngineP1Name, kEngineP1Url, false, 0, 0); + CheckPrepopulatedItem(kEngineP2Name, kEngineP2Url, false, 0, 1); + CheckPrepopulatedItem(kEngineP3Name, kEngineP3Url, false, 0, 2); + CheckCustomItem(kEngineC2Name, kEngineC2Url, true, 0, 3); ASSERT_EQ(2, NumberOfItemsInSection(1)); - CheckTextCellTextAndDetailText(@"custom-1", @"c1.com", 1, 0); - CheckTextCellChecked(false, 1, 0); - CheckTextCellTextAndDetailText(@"custom-3", @"c3.com", 1, 1); - CheckTextCellChecked(false, 1, 1); + CheckCustomItem(kEngineC1Name, kEngineC1Url, false, 1, 0); + CheckCustomItem(kEngineC3Name, kEngineC3Url, false, 1, 1); } // Tests that when TemplateURLService add or remove TemplateURLs, or update // default search engine, the controller will update the displayed items. TEST_F(SearchEngineTableViewControllerTest, TestUrlModifiedByService) { TemplateURL* url_p1 = - AddPriorSearchEngine("prepopulated-1", "p1.com", 1, true); + AddPriorSearchEngine(kEngineP1Name, kEngineP1Url, 1001, true); CreateController(); CheckController(); ASSERT_EQ(1, NumberOfSections()); ASSERT_EQ(1, NumberOfItemsInSection(0)); - CheckTextCellTextAndDetailText(@"prepopulated-1", @"p1.com", 0, 0); - CheckTextCellChecked(true, 0, 0); + CheckPrepopulatedItem(kEngineP1Name, kEngineP1Url, true, 0, 0); TemplateURL* url_p2 = - AddPriorSearchEngine("prepopulated-2", "p2.com", 2, false); + AddPriorSearchEngine(kEngineP2Name, kEngineP2Url, 1002, false); ASSERT_EQ(1, NumberOfSections()); ASSERT_EQ(2, NumberOfItemsInSection(0)); - CheckTextCellTextAndDetailText(@"prepopulated-1", @"p1.com", 0, 0); - CheckTextCellChecked(true, 0, 0); - CheckTextCellTextAndDetailText(@"prepopulated-2", @"p2.com", 0, 1); - CheckTextCellChecked(false, 0, 1); + CheckPrepopulatedItem(kEngineP1Name, kEngineP1Url, true, 0, 0); + CheckPrepopulatedItem(kEngineP2Name, kEngineP2Url, false, 0, 1); template_url_service_->SetUserSelectedDefaultSearchProvider(url_p2); ASSERT_EQ(1, NumberOfSections()); ASSERT_EQ(2, NumberOfItemsInSection(0)); - CheckTextCellTextAndDetailText(@"prepopulated-1", @"p1.com", 0, 0); - CheckTextCellChecked(false, 0, 0); - CheckTextCellTextAndDetailText(@"prepopulated-2", @"p2.com", 0, 1); - CheckTextCellChecked(true, 0, 1); + CheckPrepopulatedItem(kEngineP1Name, kEngineP1Url, false, 0, 0); + CheckPrepopulatedItem(kEngineP2Name, kEngineP2Url, true, 0, 1); template_url_service_->SetUserSelectedDefaultSearchProvider(url_p1); template_url_service_->Remove(url_p2); ASSERT_EQ(1, NumberOfSections()); ASSERT_EQ(1, NumberOfItemsInSection(0)); - CheckTextCellTextAndDetailText(@"prepopulated-1", @"p1.com", 0, 0); - CheckTextCellChecked(true, 0, 0); + CheckPrepopulatedItem(kEngineP1Name, kEngineP1Url, true, 0, 0); } // Tests that when user change default search engine, all items can be displayed @@ -268,9 +337,9 @@ std::swap(url_p1_index, url_p2_index); // Also add some custom search engines. - TemplateURL* url_c1 = - AddCustomSearchEngine("custom-1", "c1.com", base::Time::Now(), false); - AddCustomSearchEngine("custom-2", "c2.com", + TemplateURL* url_c1 = AddCustomSearchEngine(kEngineC1Name, kEngineC1Url, + base::Time::Now(), false); + AddCustomSearchEngine(kEngineC2Name, kEngineC2Url, base::Time::Now() - base::TimeDelta::FromSeconds(10), false); @@ -285,20 +354,12 @@ ASSERT_EQ(2, NumberOfSections()); // Check first list. ASSERT_EQ(2, NumberOfItemsInSection(0)); - CheckTextCellTextAndDetailText(base::SysUTF16ToNSString(url_p1->short_name()), - base::SysUTF16ToNSString(url_p1->keyword()), 0, - url_p1_index); - CheckTextCellChecked(true, 0, url_p1_index); - CheckTextCellTextAndDetailText(base::SysUTF16ToNSString(url_p2->short_name()), - base::SysUTF16ToNSString(url_p2->keyword()), 0, - url_p2_index); - CheckTextCellChecked(false, 0, url_p2_index); + CheckRealItem(url_p1, true, 0, url_p1_index); + CheckRealItem(url_p2, false, 0, url_p2_index); // Check second list. ASSERT_EQ(2, NumberOfItemsInSection(1)); - CheckTextCellTextAndDetailText(@"custom-1", @"c1.com", 1, 0); - CheckTextCellChecked(false, 1, 0); - CheckTextCellTextAndDetailText(@"custom-2", @"c2.com", 1, 1); - CheckTextCellChecked(false, 1, 1); + CheckCustomItem(kEngineC1Name, kEngineC1Url, false, 1, 0); + CheckCustomItem(kEngineC2Name, kEngineC2Url, false, 1, 1); // Check default search engine. EXPECT_EQ(url_p1, template_url_service_->GetDefaultSearchProvider()); // Check UMA. @@ -314,20 +375,12 @@ ASSERT_EQ(2, NumberOfSections()); // Check first list. ASSERT_EQ(2, NumberOfItemsInSection(0)); - CheckTextCellTextAndDetailText(base::SysUTF16ToNSString(url_p1->short_name()), - base::SysUTF16ToNSString(url_p1->keyword()), 0, - url_p1_index); - CheckTextCellChecked(false, 0, url_p1_index); - CheckTextCellTextAndDetailText(base::SysUTF16ToNSString(url_p2->short_name()), - base::SysUTF16ToNSString(url_p2->keyword()), 0, - url_p2_index); - CheckTextCellChecked(true, 0, url_p2_index); + CheckRealItem(url_p1, false, 0, url_p1_index); + CheckRealItem(url_p2, true, 0, url_p2_index); // Check second list. ASSERT_EQ(2, NumberOfItemsInSection(1)); - CheckTextCellTextAndDetailText(@"custom-1", @"c1.com", 1, 0); - CheckTextCellChecked(false, 1, 0); - CheckTextCellTextAndDetailText(@"custom-2", @"c2.com", 1, 1); - CheckTextCellChecked(false, 1, 1); + CheckCustomItem(kEngineC1Name, kEngineC1Url, false, 1, 0); + CheckCustomItem(kEngineC2Name, kEngineC2Url, false, 1, 1); // Check default search engine. EXPECT_EQ(url_p2, template_url_service_->GetDefaultSearchProvider()); // Check UMA. @@ -346,20 +399,12 @@ ASSERT_EQ(2, NumberOfSections()); // Check first list. ASSERT_EQ(2, NumberOfItemsInSection(0)); - CheckTextCellTextAndDetailText(base::SysUTF16ToNSString(url_p1->short_name()), - base::SysUTF16ToNSString(url_p1->keyword()), 0, - url_p1_index); - CheckTextCellChecked(false, 0, url_p1_index); - CheckTextCellTextAndDetailText(base::SysUTF16ToNSString(url_p2->short_name()), - base::SysUTF16ToNSString(url_p2->keyword()), 0, - url_p2_index); - CheckTextCellChecked(false, 0, url_p2_index); + CheckRealItem(url_p1, false, 0, url_p1_index); + CheckRealItem(url_p2, false, 0, url_p2_index); // Check second list. ASSERT_EQ(2, NumberOfItemsInSection(1)); - CheckTextCellTextAndDetailText(@"custom-1", @"c1.com", 1, 0); - CheckTextCellChecked(true, 1, 0); - CheckTextCellTextAndDetailText(@"custom-2", @"c2.com", 1, 1); - CheckTextCellChecked(false, 1, 1); + CheckCustomItem(kEngineC1Name, kEngineC1Url, true, 1, 0); + CheckCustomItem(kEngineC2Name, kEngineC2Url, false, 1, 1); // Check default search engine. EXPECT_EQ(url_c1, template_url_service_->GetDefaultSearchProvider()); // Check UMA.
diff --git a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm index 8a45471..bc4a91e 100644 --- a/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm +++ b/ios/chrome/browser/ui/tab_grid/tab_grid_mediator.mm
@@ -23,7 +23,6 @@ #import "ios/chrome/browser/tabs/tab_title_util.h" #import "ios/chrome/browser/ui/tab_grid/grid/grid_consumer.h" #import "ios/chrome/browser/ui/tab_grid/grid/grid_item.h" -#include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/web/tab_id_tab_helper.h" #include "ios/chrome/browser/web_state_list/web_state_list.h" #import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h" @@ -401,16 +400,10 @@ if (IsURLNtp(webState->GetVisibleURL())) { return; } - UIImage* defaultFavicon; - if (IsUIRefreshPhase1Enabled()) { - if (webState->GetBrowserState()->IsOffTheRecord()) { - defaultFavicon = [UIImage imageNamed:@"default_world_favicon_incognito"]; - } else { - defaultFavicon = [UIImage imageNamed:@"default_world_favicon_regular"]; - } - } else { - defaultFavicon = [UIImage imageNamed:@"default_favicon"]; - } + UIImage* defaultFavicon = + webState->GetBrowserState()->IsOffTheRecord() + ? [UIImage imageNamed:@"default_world_favicon_incognito"] + : [UIImage imageNamed:@"default_world_favicon_regular"]; completion(defaultFavicon); favicon::FaviconDriver* faviconDriver =
diff --git a/ios/chrome/browser/ui/tabs/tab_view.mm b/ios/chrome/browser/ui/tabs/tab_view.mm index 99110798..ed25877 100644 --- a/ios/chrome/browser/ui/tabs/tab_view.mm +++ b/ios/chrome/browser/ui/tabs/tab_view.mm
@@ -16,7 +16,6 @@ #import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" #import "ios/chrome/browser/ui/image_util/image_util.h" #include "ios/chrome/browser/ui/util/rtl_geometry.h" -#include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/highlight_button.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" @@ -386,26 +385,13 @@ } - (void)updateCloseButtonImages { - if (IsUIRefreshPhase1Enabled()) { - [_closeButton - setImage:[[UIImage imageNamed:@"grid_cell_close_button"] - imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] - forState:UIControlStateNormal]; - _closeButton.tintColor = _incognitoStyle - ? UIColorFromRGB(kTabCloseTintIncognito) - : UIColorFromRGB(kTabCloseTint); - } else { - NSString* incognito = self.incognitoStyle ? @"_incognito" : @""; - UIImage* normalImage = [UIImage - imageNamed:[NSString stringWithFormat:@"tabstrip_tab_close%@_legacy", - incognito]]; - UIImage* pressedImage = [UIImage - imageNamed:[NSString - stringWithFormat:@"tabstrip_tab_close%@_pressed_legacy", - incognito]]; - [_closeButton setImage:normalImage forState:UIControlStateNormal]; - [_closeButton setImage:pressedImage forState:UIControlStateHighlighted]; - } + [_closeButton + setImage:[[UIImage imageNamed:@"grid_cell_close_button"] + imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] + forState:UIControlStateNormal]; + _closeButton.tintColor = _incognitoStyle + ? UIColorFromRGB(kTabCloseTintIncognito) + : UIColorFromRGB(kTabCloseTint); } - (UIImage*)defaultFaviconImage {
diff --git a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller_unittest.mm b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller_unittest.mm index 335ee70..73acdfd 100644 --- a/ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller_unittest.mm +++ b/ios/chrome/browser/ui/toolbar/adaptive_toolbar_view_controller_unittest.mm
@@ -15,7 +15,6 @@ #import "ios/chrome/browser/ui/toolbar/buttons/toolbar_button_factory.h" #import "ios/chrome/browser/ui/toolbar/primary_toolbar_view_controller.h" #import "ios/chrome/browser/ui/toolbar/public/toolbar_constants.h" -#include "ios/chrome/browser/ui/util/ui_util.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/platform_test.h" #import "third_party/ocmock/OCMock/OCMock.h" @@ -49,9 +48,6 @@ }; TEST_F(AdaptiveToolbarViewControllerTest, DetectForceTouch) { - if (!IsUIRefreshPhase1Enabled()) - return; - id dispatcher = OCMProtocolMock(@protocol(PopupMenuCommands)); id longPressDelegate = OCMProtocolMock(@protocol(PopupMenuLongPressDelegate)); ToolbarButtonFactory* factory =
diff --git a/ios/chrome/browser/ui/translate/translate_infobar_view.mm b/ios/chrome/browser/ui/translate/translate_infobar_view.mm index f6017b5..a4e4740 100644 --- a/ios/chrome/browser/ui/translate/translate_infobar_view.mm +++ b/ios/chrome/browser/ui/translate/translate_infobar_view.mm
@@ -18,7 +18,6 @@ #import "ios/chrome/browser/ui/util/label_link_controller.h" #import "ios/chrome/browser/ui/util/layout_guide_names.h" #import "ios/chrome/browser/ui/util/named_guide.h" -#include "ios/chrome/browser/ui/util/ui_util.h" #import "ios/chrome/browser/ui/util/uikit_ui_util.h" #import "ios/chrome/common/ui_util/constraints_ui_util.h" #include "ios/chrome/grit/ios_strings.h" @@ -214,11 +213,7 @@ a11yAnnoucement); } - if (IsUIRefreshPhase1Enabled()) { - self.backgroundColor = UIColorFromRGB(kInfobarBackgroundColor); - } else { - self.backgroundColor = [UIColor whiteColor]; - } + self.backgroundColor = UIColorFromRGB(kInfobarBackgroundColor); id<LayoutGuideProvider> safeAreaLayoutGuide = self.safeAreaLayoutGuide; // The Content view. Holds all the other subviews.
diff --git a/ios/chrome/browser/ui/ui_feature_flags.cc b/ios/chrome/browser/ui/ui_feature_flags.cc index 2b4c3a0..5cda4d9 100644 --- a/ios/chrome/browser/ui/ui_feature_flags.cc +++ b/ios/chrome/browser/ui/ui_feature_flags.cc
@@ -30,7 +30,7 @@ base::FEATURE_DISABLED_BY_DEFAULT}; const base::Feature kDisplaySearchEngineFavicon{ - "DisplaySearchEngineFavicon", base::FEATURE_DISABLED_BY_DEFAULT}; + "DisplaySearchEngineFavicon", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kNewOmniboxPopupLayout{"NewOmniboxPopupLayout", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/ios/chrome/test/earl_grey/chrome_earl_grey.mm b/ios/chrome/test/earl_grey/chrome_earl_grey.mm index bd169d8..567629c 100644 --- a/ios/chrome/test/earl_grey/chrome_earl_grey.mm +++ b/ios/chrome/test/earl_grey/chrome_earl_grey.mm
@@ -111,8 +111,10 @@ [ChromeEarlGrey waitForPageToFinishLoading]; web::WebState* webState = chrome_test_util::GetCurrentWebState(); - if (webState->ContentIsHTML()) - web::WaitUntilWindowIdInjected(webState); + if (webState->ContentIsHTML()) { + GREYAssert(web::WaitUntilWindowIdInjected(webState), + @"WindowID failed to inject"); + } } + (void)reload {
diff --git a/ios/third_party/material_components_ios/BUILD.gn b/ios/third_party/material_components_ios/BUILD.gn index 85c03fb..f204498 100644 --- a/ios/third_party/material_components_ios/BUILD.gn +++ b/ios/third_party/material_components_ios/BUILD.gn
@@ -14,6 +14,7 @@ "src/components/Buttons/src/MaterialButtons.h", "src/components/Buttons/src/ShapeThemer/MaterialButtons+ShapeThemer.h", "src/components/Buttons/src/TypographyThemer/MaterialButtons+TypographyThemer.h", + "src/components/Cards/src/MaterialCards.h", "src/components/Dialogs/src/MaterialDialogs.h", "src/components/ShadowElevations/src/MaterialShadowElevations.h", "src/components/schemes/Color/src/MaterialColorScheme.h",
diff --git a/ios/web/public/test/earl_grey/js_test_util.h b/ios/web/public/test/earl_grey/js_test_util.h index 1dfdf80..fe4447b14 100644 --- a/ios/web/public/test/earl_grey/js_test_util.h +++ b/ios/web/public/test/earl_grey/js_test_util.h
@@ -12,18 +12,9 @@ namespace web { // Waits until the Window ID has been injected and the page is thus ready to -// respond to JavaScript injection. Fails with a GREYAssert on timeout or if +// respond to JavaScript injection. Returns false on timeout or if an // unrecoverable error (such as no web view) occurs. -void WaitUntilWindowIdInjected(WebState* web_state); - -// Executes |javascript| on the given |web_state|, and waits until execution is -// completed. If |out_error| is not nil, it is set to the error resulting from -// the execution, if one occurs. The return value is the result of the -// JavaScript execution. If the script execution is timed out, then this method -// fails with a GREYAssert. -id ExecuteJavaScript(WebState* web_state, - NSString* javascript, - NSError* __autoreleasing* out_error); +bool WaitUntilWindowIdInjected(WebState* web_state) WARN_UNUSED_RESULT; // Synchronously returns the result of executed JavaScript on interstitial page // displayed for |web_state|.
diff --git a/ios/web/public/test/earl_grey/js_test_util.mm b/ios/web/public/test/earl_grey/js_test_util.mm index 7adf7d8..b754f324 100644 --- a/ios/web/public/test/earl_grey/js_test_util.mm +++ b/ios/web/public/test/earl_grey/js_test_util.mm
@@ -21,6 +21,32 @@ namespace web { +// Executes |javascript| on the given |web_state|, and waits until execution is +// completed. If |out_error| is not nil, it is set to the error resulting from +// the execution, if one occurs. The return value is the result of the +// JavaScript execution, or nil if script execution timed out. +id ExecuteJavaScript(WebState* web_state, + NSString* javascript, + NSError* __autoreleasing* out_error) { + __block bool did_complete = false; + __block id result = nil; + CRWJSInjectionReceiver* receiver = web_state->GetJSInjectionReceiver(); + [receiver executeJavaScript:javascript + completionHandler:^(id value, NSError* error) { + did_complete = true; + result = [value copy]; + if (out_error) + *out_error = [error copy]; + }]; + + // Wait for completion. + BOOL succeeded = WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ + return did_complete; + }); + + return succeeded ? result : nil; +} + // Evaluates the given |script| on |interstitial|. void ExecuteScriptForTesting(web::WebInterstitialImpl* interstitial, NSString* script, @@ -29,7 +55,7 @@ interstitial->ExecuteJavaScript(script, handler); } -void WaitUntilWindowIdInjected(WebState* web_state) { +bool WaitUntilWindowIdInjected(WebState* web_state) { bool is_window_id_injected = false; bool is_timeout = false; bool is_unrecoverable_error = false; @@ -52,31 +78,7 @@ } is_timeout = timeout < timer.Elapsed(); } - GREYAssertFalse(is_timeout, @"windowID injection timed out"); - GREYAssertFalse(is_unrecoverable_error, @"script execution error"); -} - -id ExecuteJavaScript(WebState* web_state, - NSString* javascript, - NSError* __autoreleasing* out_error) { - __block bool did_complete = false; - __block id result = nil; - CRWJSInjectionReceiver* receiver = web_state->GetJSInjectionReceiver(); - [receiver executeJavaScript:javascript - completionHandler:^(id value, NSError* error) { - did_complete = true; - result = [value copy]; - if (out_error) - *out_error = [error copy]; - }]; - - // Wait for completion. - BOOL succeeded = WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ - return did_complete; - }); - GREYAssert(succeeded, @"Script execution timed out"); - - return result; + return !is_timeout && !is_unrecoverable_error; } id ExecuteScriptOnInterstitial(WebState* web_state, NSString* script) { @@ -92,8 +94,8 @@ BOOL succeeded = WaitUntilConditionOrTimeout(kWaitForJSCompletionTimeout, ^{ return did_finish; }); - GREYAssert(succeeded, @"Script execution timed out"); - return script_result; + + return succeeded ? script_result : nil; } } // namespace web
diff --git a/ios/web/public/test/earl_grey/web_view_actions.mm b/ios/web/public/test/earl_grey/web_view_actions.mm index 0f71aac..3099e4d 100644 --- a/ios/web/public/test/earl_grey/web_view_actions.mm +++ b/ios/web/public/test/earl_grey/web_view_actions.mm
@@ -197,7 +197,7 @@ return NO; } - // Run the action. + // Run the action and wait for the UI to settle. [[EarlGrey selectElementWithMatcher:WebViewInWebState(state)] performAction:action error:error]; @@ -205,23 +205,23 @@ if (*error) { return NO; } + [[GREYUIThreadExecutor sharedInstance] drainUntilIdle]; // Wait for the verified to trigger and set |verified|. NSString* verification_timeout_message = [NSString stringWithFormat:@"The action (%@) on element %@ wasn't " @"verified before timing out.", action.name, selector.selectorDescription]; - GREYAssert(base::test::ios::WaitUntilConditionOrTimeout( - kWaitForVerificationTimeout, - ^{ - return verified; - }), - verification_timeout_message); + bool success = base::test::ios::WaitUntilConditionOrTimeout( + kWaitForVerificationTimeout, ^{ + return verified; + }); - // If |verified| is not true, the wait condition should have already exited - // this control flow, so sanity check that it has in fact been set to - // true by this point. - DCHECK(verified); + if (!success || !verified) { + DLOG(WARNING) << base::SysNSStringToUTF8(verification_timeout_message); + return NO; + } + return YES; };
diff --git a/ios/web/shell/test/earl_grey/shell_earl_grey.mm b/ios/web/shell/test/earl_grey/shell_earl_grey.mm index 0dd83d2..4878039 100644 --- a/ios/web/shell/test/earl_grey/shell_earl_grey.mm +++ b/ios/web/shell/test/earl_grey/shell_earl_grey.mm
@@ -31,8 +31,11 @@ if (!web::test::WaitForPageToFinishLoading(webState)) return false; - if (webState->ContentIsHTML()) - web::WaitUntilWindowIdInjected(webState); + if (webState->ContentIsHTML()) { + if (!web::WaitUntilWindowIdInjected(webState)) { + return false; + } + } // Ensure any UI elements handled by EarlGrey become idle for any subsequent // EarlGrey steps.
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 66e8c0c..357e51f 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -617,7 +617,6 @@ "test:video_player_test_environment", "test:video_player_thumbnail_renderer", "//media:test_support", - "//mojo/core/embedder", "//testing/gtest", ] } @@ -637,7 +636,6 @@ "test:video_player", "test:video_player_test_environment", "//media:test_support", - "//mojo/core/embedder", "//testing/gtest", ] }
diff --git a/media/gpu/test/BUILD.gn b/media/gpu/test/BUILD.gn index d1590a6..73d65c09 100644 --- a/media/gpu/test/BUILD.gn +++ b/media/gpu/test/BUILD.gn
@@ -182,6 +182,7 @@ "//base/test:test_config", "//base/test:test_support", "//media/gpu", + "//mojo/core/embedder:embedder", "//testing/gtest:gtest", ] if (use_ozone) {
diff --git a/media/gpu/test/image_processor/image_processor_client.cc b/media/gpu/test/image_processor/image_processor_client.cc index bb3e2f5..c27e712 100644 --- a/media/gpu/test/image_processor/image_processor_client.cc +++ b/media/gpu/test/image_processor/image_processor_client.cc
@@ -50,13 +50,13 @@ LOG_ASSERT(dst_layout.planes().size() == num_planes); LOG_ASSERT(src_frame->layout().planes().size() == num_planes); for (size_t i = 0; i < num_planes; ++i) { + // |width| in libyuv::CopyPlane() is in bytes, not pixels. + gfx::Size plane_size = VideoFrame::PlaneSize(dst_frame->format(), i, + dst_frame->natural_size()); libyuv::CopyPlane( src_frame->data(i), src_frame->layout().planes()[i].stride, dst_frame->data(i), dst_frame->layout().planes()[i].stride, - VideoFrame::Columns(i, dst_frame->format(), - dst_frame->natural_size().width()), - VideoFrame::Rows(i, dst_frame->format(), - dst_frame->natural_size().height())); + plane_size.width(), plane_size.height()); } return dst_frame; @@ -223,7 +223,7 @@ // VideoFrame should be processed in FIFO order. EXPECT_EQ(frame_index, num_processed_frames_); for (auto& processor : frame_processors_) - processor->ProcessVideoFrame(std::move(frame), frame_index); + processor->ProcessVideoFrame(frame, frame_index); num_processed_frames_++; output_cv_.Signal(); }
diff --git a/media/gpu/test/video_player/video_player_test_environment.cc b/media/gpu/test/video_player/video_player_test_environment.cc index 1c40bcf..974ca91a 100644 --- a/media/gpu/test/video_player/video_player_test_environment.cc +++ b/media/gpu/test/video_player/video_player_test_environment.cc
@@ -4,14 +4,35 @@ #include "media/gpu/test/video_player/video_player_test_environment.h" +#include "base/command_line.h" +#include "base/test/test_timeouts.h" +#include "media/gpu/buildflags.h" +#include "media/gpu/test/video_player/video.h" +#include "mojo/core/embedder/embedder.h" + +#if BUILDFLAG(USE_VAAPI) +#include "media/gpu/vaapi/vaapi_wrapper.h" +#endif + +#if defined(USE_OZONE) +#include "ui/ozone/public/ozone_gpu_test_helper.h" +#include "ui/ozone/public/ozone_platform.h" +#endif + namespace media { namespace test { VideoPlayerTestEnvironment::VideoPlayerTestEnvironment(const Video* video) : video_(video) {} -VideoPlayerTestEnvironment::~VideoPlayerTestEnvironment() = default; - void VideoPlayerTestEnvironment::SetUp() { + // Using shared memory requires mojo to be initialized (crbug.com/849207). + mojo::core::Init(); + + // Needed to enable DVLOG through --vmodule. + logging::LoggingSettings settings; + settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; + LOG_ASSERT(logging::InitLogging(settings)); + // Setting up a task environment will create a task runner for the current // thread and allow posting tasks to other threads. This is required for the // test video player to function correctly.
diff --git a/media/gpu/test/video_player/video_player_test_environment.h b/media/gpu/test/video_player/video_player_test_environment.h index cb66a573..014e9700 100644 --- a/media/gpu/test/video_player/video_player_test_environment.h +++ b/media/gpu/test/video_player/video_player_test_environment.h
@@ -6,29 +6,27 @@ #define MEDIA_GPU_TEST_VIDEO_PLAYER_VIDEO_PLAYER_TEST_ENVIRONMENT_H_ #include <memory> + #include "base/at_exit.h" #include "base/test/scoped_task_environment.h" -#include "base/test/test_timeouts.h" -#include "media/gpu/buildflags.h" -#include "media/gpu/test/video_player/video.h" -#if BUILDFLAG(USE_VAAPI) -#include "media/gpu/vaapi/vaapi_wrapper.h" -#endif #include "testing/gtest/include/gtest/gtest.h" + #if defined(USE_OZONE) -#include "ui/ozone/public/ozone_gpu_test_helper.h" -#include "ui/ozone/public/ozone_platform.h" +namespace ui { +class OzoneGpuTestHelper; +} #endif namespace media { namespace test { +class Video; + // Test environment for video decode tests. Performs setup and teardown once for // the entire test run. class VideoPlayerTestEnvironment : public ::testing::Environment { public: explicit VideoPlayerTestEnvironment(const Video* video); - ~VideoPlayerTestEnvironment(); // Set up the video decode test environment, only called once. void SetUp() override;
diff --git a/media/gpu/video_decode_accelerator_perf_tests.cc b/media/gpu/video_decode_accelerator_perf_tests.cc index 060c764..b1e51e14 100644 --- a/media/gpu/video_decode_accelerator_perf_tests.cc +++ b/media/gpu/video_decode_accelerator_perf_tests.cc
@@ -13,7 +13,6 @@ #include "media/gpu/test/video_player/video_decoder_client.h" #include "media/gpu/test/video_player/video_player.h" #include "media/gpu/test/video_player/video_player_test_environment.h" -#include "mojo/core/embedder/embedder.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -182,14 +181,6 @@ testing::InitGoogleTest(&argc, argv); base::CommandLine::Init(argc, argv); - // Using shared memory requires mojo to be initialized (crbug.com/849207). - mojo::core::Init(); - - // Needed to enable DVLOG through --vmodule. - logging::LoggingSettings settings; - settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; - LOG_ASSERT(logging::InitLogging(settings)); - // Set the default test data path. media::test::Video::SetTestDataPath(media::GetTestDataPath());
diff --git a/media/gpu/video_decode_accelerator_tests.cc b/media/gpu/video_decode_accelerator_tests.cc index f494f45..72af438 100644 --- a/media/gpu/video_decode_accelerator_tests.cc +++ b/media/gpu/video_decode_accelerator_tests.cc
@@ -13,7 +13,6 @@ #include "media/gpu/test/video_player/video_decoder_client.h" #include "media/gpu/test/video_player/video_player.h" #include "media/gpu/test/video_player/video_player_test_environment.h" -#include "mojo/core/embedder/embedder.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -277,14 +276,6 @@ testing::InitGoogleTest(&argc, argv); - // Using shared memory requires mojo to be initialized (crbug.com/849207). - mojo::core::Init(); - - // Needed to enable DVLOG through --vmodule. - logging::LoggingSettings settings; - settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; - LOG_ASSERT(logging::InitLogging(settings)); - // Set the default test data path. media::test::Video::SetTestDataPath(media::GetTestDataPath());
diff --git a/media/test/data/README.md b/media/test/data/README.md index 6722053..cc0aa16 100644 --- a/media/test/data/README.md +++ b/media/test/data/README.md
@@ -788,6 +788,16 @@ #### bear\_320x192.yv12.yuv First frame of bear\_320x192\_40frames.yv12.yuv for image\_processor_test. +#### bear\_320x192.rgba +RAW RGBA format data. This data is created from bear\_320x192.i420.yuv by the +following command. Alpha channel is always 0xFF because of that. +`ffmpeg -s 320x192 -pix_fmt yuv420p -i bear_320x192.i420.yuv -vcodec rawvideo -f image2 -pix_fmt rgba bear_320x192.rgba` + +#### bear\_320x192.bgra +RAW BGRA format data. This data is created from bear\_320x192.i420.yuv by the +following command. Alpha channel is always 0xFF because of that. +`ffmpeg -s 320x192 -pix_fmt yuv420p -i bear_320x192.i420.yuv -vcodec rawvideo -f image2 -pix_fmt rgba bear_320x192.bgra` + ### VP9 parser test files: #### bear-vp9.ivf
diff --git a/media/test/data/bear_320x192.bgra b/media/test/data/bear_320x192.bgra new file mode 100644 index 0000000..e35e345e --- /dev/null +++ b/media/test/data/bear_320x192.bgra Binary files differ
diff --git a/media/test/data/bear_320x192.bgra.json b/media/test/data/bear_320x192.bgra.json new file mode 100644 index 0000000..cf088ae --- /dev/null +++ b/media/test/data/bear_320x192.bgra.json
@@ -0,0 +1,6 @@ +{ + "pixel_format": "BRGA", + "width": 320, + "height": 192, + "checksum": "edc7e1721d769695d18cd20c71140ebd" +}
diff --git a/media/test/data/bear_320x192.rgba b/media/test/data/bear_320x192.rgba new file mode 100644 index 0000000..f0e5293 --- /dev/null +++ b/media/test/data/bear_320x192.rgba Binary files differ
diff --git a/media/test/data/bear_320x192.rgba.json b/media/test/data/bear_320x192.rgba.json new file mode 100644 index 0000000..ddd9e49 --- /dev/null +++ b/media/test/data/bear_320x192.rgba.json
@@ -0,0 +1,6 @@ +{ + "pixel_format": "RGBA", + "width": 320, + "height": 192, + "checksum": "b1277dff463d24af3ae4f02bcfa16a32" +}
diff --git a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc index f3c2169b..a9fe780c 100644 --- a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc +++ b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store.cc
@@ -122,10 +122,12 @@ void LoadNELPoliciesAndNotifyInBackground( NELPoliciesLoadedCallback loaded_callback); - // Calls |loaded_callback| with the loaded NEL policies in |loaded_policies|. - void NotifyNELPoliciesLoaded( + // Calls |loaded_callback| with the loaded NEL policies (which may be empty if + // loading was unsuccessful). If loading was successful, also report metrics. + void CompleteLoadNELPoliciesAndNotifyInForeground( NELPoliciesLoadedCallback loaded_callback, - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies); + std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies, + bool load_success); // Total number of pending operations (may not match the sum of the number of // elements in the pending operations queues, due to operation coalescing). @@ -470,8 +472,15 @@ NELPoliciesLoadedCallback loaded_callback) { DCHECK(background_task_runner()->RunsTasksInCurrentSequence()); - if (!InitializeDatabase()) + std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies; + if (!InitializeDatabase()) { + PostClientTask( + FROM_HERE, + base::BindOnce(&Backend::CompleteLoadNELPoliciesAndNotifyInForeground, + this, std::move(loaded_callback), + std::move(loaded_policies), false /* load_success */)); return; + } sql::Statement smt(db()->GetUniqueStatement( "SELECT origin_scheme, origin_host, origin_port, received_ip_address," @@ -479,10 +488,14 @@ "is_include_subdomains, last_access_us_since_epoch FROM nel_policies")); if (!smt.is_valid()) { Reset(); + PostClientTask( + FROM_HERE, + base::BindOnce(&Backend::CompleteLoadNELPoliciesAndNotifyInForeground, + this, std::move(loaded_callback), + std::move(loaded_policies), false /* load_success */)); return; } - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies; while (smt.Step()) { // Reconstitute a NEL policy from the fields stored in the database. NetworkErrorLoggingService::NELPolicy policy; @@ -504,16 +517,26 @@ loaded_policies.push_back(std::move(policy)); } - PostClientTask(FROM_HERE, base::BindOnce(&Backend::NotifyNELPoliciesLoaded, - this, std::move(loaded_callback), - std::move(loaded_policies))); + PostClientTask( + FROM_HERE, + base::BindOnce(&Backend::CompleteLoadNELPoliciesAndNotifyInForeground, + this, std::move(loaded_callback), + std::move(loaded_policies), true /* load_success */)); } -void SQLitePersistentReportingAndNELStore::Backend::NotifyNELPoliciesLoaded( - NELPoliciesLoadedCallback loaded_callback, - std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies) { +void SQLitePersistentReportingAndNELStore::Backend:: + CompleteLoadNELPoliciesAndNotifyInForeground( + NELPoliciesLoadedCallback loaded_callback, + std::vector<NetworkErrorLoggingService::NELPolicy> loaded_policies, + bool load_success) { DCHECK(client_task_runner()->RunsTasksInCurrentSequence()); + if (load_success) { + // TODO(chlily): report metrics + } else { + DCHECK(loaded_policies.empty()); + } + std::move(loaded_callback).Run(std::move(loaded_policies)); }
diff --git a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc index 44a9dcb..c61007d9 100644 --- a/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc +++ b/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc
@@ -179,6 +179,20 @@ EXPECT_TRUE(WithinOneMicrosecond(policy.last_used, policies[0].last_used)); } +TEST_F(SQLitePersistentReportingAndNELStoreTest, LoadNELPoliciesFailed) { + // Inject a db initialization failure by creating a directory where the db + // file should be. + ASSERT_TRUE(base::CreateDirectory( + temp_dir_.GetPath().Append(kReportingAndNELStoreFilename))); + store_ = std::make_unique<SQLitePersistentReportingAndNELStore>( + temp_dir_.GetPath().Append(kReportingAndNELStoreFilename), + client_task_runner_, background_task_runner_); + + // InitializeStore() checks that we receive an empty vector of policies, + // signifying the failure to load. + InitializeStore(); +} + TEST_F(SQLitePersistentReportingAndNELStoreTest, UpdateNELPolicyAccessTime) { CreateStore(); InitializeStore();
diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc index 50a92fc..a2cde27e 100644 --- a/net/url_request/url_request_unittest.cc +++ b/net/url_request/url_request_unittest.cc
@@ -11416,7 +11416,13 @@ : public HTTPSOCSPTest, public testing::WithParamInterface<OCSPVerifyTestData> {}; -TEST_P(HTTPSOCSPVerifyTest, VerifyResult) { +// TODO(crbug.com/949958): The test is flaky on Mac +#if defined(OS_MACOSX) +#define MAYBE_VerifyResult DISABLED_VerifyResult +#else +#define MAYBE_VerifyResult VerifyResult +#endif +TEST_P(HTTPSOCSPVerifyTest, MAYBE_VerifyResult) { SpawnedTestServer::SSLOptions ssl_options( SpawnedTestServer::SSLOptions::CERT_AUTO); OCSPVerifyTestData test = GetParam();
diff --git a/remoting/signaling/signaling_address.cc b/remoting/signaling/signaling_address.cc index 3f4102e..1165610 100644 --- a/remoting/signaling/signaling_address.cc +++ b/remoting/signaling/signaling_address.cc
@@ -4,9 +4,11 @@ #include "remoting/signaling/signaling_address.h" -#include "base/base64.h" +#include <string.h> + #include "base/logging.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "remoting/base/name_value_map.h" #include "remoting/base/remoting_bot.h" #include "remoting/base/service_urls.h" @@ -17,7 +19,13 @@ namespace { -const char kJingleNamespace[] = "urn:xmpp:jingle:1"; +constexpr char kJingleNamespace[] = "urn:xmpp:jingle:1"; +constexpr char kLcsResourcePrefix[] = "chromoting_lcs_"; + +// FTL JID format: +// user@domain.com/chromoting_ftl_(registration ID) +// The FTL JID is only used local to the program. +constexpr char kFtlResourcePrefix[] = "chromoting_ftl_"; // Represents the XML attrbute names for the various address fields in the // iq stanza. @@ -26,6 +34,7 @@ const NameMapElement<SignalingAddress::Channel> kChannelTypes[] = { {SignalingAddress::Channel::LCS, "lcs"}, {SignalingAddress::Channel::XMPP, "xmpp"}, + {SignalingAddress::Channel::FTL, "ftl"}, }; jingle_xmpp::QName GetQNameByField(Field attr, SignalingAddress::Direction direction) { @@ -50,9 +59,14 @@ SignalingAddress::Channel GetChannelType(std::string address) { std::string bare_jid; std::string resource; - if (SplitJidResource(address, &bare_jid, &resource) && - resource.find("chromoting_lcs_") == 0) { - return SignalingAddress::Channel::LCS; + bool has_jid_resource = SplitJidResource(address, &bare_jid, &resource); + if (has_jid_resource) { + if (resource.find(kLcsResourcePrefix) == 0) { + return SignalingAddress::Channel::LCS; + } + if (resource.find(kFtlResourcePrefix) == 0) { + return SignalingAddress::Channel::FTL; + } } return SignalingAddress::Channel::XMPP; } @@ -72,6 +86,9 @@ endpoint_id_ = NormalizeJid(address); jid_ = remoting::ServiceUrls::GetInstance()->directory_bot_jid(); break; + case SignalingAddress::Channel::FTL: + jid_ = NormalizeJid(address); + break; default: NOTREACHED(); } @@ -99,6 +116,16 @@ return !(*this == other); } +// static +SignalingAddress SignalingAddress::CreateFtlSignalingAddress( + const std::string& username, + const std::string& registration_id) { + return SignalingAddress(base::StringPrintf("%s/%s%s", username.c_str(), + kFtlResourcePrefix, + registration_id.c_str())); +} + +// static SignalingAddress SignalingAddress::Parse(const jingle_xmpp::XmlElement* iq, SignalingAddress::Direction direction, std::string* error) { @@ -110,7 +137,7 @@ const jingle_xmpp::XmlElement* jingle = iq->FirstNamed(jingle_xmpp::QName(kJingleNamespace, "jingle")); - if (!jingle) { + if (!jingle || GetChannelType(jid) == SignalingAddress::Channel::FTL) { return SignalingAddress(jid); } @@ -189,4 +216,18 @@ } } +bool SignalingAddress::GetFtlInfo(std::string* username, + std::string* registration_id) const { + if (channel_ != Channel::FTL) { + return false; + } + std::string resource; + bool has_jid_resource = SplitJidResource(jid_, username, &resource); + DCHECK(has_jid_resource); + size_t ftl_resource_prefix_length = strlen(kFtlResourcePrefix); + DCHECK_LT(ftl_resource_prefix_length, resource.length()); + *registration_id = resource.substr(ftl_resource_prefix_length); + return true; +} + } // namespace remoting
diff --git a/remoting/signaling/signaling_address.h b/remoting/signaling/signaling_address.h index 993802c..1508c14e 100644 --- a/remoting/signaling/signaling_address.h +++ b/remoting/signaling/signaling_address.h
@@ -16,21 +16,34 @@ // Represents an address of a Chromoting endpoint and its routing channel. class SignalingAddress { public: - enum class Channel { LCS, XMPP }; + enum class Channel { LCS, XMPP, FTL }; enum Direction { TO, FROM }; // Creates an empty SignalingAddress. SignalingAddress(); // Creates a SignalingAddress with |jid|, which can either be a valid - // XMPP JID or an LCS address in a JID like format. + // XMPP JID, or an LCS address in a JID like format, or FTL address in a JID + // like format. explicit SignalingAddress(const std::string& jid); + // Creates a SignalingAddress that represents an FTL endpoint. Note that the + // FTL SignalingAddress is irrelevant to the FTL server or client. It is just + // to make existing Jingle session logic work with the new messaging service. + static SignalingAddress CreateFtlSignalingAddress( + const std::string& username, + const std::string& registration_id); + static SignalingAddress Parse(const jingle_xmpp::XmlElement* iq, Direction direction, std::string* error); void SetInMessage(jingle_xmpp::XmlElement* message, Direction direction) const; + // Writes FTL info to |username| and |registration_id|. Returns true if the + // SIgnalingAddress is a valid FTL address and info is successfully written. + // If this returns false then none of the parameters will be touched. + bool GetFtlInfo(std::string* username, std::string* registration_id) const; + const std::string& jid() const { return jid_; } const std::string& endpoint_id() const { return endpoint_id_; } Channel channel() const { return channel_; }
diff --git a/remoting/signaling/signaling_address_unittest.cc b/remoting/signaling/signaling_address_unittest.cc index 01dea593..bd0b1fec 100644 --- a/remoting/signaling/signaling_address_unittest.cc +++ b/remoting/signaling/signaling_address_unittest.cc
@@ -25,6 +25,11 @@ "user@domain.com/chromoting_lcs_KkMKIDB5NldsZndLalZZamZWVTZlYmhPT1RBa2p2TUl" "GX0lvEKT-HRhwIhB1V3QxYVkwdUptWlc3bnIxKVYHxmgZQ7i7"; +constexpr char kFtlRegistrationId[] = "f6b43f10-566e-11e9-8647-d663bd873d93"; + +constexpr char kFtlAddress[] = + "user@domain.com/chromoting_ftl_f6b43f10-566e-11e9-8647-d663bd873d93"; + } // namespace TEST(SignalingAddressTest, ParseAddress) { @@ -168,6 +173,18 @@ EXPECT_EQ(kLcsAddress, jingle->Attr(QName("", "to-endpoint-id"))); } +TEST(SignalingAddressTest, SetInMessageToFtl) { + std::unique_ptr<jingle_xmpp::XmlElement> message = GetEmptyJingleMessage(); + SignalingAddress addr(kFtlAddress); + + addr.SetInMessage(message.get(), SignalingAddress::TO); + EXPECT_EQ(kFtlAddress, message->Attr(QName("", "to"))); + jingle_xmpp::XmlElement* jingle = + message->FirstNamed(jingle_xmpp::QName("urn:xmpp:jingle:1", "jingle")); + EXPECT_EQ("", jingle->Attr(QName("", "to-channel"))); + EXPECT_EQ("", jingle->Attr(QName("", "to-endpoint-id"))); +} + TEST(SignalingAddressTest, SetInMessageFromXmpp) { std::unique_ptr<jingle_xmpp::XmlElement> message = GetEmptyJingleMessage(); SignalingAddress addr("user@domain.com/resource"); @@ -191,4 +208,37 @@ EXPECT_EQ(kLcsAddress, jingle->Attr(QName("", "from-endpoint-id"))); } +TEST(SignalingAddressTest, SetInMessageFromFtl) { + std::unique_ptr<jingle_xmpp::XmlElement> message = GetEmptyJingleMessage(); + SignalingAddress addr(kFtlAddress); + addr.SetInMessage(message.get(), SignalingAddress::FROM); + EXPECT_EQ(kFtlAddress, message->Attr(QName("", "from"))); + jingle_xmpp::XmlElement* jingle = + message->FirstNamed(jingle_xmpp::QName("urn:xmpp:jingle:1", "jingle")); + EXPECT_EQ("", jingle->Attr(QName("", "from-channel"))); + EXPECT_EQ("", jingle->Attr(QName("", "from-endpoint-id"))); +} + +TEST(SignalingAddressTest, CreateFtlSignalingAddress) { + SignalingAddress addr = SignalingAddress::CreateFtlSignalingAddress( + "user@domain.com", kFtlRegistrationId); + EXPECT_EQ(kFtlAddress, addr.jid()); + + std::string username; + std::string registration_id; + EXPECT_TRUE(addr.GetFtlInfo(&username, ®istration_id)); + EXPECT_EQ("user@domain.com", username); + EXPECT_EQ(kFtlRegistrationId, registration_id); +} + +TEST(SignalingAddressTest, GetFtlInfo_NotFtlInfo) { + SignalingAddress addr(kLcsAddress); + + std::string username; + std::string registration_id; + EXPECT_FALSE(addr.GetFtlInfo(&username, ®istration_id)); + EXPECT_TRUE(username.empty()); + EXPECT_TRUE(registration_id.empty()); +} + } // namespace remoting
diff --git a/services/identity/public/cpp/identity_manager.cc b/services/identity/public/cpp/identity_manager.cc index a402097..ad20c7df3 100644 --- a/services/identity/public/cpp/identity_manager.cc +++ b/services/identity/public/cpp/identity_manager.cc
@@ -467,11 +467,6 @@ } } -void IdentityManager::GoogleSigninFailed(const GoogleServiceAuthError& error) { - for (auto& observer : observer_list_) - observer.OnPrimaryAccountSigninFailed(error); -} - void IdentityManager::OnRefreshTokenAvailable(const std::string& account_id) { CoreAccountInfo account_info = GetAccountInfoForAccountWithRefreshToken(account_id);
diff --git a/services/identity/public/cpp/identity_manager.h b/services/identity/public/cpp/identity_manager.h index 530095e..5b54669 100644 --- a/services/identity/public/cpp/identity_manager.h +++ b/services/identity/public/cpp/identity_manager.h
@@ -76,11 +76,6 @@ virtual void OnPrimaryAccountCleared( const CoreAccountInfo& previous_primary_account_info) {} - // Called when the user attempts but fails to set their primary - // account. |error| gives the reason for the failure. - virtual void OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) {} - // Called when a new refresh token is associated with |account_info|. // NOTE: On a signin event, the ordering of this callback wrt the // OnPrimaryAccountSet() callback is undefined. If you as a client are @@ -607,7 +602,6 @@ // SigninManagerBase::Observer: void GoogleSigninSucceeded(const AccountInfo& account_info) override; void GoogleSignedOut(const AccountInfo& account_info) override; - void GoogleSigninFailed(const GoogleServiceAuthError& error) override; // OAuth2TokenService::Observer: void OnRefreshTokenAvailable(const std::string& account_id) override;
diff --git a/services/identity/public/cpp/primary_account_mutator_unittest.cc b/services/identity/public/cpp/primary_account_mutator_unittest.cc index b5082b1..6610d1d3 100644 --- a/services/identity/public/cpp/primary_account_mutator_unittest.cc +++ b/services/identity/public/cpp/primary_account_mutator_unittest.cc
@@ -41,12 +41,6 @@ base::RepeatingCallback<void(const CoreAccountInfo&)>; // This callback will be invoked every time the IdentityManager::Observer -// method OnPrimaryAccountSigninFailed is invoked. The parameter will be -// a reference to the authentication error. -using PrimaryAccountSigninFailedCallback = - base::RepeatingCallback<void(const GoogleServiceAuthError&)>; - -// This callback will be invoked every time the IdentityManager::Observer // method OnRefreshTokenRemoved is invoked. The parameter will be a reference // to the account_id whose token was removed. using RefreshTokenRemovedCallback = @@ -60,15 +54,11 @@ ClearPrimaryAccountTestObserver( identity::IdentityManager* identity_manager, PrimaryAccountClearedCallback on_primary_account_cleared, - PrimaryAccountSigninFailedCallback on_primary_account_signin_failed, RefreshTokenRemovedCallback on_refresh_token_removed) : on_primary_account_cleared_(std::move(on_primary_account_cleared)), - on_primary_account_signin_failed_( - std::move(on_primary_account_signin_failed)), on_refresh_token_removed_(std::move(on_refresh_token_removed)), scoped_observer_(this) { DCHECK(on_primary_account_cleared_); - DCHECK(on_primary_account_signin_failed_); DCHECK(on_refresh_token_removed_); scoped_observer_.Add(identity_manager); } @@ -78,18 +68,12 @@ on_primary_account_cleared_.Run(account_info); } - void OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) override { - on_primary_account_signin_failed_.Run(error); - } - void OnRefreshTokenRemovedForAccount(const std::string& account_id) override { on_refresh_token_removed_.Run(account_id); } private: PrimaryAccountClearedCallback on_primary_account_cleared_; - PrimaryAccountSigninFailedCallback on_primary_account_signin_failed_; RefreshTokenRemovedCallback on_refresh_token_removed_; ScopedObserver<identity::IdentityManager, identity::IdentityManager::Observer> scoped_observer_; @@ -165,12 +149,6 @@ const CoreAccountInfo&) { quit_closure.Run(); }, run_loop.QuitClosure()); - // Authentication error should not occur. - PrimaryAccountSigninFailedCallback primary_account_signin_failed_callback = - base::BindRepeating([](const GoogleServiceAuthError&) { - FAIL() << "auth should not fail"; - }); - // Track Observer token removal notification. base::flat_set<std::string> observed_removals; RefreshTokenRemovedCallback refresh_token_removed_callback = @@ -183,7 +161,7 @@ ClearPrimaryAccountTestObserver scoped_observer( identity_manager, primary_account_cleared_callback, - primary_account_signin_failed_callback, refresh_token_removed_callback); + refresh_token_removed_callback); primary_account_mutator->ClearPrimaryAccount( account_action, signin_metrics::SIGNOUT_TEST,
diff --git a/services/identity/public/cpp/test_identity_manager_observer.cc b/services/identity/public/cpp/test_identity_manager_observer.cc index 57d63a29..9c2f9a6 100644 --- a/services/identity/public/cpp/test_identity_manager_observer.cc +++ b/services/identity/public/cpp/test_identity_manager_observer.cc
@@ -39,16 +39,6 @@ return primary_account_from_cleared_callback_; } -void TestIdentityManagerObserver::SetOnPrimaryAccountSigninFailedCallback( - base::OnceClosure callback) { - on_primary_account_signin_failed_callback_ = std::move(callback); -} - -const GoogleServiceAuthError& -TestIdentityManagerObserver::ErrorFromSigninFailedCallback() const { - return google_signin_failed_error_; -} - void TestIdentityManagerObserver::SetOnRefreshTokenUpdatedCallback( base::OnceClosure callback) { on_refresh_token_updated_callback_ = std::move(callback); @@ -146,13 +136,6 @@ std::move(on_primary_account_cleared_callback_).Run(); } -void TestIdentityManagerObserver::OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) { - google_signin_failed_error_ = error; - if (on_primary_account_signin_failed_callback_) - std::move(on_primary_account_signin_failed_callback_).Run(); -} - void TestIdentityManagerObserver::OnRefreshTokenUpdatedForAccount( const CoreAccountInfo& account_info) { if (!is_inside_batch_)
diff --git a/services/identity/public/cpp/test_identity_manager_observer.h b/services/identity/public/cpp/test_identity_manager_observer.h index 91cc2e6..91b6f8b 100644 --- a/services/identity/public/cpp/test_identity_manager_observer.h +++ b/services/identity/public/cpp/test_identity_manager_observer.h
@@ -30,9 +30,6 @@ void SetOnPrimaryAccountClearedCallback(base::OnceClosure callback); const CoreAccountInfo& PrimaryAccountFromClearedCallback(); - void SetOnPrimaryAccountSigninFailedCallback(base::OnceClosure callback); - const GoogleServiceAuthError& ErrorFromSigninFailedCallback() const; - void SetOnRefreshTokenUpdatedCallback(base::OnceClosure callback); const CoreAccountInfo& AccountFromRefreshTokenUpdatedCallback(); @@ -68,9 +65,6 @@ const CoreAccountInfo& primary_account_info) override; void OnPrimaryAccountCleared( const CoreAccountInfo& previous_primary_account_info) override; - void OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) override; - void OnRefreshTokenUpdatedForAccount( const CoreAccountInfo& account_info) override; void OnRefreshTokenRemovedForAccount(const std::string& account_id) override; @@ -98,9 +92,6 @@ base::OnceClosure on_primary_account_cleared_callback_; CoreAccountInfo primary_account_from_cleared_callback_; - base::OnceClosure on_primary_account_signin_failed_callback_; - GoogleServiceAuthError google_signin_failed_error_; - base::OnceClosure on_refresh_token_updated_callback_; CoreAccountInfo account_from_refresh_token_updated_callback_;
diff --git a/services/identity/public/objc/identity_manager_observer_bridge.h b/services/identity/public/objc/identity_manager_observer_bridge.h index 2e7e7b4..4e5e3b0d 100644 --- a/services/identity/public/objc/identity_manager_observer_bridge.h +++ b/services/identity/public/objc/identity_manager_observer_bridge.h
@@ -25,7 +25,6 @@ - (void)onPrimaryAccountSet:(const CoreAccountInfo&)primaryAccountInfo; - (void)onPrimaryAccountCleared: (const CoreAccountInfo&)previousPrimaryAccountInfo; -- (void)onPrimaryAccountSigninFailed:(const GoogleServiceAuthError&)error; - (void)onRefreshTokenUpdatedForAccount:(const CoreAccountInfo&)accountInfo; - (void)onRefreshTokenRemovedForAccount:(const std::string&)accountId; - (void)onRefreshTokensLoaded; @@ -52,8 +51,6 @@ const CoreAccountInfo& primary_account_info) override; void OnPrimaryAccountCleared( const CoreAccountInfo& previous_primary_account_info) override; - void OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) override; void OnRefreshTokenUpdatedForAccount( const CoreAccountInfo& account_info) override; void OnRefreshTokenRemovedForAccount(const std::string& account_id) override;
diff --git a/services/identity/public/objc/identity_manager_observer_bridge.mm b/services/identity/public/objc/identity_manager_observer_bridge.mm index aa8aa3149..59aaea8d 100644 --- a/services/identity/public/objc/identity_manager_observer_bridge.mm +++ b/services/identity/public/objc/identity_manager_observer_bridge.mm
@@ -35,13 +35,6 @@ } } -void IdentityManagerObserverBridge::OnPrimaryAccountSigninFailed( - const GoogleServiceAuthError& error) { - if ([delegate_ respondsToSelector:@selector(onPrimaryAccountSigninFailed:)]) { - [delegate_ onPrimaryAccountSigninFailed:error]; - } -} - void IdentityManagerObserverBridge::OnRefreshTokenUpdatedForAccount( const CoreAccountInfo& account_info) { if ([delegate_
diff --git a/services/metrics/ukm_api.md b/services/metrics/ukm_api.md index a50adbe..dbcb414 100644 --- a/services/metrics/ukm_api.md +++ b/services/metrics/ukm_api.md
@@ -80,6 +80,7 @@ * `profile.country` * `profile.form_factor` +* `profile.system_ram` ## Enumeration Proportions
diff --git a/services/network/p2p/socket_tcp.cc b/services/network/p2p/socket_tcp.cc index 0895b68..89a5ac7 100644 --- a/services/network/p2p/socket_tcp.cc +++ b/services/network/p2p/socket_tcp.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/sys_byteorder.h" #include "base/threading/thread_task_runner_handle.h" +#include "base/time/time.h" #include "jingle/glue/fake_ssl_client_socket.h" #include "net/base/io_buffer.h" #include "net/base/net_errors.h" @@ -235,8 +236,9 @@ } } - client_->DataReceived(remote_address_.ip_address, data, - base::TimeTicks::Now()); + client_->DataReceived( + remote_address_.ip_address, data, + base::TimeTicks() + base::TimeDelta::FromNanoseconds(rtc::TimeNanos())); delegate_->DumpPacket( base::make_span(reinterpret_cast<const uint8_t*>(&data[0]), data.size()), @@ -296,9 +298,9 @@ write_buffer_.buffer->DidConsume(result); if (write_buffer_.buffer->BytesRemaining() == 0) { - base::TimeTicks send_time = base::TimeTicks::Now(); + int64_t send_time_ms = rtc::TimeMillis(); client_->SendComplete( - P2PSendPacketMetrics(0, write_buffer_.rtc_packet_id, send_time)); + P2PSendPacketMetrics(0, write_buffer_.rtc_packet_id, send_time_ms)); if (write_queue_.empty()) { write_buffer_.buffer = nullptr; write_buffer_.rtc_packet_id = -1; @@ -443,8 +445,7 @@ reinterpret_cast<uint8_t*>(send_buffer.buffer->data()) + kPacketHeaderSize, send_buffer.buffer->BytesRemaining() - kPacketHeaderSize, - options.packet_time_params, - (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds()); + options.packet_time_params, rtc::TimeMicros()); WriteOrQueue(send_buffer); } @@ -523,8 +524,7 @@ cricket::ApplyPacketOptions( reinterpret_cast<uint8_t*>(send_buffer.buffer->data()), data.size(), - options.packet_time_params, - (base::TimeTicks::Now() - base::TimeTicks()).InMicroseconds()); + options.packet_time_params, rtc::TimeMicros()); if (pad_bytes) { char padding[4] = {0};
diff --git a/services/network/p2p/socket_tcp_unittest.cc b/services/network/p2p/socket_tcp_unittest.cc index 6db0811..714be9c 100644 --- a/services/network/p2p/socket_tcp_unittest.cc +++ b/services/network/p2p/socket_tcp_unittest.cc
@@ -276,7 +276,7 @@ const int32_t kRtcPacketId = 1234; - base::TimeTicks now = base::TimeTicks::Now(); + int64_t now = rtc::TimeMillis(); EXPECT_CALL(*fake_client_.get(), SendComplete(MatchSendPacketMetrics(kRtcPacketId, now)))
diff --git a/services/network/p2p/socket_test_utils.h b/services/network/p2p/socket_test_utils.h index 8683e10..9315c3c 100644 --- a/services/network/p2p/socket_test_utils.h +++ b/services/network/p2p/socket_test_utils.h
@@ -159,8 +159,8 @@ MATCHER_P2(MatchSendPacketMetrics, rtc_packet_id, test_start_time, "") { return arg.rtc_packet_id == rtc_packet_id && - arg.send_time >= test_start_time && - arg.send_time <= base::TimeTicks::Now(); + arg.send_time_ms >= test_start_time && + arg.send_time_ms <= rtc::TimeMillis(); } } // namespace network
diff --git a/services/network/p2p/socket_udp.cc b/services/network/p2p/socket_udp.cc index fdaaf92..bb11a9a 100644 --- a/services/network/p2p/socket_udp.cc +++ b/services/network/p2p/socket_udp.cc
@@ -9,6 +9,7 @@ #include "base/metrics/histogram_macros.h" #include "base/stl_util.h" #include "base/strings/stringprintf.h" +#include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "net/base/io_buffer.h" @@ -222,7 +223,9 @@ } } - client_->DataReceived(recv_address_, data, base::TimeTicks::Now()); + client_->DataReceived( + recv_address_, data, + base::TimeTicks() + base::TimeDelta::FromNanoseconds(rtc::TimeNanos())); delegate_->DumpPacket( base::make_span(reinterpret_cast<uint8_t*>(&data[0]), data.size()), @@ -237,7 +240,7 @@ } bool P2PSocketUdp::DoSend(const PendingPacket& packet) { - base::TimeTicks send_time = base::TimeTicks::Now(); + int64_t send_time_us = rtc::TimeMicros(); // The peer is considered not connected until the first incoming STUN // request/response. In that state the renderer is allowed to send only STUN @@ -262,7 +265,7 @@ // and in the same order it generates them, so we need to respond even // when the packet is dropped. client_->SendComplete(P2PSendPacketMetrics( - packet.id, packet.packet_options.packet_id, send_time)); + packet.id, packet.packet_options.packet_id, send_time_us / 1000)); // Do not reset the socket. return true; } @@ -289,13 +292,12 @@ } } - cricket::ApplyPacketOptions(reinterpret_cast<uint8_t*>(packet.data->data()), - packet.size, - packet.packet_options.packet_time_params, - (send_time - base::TimeTicks()).InMicroseconds()); + cricket::ApplyPacketOptions( + reinterpret_cast<uint8_t*>(packet.data->data()), packet.size, + packet.packet_options.packet_time_params, send_time_us); auto callback_binding = base::Bind(&P2PSocketUdp::OnSend, base::Unretained(this), packet.id, - packet.packet_options.packet_id, send_time); + packet.packet_options.packet_id, send_time_us / 1000); // TODO(crbug.com/656607): Pass traffic annotation after DatagramSocketServer // is updated. @@ -313,8 +315,8 @@ if (result == net::ERR_IO_PENDING) { send_pending_ = true; } else { - if (!HandleSendResult(packet.id, packet.packet_options.packet_id, send_time, - result)) { + if (!HandleSendResult(packet.id, packet.packet_options.packet_id, + send_time_us / 1000, result)) { return false; } } @@ -329,14 +331,14 @@ void P2PSocketUdp::OnSend(uint64_t packet_id, int32_t transport_sequence_number, - base::TimeTicks send_time, + int64_t send_time_ms, int result) { DCHECK(send_pending_); DCHECK_NE(result, net::ERR_IO_PENDING); send_pending_ = false; - if (!HandleSendResult(packet_id, transport_sequence_number, send_time, + if (!HandleSendResult(packet_id, transport_sequence_number, send_time_ms, result)) { return; } @@ -353,7 +355,7 @@ bool P2PSocketUdp::HandleSendResult(uint64_t packet_id, int32_t transport_sequence_number, - base::TimeTicks send_time, + int64_t send_time_ms, int result) { TRACE_EVENT_ASYNC_END1("p2p", "Send", packet_id, "result", result); if (result < 0) { @@ -371,11 +373,12 @@ // UMA to track the histograms from 1ms to 1 sec for how long a packet spends // in the browser process. - UMA_HISTOGRAM_TIMES("WebRTC.SystemSendPacketDuration_UDP" /* name */, - base::TimeTicks::Now() - send_time /* sample */); + UMA_HISTOGRAM_TIMES( + "WebRTC.SystemSendPacketDuration_UDP" /* name */, + base::TimeDelta::FromMilliseconds(rtc::TimeMillis() - send_time_ms)); client_->SendComplete( - P2PSendPacketMetrics(packet_id, transport_sequence_number, send_time)); + P2PSendPacketMetrics(packet_id, transport_sequence_number, send_time_ms)); return true; }
diff --git a/services/network/p2p/socket_udp.h b/services/network/p2p/socket_udp.h index 8362a7f..e0d97db 100644 --- a/services/network/p2p/socket_udp.h +++ b/services/network/p2p/socket_udp.h
@@ -94,13 +94,13 @@ WARN_UNUSED_RESULT bool HandleReadResult(int result); WARN_UNUSED_RESULT bool HandleSendResult(uint64_t packet_id, int32_t transport_sequence_number, - base::TimeTicks send_time, + int64_t send_time_ms, int result); WARN_UNUSED_RESULT bool DoSend(const PendingPacket& packet); void OnSend(uint64_t packet_id, int32_t transport_sequence_number, - base::TimeTicks send_time, + int64_t send_time_ms, int result); int SetSocketDiffServCodePointInternal(net::DiffServCodePoint dscp);
diff --git a/services/network/public/cpp/p2p_param_traits.h b/services/network/public/cpp/p2p_param_traits.h index e236d37..9572939 100644 --- a/services/network/public/cpp/p2p_param_traits.h +++ b/services/network/public/cpp/p2p_param_traits.h
@@ -57,7 +57,7 @@ IPC_STRUCT_TRAITS_BEGIN(network::P2PSendPacketMetrics) IPC_STRUCT_TRAITS_MEMBER(packet_id) IPC_STRUCT_TRAITS_MEMBER(rtc_packet_id) - IPC_STRUCT_TRAITS_MEMBER(send_time) + IPC_STRUCT_TRAITS_MEMBER(send_time_ms) IPC_STRUCT_TRAITS_END() IPC_STRUCT_TRAITS_BEGIN(network::P2PPortRange)
diff --git a/services/network/public/cpp/p2p_socket_type.h b/services/network/public/cpp/p2p_socket_type.h index e88d18d0..3aa7fa7 100644 --- a/services/network/public/cpp/p2p_socket_type.h +++ b/services/network/public/cpp/p2p_socket_type.h
@@ -56,10 +56,10 @@ P2PSendPacketMetrics() {} P2PSendPacketMetrics(uint64_t packet_id, int32_t rtc_packet_id, - base::TimeTicks send_time) + int64_t send_time_ms) : packet_id(packet_id), rtc_packet_id(rtc_packet_id), - send_time(send_time) {} + send_time_ms(send_time_ms) {} uint64_t packet_id = 0; // rtc_packet_id is a sequential packet counter written in the RTP header and @@ -67,7 +67,10 @@ // corresponding send time to WebRTC in the browser process so that it can be // combined with ACKs to compute inter-packet delay variations. int32_t rtc_packet_id = -1; - base::TimeTicks send_time; + + // The time the packet was sent. Should be set using the webrtc clock + // rtc::TimeMillis() + int64_t send_time_ms = -1; }; // Struct that carries a port range.
diff --git a/services/network/throttling/throttling_controller.cc b/services/network/throttling/throttling_controller.cc index cc1d68ed..06176d94 100644 --- a/services/network/throttling/throttling_controller.cc +++ b/services/network/throttling/throttling_controller.cc
@@ -29,14 +29,6 @@ } // static -base::Optional<base::UnguessableToken> -ThrottlingController::GetProfileIDForNetLogSource(uint32_t net_log_source_id) { - if (!instance_) - return base::nullopt; - return instance_->GetProfileID(net_log_source_id); -} - -// static ThrottlingNetworkInterceptor* ThrottlingController::GetInterceptor( uint32_t net_log_source_id) { if (!instance_)
diff --git a/services/network/throttling/throttling_controller.h b/services/network/throttling/throttling_controller.h index b058a23c..f304242 100644 --- a/services/network/throttling/throttling_controller.h +++ b/services/network/throttling/throttling_controller.h
@@ -29,16 +29,6 @@ static void SetConditions(const base::UnguessableToken& throttling_profile_id, std::unique_ptr<NetworkConditions>); - // Returns the profile ID for the NetLog source ID. Returns an empty string if - // not registered. - // Note: This method is used only from ServiceWorkerFetchDispatcher to copy - // the profile ID from the net::URLRequest of original navigation request to - // the network::ResourceRequest of navigation preload request when - // S13nServiceWorker is not enabled. - // TODO(crbug/846235): Remove this method once S13nServiceWorker is shipped. - static base::Optional<base::UnguessableToken> GetProfileIDForNetLogSource( - uint32_t net_log_source_id); - // Returns the interceptor for the NetLog source ID. static ThrottlingNetworkInterceptor* GetInterceptor( uint32_t net_log_source_id);
diff --git a/services/ws/window_service_unittest.cc b/services/ws/window_service_unittest.cc index 1928508b..b20c9f7 100644 --- a/services/ws/window_service_unittest.cc +++ b/services/ws/window_service_unittest.cc
@@ -120,6 +120,15 @@ } private: + // ime::mojom::ImeEngineClient: + void CommitText(const std::string& text) override {} + void UpdateCompositionText(const ui::CompositionText& composition, + uint32_t cursor_pos, + bool visible) override {} + void DeleteSurroundingText(int32_t offset, uint32_t length) override {} + void SendKeyEvent(std::unique_ptr<ui::Event> key_event) override {} + void Reconnect() override {} + mojo::Binding<ime::mojom::ImeEngineClient> binding_; DISALLOW_COPY_AND_ASSIGN(TestImeEngineClient);
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index c001e32..213b240 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -10576,6 +10576,196 @@ } ] }, + "Linux FYI SkiaRenderer Vulkan (NVIDIA)": { + "gtest_tests": [ + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "angle_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0", + "--no-xvfb" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "angle_unittests" + }, + { + "args": [ + "--test-launcher-retry-limit=0" + ], + "should_retry_with_patch": false, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "angle_white_box_tests" + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*", + "--no-xvfb" + ], + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "browser_tests" + }, + { + "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter", + "--enable-features=VizDisplayCompositor,UseSkiaRenderer,UiGpuRasterization", + "--use-gl=any", + "--enable-oop-rasterization", + "--enable-vulkan", + "--enable-gpu-rasterization", + "--enable-raster-to-sk-image", + "--force-gpu-rasterization", + "--disable-software-compositing-fallback", + "--no-xvfb" + ], + "name": "vulkan_content_browsertests", + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "content_browsertests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--test-launcher-retry-limit=0" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ], + "shards": 4 + }, + "test": "dawn_end2end_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--use-cmd-decoder=validating" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_tests" + }, + { + "args": [ + "--use-gpu-in-tests", + "--no-xvfb" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gl_unittests" + }, + { + "args": [ + "--use-gpu-in-tests" + ], + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "gles2_conform_test" + }, + { + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "gpu": "nvidia-quadro-p400-ubuntu-stable", + "os": "Ubuntu", + "pool": "Chrome-GPU" + } + ] + }, + "test": "swiftshader_unittests" + } + ] + }, "Linux FYI dEQP Release (Intel HD 630)": { "gtest_tests": [ {
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl index bbec5e6..e6e2ec3 100644 --- a/testing/buildbot/waterfalls.pyl +++ b/testing/buildbot/waterfalls.pyl
@@ -2537,6 +2537,16 @@ 'gpu_telemetry_tests': 'gpu_fyi_linux_intel_and_nvidia_release_telemetry_tests', }, }, + 'Linux FYI SkiaRenderer Vulkan (NVIDIA)': { + 'os_type': 'linux', + 'browser_config': 'release', + 'mixins': [ + 'linux_nvidia_quadro_p400', + ], + 'test_suites': { + 'gtest_tests': 'gpu_fyi_linux_release_gtests', + }, + }, 'Linux FYI dEQP Release (Intel HD 630)': { 'os_type': 'linux', 'browser_config': 'release',
diff --git a/testing/libfuzzer/fuzzers/BUILD.gn b/testing/libfuzzer/fuzzers/BUILD.gn index 71447aef..88e5804e4 100644 --- a/testing/libfuzzer/fuzzers/BUILD.gn +++ b/testing/libfuzzer/fuzzers/BUILD.gn
@@ -401,7 +401,7 @@ "$target_gen_dir/javascript_parser.proto", ] proto_deps = [ ":gen_javascript_parser_proto" ] - proto_out_dir = "" + proto_out_dir = target_gen_dir } fuzzer_test("javascript_parser_proto_fuzzer") {
diff --git a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc index e38f88e..56f39a0 100644 --- a/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc +++ b/testing/libfuzzer/fuzzers/javascript_parser_proto_fuzzer.cc
@@ -6,7 +6,7 @@ #include <iostream> -#include "javascript_parser.pb.h" // from out/gen +#include "testing/libfuzzer/fuzzers/javascript_parser.pb.h" // from out/gen #include "testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h" #include "third_party/libprotobuf-mutator/src/src/libfuzzer/libfuzzer_macro.h"
diff --git a/testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h b/testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h index 285ed1a..d9e5a4c 100644 --- a/testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h +++ b/testing/libfuzzer/fuzzers/javascript_parser_proto_to_string.h
@@ -5,7 +5,7 @@ #ifndef TESTING_LIBFUZZER_FUZZERS_JAVASCRIPT_PARSER_PROTO_TO_STRING_H #define TESTING_LIBFUZZER_FUZZERS_JAVASCRIPT_PARSER_PROTO_TO_STRING_H -#include "javascript_parser.pb.h" // from out/gen +#include "testing/libfuzzer/fuzzers/javascript_parser.pb.h" // from out/gen #include <string>
diff --git a/testing/libfuzzer/proto/BUILD.gn b/testing/libfuzzer/proto/BUILD.gn index 47747e3..40d3a9a 100644 --- a/testing/libfuzzer/proto/BUILD.gn +++ b/testing/libfuzzer/proto/BUILD.gn
@@ -8,10 +8,6 @@ sources = [ "json.proto", ] - - # This way json.pb.h header goes into "$root_gen_dir" directory precisely, - # otherwise it goes into "$root_gen_dir" + "/testing/libfuzzer/proto/". - proto_out_dir = "" } source_set("json_proto_converter") { @@ -19,6 +15,7 @@ "json_proto_converter.cc", "json_proto_converter.h", ] + include_dirs = [ target_gen_dir ] deps = [ ":json_proto", ]
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 0b52366d..d28ea53 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -5832,10 +5832,7 @@ ], "experiments": [ { - "name": "Default", - "enable_features": [ - "WebRTC-Aec3FilterAnalyzerIncrementalAnalysisKillSwitch" - ] + "name": "SwitchEnabled" } ] }
diff --git a/third_party/blink/public/mojom/service_worker/controller_service_worker.mojom b/third_party/blink/public/mojom/service_worker/controller_service_worker.mojom index faeab18..90c777c 100644 --- a/third_party/blink/public/mojom/service_worker/controller_service_worker.mojom +++ b/third_party/blink/public/mojom/service_worker/controller_service_worker.mojom
@@ -14,7 +14,6 @@ import "third_party/blink/public/mojom/service_worker/service_worker_object.mojom"; import "third_party/blink/public/mojom/web_feature/web_feature.mojom"; -// S13nServiceWorker: // Represents a service worker that is a 'controller'. // (https://w3c.github.io/ServiceWorker/#navigator-service-worker-controller) // One of its Mojo end points (i.e. the caller end) is passed to the @@ -58,11 +57,9 @@ blink.mojom.ControllerServiceWorkerMode mode = blink.mojom.ControllerServiceWorkerMode.kNoController; - // S13nServiceWorker only: // Non-null iff there is a controller and it has a fetch event handler. ControllerServiceWorker? endpoint; - // S13nServiceWorker: // The client being controlled, used for FetchEvent#clientId. The ID is // issued by the browser process for this receiving client, and would // never change thoughout the lifetime of the client.
diff --git a/third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom b/third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom index 402efab..756800b 100644 --- a/third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom +++ b/third_party/blink/public/mojom/service_worker/controller_service_worker_mode.mojom
@@ -6,12 +6,6 @@ // Describes whether a controller service worker exists and if it has a fetch // handler. -// -// BEWARE: In non-NetS13nServiceWorker, the renderer often does not know which -// controller service worker a request will go to, as skipWaiting() may occur -// in the browser process at the same time the renderer makes a request. -// Therefore, non-NetS13nServiceWorker should usually treat -// kNoFetchEventHandler and kControlled as the same. enum ControllerServiceWorkerMode { // No controller exists. kNoController,
diff --git a/third_party/blink/public/mojom/service_worker/embedded_worker.mojom b/third_party/blink/public/mojom/service_worker/embedded_worker.mojom index 43df8684..ac10ca22 100644 --- a/third_party/blink/public/mojom/service_worker/embedded_worker.mojom +++ b/third_party/blink/public/mojom/service_worker/embedded_worker.mojom
@@ -31,53 +31,71 @@ // The id of the service worker being started. This remains fixed even if the // worker is stopped and restarted, or even if the browser restarts. int64 service_worker_version_id; + // This service worker's registration's scope: // https://w3c.github.io/ServiceWorker/#service-worker-registration-scope url.mojom.Url scope; + // This service worker's script url: // https://w3c.github.io/ServiceWorker/#dom-serviceworker-scripturl url.mojom.Url script_url; + // This service worker's script type: // https://w3c.github.io/ServiceWorker/#dfn-type ScriptType script_type; + // The string used for "user-agent" HTTP header. string user_agent; + // The id to talk with the DevTools agent for the worker. int32 worker_devtools_agent_route_id; + // Unique token identifying this worker for DevTools. mojo_base.mojom.UnguessableToken devtools_worker_token; + // When true, worker script evaluation is blocked until // EmbeddedWorkerInstanceClient::ResumeAfterDownload() is called. // This isn't used when off-the-main-thread script fetch is enabled. The // browser process is responsible for delaying execution. bool pause_after_download; + // True if starting the worker should wait until DevTools gets ready. bool wait_for_debugger; + // True if this service worker has been installed. bool is_installed; + // Determines how eagerly V8 creates the code cache. V8CacheOptions v8_cache_options; + // Used to set up fetch requests. RendererPreferences renderer_preferences; // Used to talk to the service worker from the browser process. ServiceWorker& service_worker_request; - // S13nServiceWorker: cloned and passed to each controllee to directly - // dispatch events from the controllees. + + // Cloned and passed to each controllee to directly dispatch events from the + // controllees. ControllerServiceWorker& controller_request; + // Information to transfer installed scripts from the browser to the renderer. ServiceWorkerInstalledScriptsInfo? installed_scripts_info; + // Interface for the renderer to send the status updates to the browser. associated EmbeddedWorkerInstanceHost instance_host; + // Information for creating ServiceWorkerProviderContext on the renderer. ServiceWorkerProviderInfoForStartWorker provider_info; + // Interface for the renderer to query the content settings in the browser. WorkerContentSettingsProxy content_settings_proxy; + // Interface for keeping track of the renderer preferences. RendererPreferenceWatcher& preference_watcher_request; - // S13nServiceWorker: Used to load subresources in the service worker. - // This allows the service worker to load chrome-extension:// URLs which - // the renderer's default loader factory can't load. + + // Used to load subresources in the service worker. This allows the service + // worker to load chrome-extension:// URLs which the renderer's default + // loader factory can't load. URLLoaderFactoryBundle? subresource_loader_factories; }; @@ -130,7 +148,6 @@ // EmbeddedWorkerInstanceClient, so it lives on the same message pipe as // EmbeddedWorkerInstanceClient. interface EmbeddedWorkerInstanceHost { - // S13nServiceWorker: // Called when the worker requests to be terminated. The worker will request // to be terminated when it realizes it has been idle for some time. The // browser doesn't terminate the worker when there are inflight events or
diff --git a/third_party/blink/public/mojom/service_worker/service_worker.mojom b/third_party/blink/public/mojom/service_worker/service_worker.mojom index ea0fa99f..6bf1896 100644 --- a/third_party/blink/public/mojom/service_worker/service_worker.mojom +++ b/third_party/blink/public/mojom/service_worker/service_worker.mojom
@@ -214,9 +214,7 @@ => (ServiceWorkerEventStatus status); // Arguments are passed to the event handler as parameters of SyncEvent. // Ref: https://wicg.github.io/BackgroundSync/spec/#sync-event - // S13nServiceWorker: |timeout| is the amount of time to allow this event to - // finish. - // Non-S13nServiceWorker: |timeout| is just ignored. + // |timeout| is the amount of time to allow this event to finish. DispatchSyncEvent(string id, bool last_chance, mojo_base.mojom.TimeDelta timeout) @@ -246,7 +244,6 @@ // worker. Ping() => (); - // S13nServiceWorker: // Lets the idle timer request termination immediately after all inflight // events are handled without delay. SetIdleTimerDelayToZero();
diff --git a/third_party/blink/public/mojom/service_worker/service_worker_container.mojom b/third_party/blink/public/mojom/service_worker/service_worker_container.mojom index 719910d..3e73835a 100644 --- a/third_party/blink/public/mojom/service_worker/service_worker_container.mojom +++ b/third_party/blink/public/mojom/service_worker/service_worker_container.mojom
@@ -73,7 +73,6 @@ GetRegistrationForReady() => (ServiceWorkerRegistrationObjectInfo? registration); - // S13nServiceWorker: // Returns a Mojo end point to the controller ServiceWorker. This may start a // service worker instance in a renderer process if the corresponding // instance is not alive. @@ -86,7 +85,6 @@ EnsureControllerServiceWorker(ControllerServiceWorker& controller, ControllerServiceWorkerPurpose purpose); - // S13nServiceWorker: // Makes a new endpoint to this ServiceWorkerContainerHost. CloneContainerHost(ServiceWorkerContainerHost& container_host); @@ -95,7 +93,6 @@ // you know all incoming messages up to the Ping() call have been received. Ping() => (); - // S13nServiceWorker: // Gives a hint to the browser process to update the service worker after a // controlled page load. This message is meant to be sent at a time when page // load is no longer busy, so update doesn't adversely affect performance.
diff --git a/third_party/blink/public/mojom/service_worker/service_worker_provider.mojom b/third_party/blink/public/mojom/service_worker/service_worker_provider.mojom index f86e2681..d748a51 100644 --- a/third_party/blink/public/mojom/service_worker/service_worker_provider.mojom +++ b/third_party/blink/public/mojom/service_worker/service_worker_provider.mojom
@@ -18,7 +18,6 @@ // and browser. const string kNavigation_ServiceWorkerSpec = "navigation:service_worker"; -// S13nServiceWorker: // Sent from the browser process to the renderer. Contains parameters for the // WebServiceWorkerNetworkProvider used for starting a web worker (dedicated // worker or shared worker). @@ -36,7 +35,6 @@ associated ServiceWorkerContainerHost host_ptr_info; associated ServiceWorkerContainer& client_request; - // S13nServiceWorker: // The loader to use for loading the worker's main script and // importScripts(). associated network.mojom.URLLoaderFactory? script_loader_factory_ptr_info;
diff --git a/third_party/blink/public/mojom/worker/shared_worker_factory.mojom b/third_party/blink/public/mojom/worker/shared_worker_factory.mojom index ce14a565..d254dfb 100644 --- a/third_party/blink/public/mojom/worker/shared_worker_factory.mojom +++ b/third_party/blink/public/mojom/worker/shared_worker_factory.mojom
@@ -39,11 +39,9 @@ RendererPreferenceWatcher& preference_watcher_request, WorkerContentSettingsProxy content_settings, - // S13nServiceWorker: // The info about the service worker host in the browser process that // provides support for this shared worker to be a service worker client. - // Null when S13nServiceWorker is disabled. - ServiceWorkerProviderInfoForWorker? service_worker_provider_info, + ServiceWorkerProviderInfoForWorker service_worker_provider_info, // NetworkService: // The ID of the AppCacheHost in the browser process that serves resources @@ -51,13 +49,12 @@ // is disabled or AppCache doesn't serve resources for this shared worker. int32 appcache_host_id, - // S13nServiceWorker (non-NetworkService): + // Non-NetworkService: // The URLLoaderFactory to use to request the shared worker's script // (just the main script resource; importScripts() should go through the // usual loader or the controller service worker if appropriate). // - // This is only non-null when S13nServiceWorker is enabled but - // NetworkService is disabled. + // This is only non-null when NetworkService is disabled. // // TODO(leonhsl): It doesn't really need to be associated. Make it // non-associated and update @@ -80,9 +77,9 @@ // NetworkService (PlzWorker): // Used for setting ServiceWorkerContainer#controller. This is null when - // NetworkService is disabled or there're no controller service worker. + // NetworkService is disabled or there is no controller service worker. // - // In S13nServiceWorker, the controller is sent via + // In non-NetworkService, the controller is sent via // ServiceWorkerContainer.SetController(). ControllerServiceWorkerInfo? controller_info,
diff --git a/third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h b/third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h index e2b1d91..4a78b88 100644 --- a/third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h +++ b/third_party/blink/public/platform/modules/service_worker/web_service_worker_network_provider.h
@@ -62,7 +62,6 @@ // request made. virtual void WillSendRequest(WebURLRequest&) = 0; - // S13nServiceWorker: // Returns a URLLoader for loading |request|. May return nullptr to fall back // to the default loading behavior. virtual std::unique_ptr<WebURLLoader> CreateURLLoader(
diff --git a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc index fc5dee6..0243503 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_promise_resolver_test.cc
@@ -223,15 +223,13 @@ MakeGarbageCollected<ScriptPromiseResolverKeepAlive>(GetScriptState()); } resolver->KeepAliveWhilePending(); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); ASSERT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive()); resolver->Resolve("hello"); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive()); } @@ -244,15 +242,13 @@ MakeGarbageCollected<ScriptPromiseResolverKeepAlive>(GetScriptState()); } resolver->KeepAliveWhilePending(); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); ASSERT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive()); resolver->Reject("hello"); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive()); } @@ -269,17 +265,15 @@ ScriptForbiddenScope forbidden; resolver->Resolve("hello"); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive()); } base::RunLoop().RunUntilIdle(); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive()); } @@ -292,15 +286,13 @@ MakeGarbageCollected<ScriptPromiseResolverKeepAlive>(GetScriptState()); } resolver->KeepAliveWhilePending(); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive()); GetExecutionContext()->NotifyContextDestroyed(); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive()); } @@ -313,22 +305,19 @@ MakeGarbageCollected<ScriptPromiseResolverKeepAlive>(GetScriptState()); } resolver->KeepAliveWhilePending(); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); ASSERT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive()); GetExecutionContext()->SetLifecycleState(mojom::FrameLifecycleState::kFrozen); resolver->Resolve("hello"); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_TRUE(ScriptPromiseResolverKeepAlive::IsAlive()); GetExecutionContext()->NotifyContextDestroyed(); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_FALSE(ScriptPromiseResolverKeepAlive::IsAlive()); }
diff --git a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc index ce55ccc..762889f7 100644 --- a/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc +++ b/third_party/blink/renderer/bindings/core/v8/script_streamer_test.cc
@@ -527,9 +527,8 @@ EXPECT_FALSE(resource_client_->Finished()); resource_ = nullptr; - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); } // TODO(crbug.com/939054): Tests are disabled due to flakiness caused by being
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc index a9e32990..75fd7fa 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_deserializer_for_modules.cc
@@ -350,7 +350,7 @@ key)) return nullptr; - return CryptoKey::Create(key); + return MakeGarbageCollected<CryptoKey>(key); } bool V8ScriptValueDeserializerForModules::ReadLandmark(Landmark* landmark) {
diff --git a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc index 3155d64..5548998 100644 --- a/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc +++ b/third_party/blink/renderer/bindings/modules/v8/serialization/v8_script_value_serializer_for_modules_test.cc
@@ -290,7 +290,7 @@ template <typename T> WebCryptoResult ToWebCryptoResult(ScriptState* script_state, base::RepeatingCallback<void(T)> function) { - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); result->Promise().Then( (MakeGarbageCollected<WebCryptoResultAdapter<T>>(script_state, std::move(function)))
diff --git a/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h b/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h index a3d3f04..645f4d52 100644 --- a/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h +++ b/third_party/blink/renderer/core/css/cssom/paint_worklet_input.h
@@ -48,11 +48,11 @@ gfx::SizeF GetSize() const override { return gfx::SizeF(container_size_.Width(), container_size_.Height()); } + int WorkletId() const override { return worklet_id_; } // These accessors are safe on any thread. const FloatSize& ContainerSize() const { return container_size_; } float EffectiveZoom() const { return effective_zoom_; } - int WorkletId() const { return worklet_id_; } // These should only be accessed on the PaintWorklet thread. String NameCopy() const { return name_.IsolatedCopy(); }
diff --git a/third_party/blink/renderer/core/dom/dom_node_ids_test.cc b/third_party/blink/renderer/core/dom/dom_node_ids_test.cc index d8038d99..7449a51 100644 --- a/third_party/blink/renderer/core/dom/dom_node_ids_test.cc +++ b/third_party/blink/renderer/core/dom/dom_node_ids_test.cc
@@ -39,9 +39,8 @@ DOMNodeId id_a = DOMNodeIds::IdForNode(a); a->remove(); - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_EQ(nullptr, DOMNodeIds::NodeForId(id_a)); }
diff --git a/third_party/blink/renderer/core/dom/mutation_observer_test.cc b/third_party/blink/renderer/core/dom/mutation_observer_test.cc index 63598f40..916625bf 100644 --- a/third_party/blink/renderer/core/dom/mutation_observer_test.cc +++ b/third_party/blink/renderer/core/dom/mutation_observer_test.cc
@@ -51,9 +51,8 @@ observer->registrations_.begin()->Get(); // The following GC will collect |head|, but won't collect a // MutationObserverRegistration for |head|. - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); observer->disconnect(); // The test passes if disconnect() didn't crash. crbug.com/657613. }
diff --git a/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc b/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc index 1773c2a9..6d712d0 100644 --- a/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc +++ b/third_party/blink/renderer/core/dom/weak_identifier_map_test.cc
@@ -22,9 +22,8 @@ void TearDown() override; void CollectGarbage() { - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); } };
diff --git a/third_party/blink/renderer/core/exported/web_heap.cc b/third_party/blink/renderer/core/exported/web_heap.cc index 642006f..8d9af33 100644 --- a/third_party/blink/renderer/core/exported/web_heap.cc +++ b/third_party/blink/renderer/core/exported/web_heap.cc
@@ -36,9 +36,8 @@ namespace blink { void WebHeap::CollectGarbageForTesting() { - ThreadState::Current()->CollectGarbage( - BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kHeapPointersOnStack); } void WebHeap::CollectAllGarbageForTesting() {
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc index 23f82d77..2418d77 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.cc
@@ -206,6 +206,8 @@ void WebSharedWorkerImpl::Connect(MessagePortChannel web_channel) { DCHECK(IsMainThread()); + if (asked_to_terminate_) + return; // The HTML spec requires to queue a connect event using the DOM manipulation // task source. // https://html.spec.whatwg.org/C/#shared-workers-and-the-sharedworker-interface @@ -292,16 +294,11 @@ main_script_loader_->Identifier(), main_script_loader_->SourceText()); - // S13nServiceWorker: The browser process is expected to send a - // SetController IPC before sending the script response, but there is no - // guarantee of the ordering as the messages arrive on different message - // pipes. Wait for the SetController IPC to be received before starting the - // worker; otherwise fetches from the worker might not go through the - // appropriate controller. - // - // (For non-S13nServiceWorker, we don't need to do this step as the controller - // service worker isn't used directly by the renderer, but to minimize code - // differences between the flags just do it anyway.) + // The browser process is expected to send a SetController IPC before sending + // the script response, but there is no guarantee of the ordering as the + // messages arrive on different message pipes. Wait for the SetController IPC + // to be received before starting the worker; otherwise fetches from the + // worker might not go through the appropriate controller. client_->WaitForServiceWorkerControllerInfo( shadow_page_->DocumentLoader()->GetServiceWorkerNetworkProvider(), WTF::Bind(&WebSharedWorkerImpl::ContinueStartWorkerContext,
diff --git a/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc b/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc index 80899ea5..620d420d 100644 --- a/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc +++ b/third_party/blink/renderer/core/fetch/fetch_data_loader_test.cc
@@ -7,11 +7,16 @@ #include <memory> #include "base/stl_util.h" +#include "mojo/public/cpp/system/data_pipe_utils.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/core/fetch/bytes_consumer_test_util.h" #include "third_party/blink/renderer/core/fileapi/blob.h" #include "third_party/blink/renderer/core/html/forms/form_data.h" +#include "third_party/blink/renderer/platform/loader/fetch/data_pipe_bytes_consumer.h" +#include "third_party/blink/renderer/platform/loader/testing/bytes_consumer_test_reader.h" +#include "third_party/blink/renderer/platform/loader/testing/replaying_bytes_consumer.h" +#include "third_party/blink/renderer/platform/scheduler/test/fake_task_runner.h" namespace blink { @@ -58,7 +63,50 @@ constexpr size_t kQuickBrownFoxFormDataLength = base::size(kQuickBrownFoxFormData) - 1u; -TEST(FetchDataLoaderTest, LoadAsBlob) { +class FetchDataLoaderTest : public testing::Test { + protected: + struct PipingClient : public GarbageCollectedFinalized<PipingClient>, + public FetchDataLoader::Client { + USING_GARBAGE_COLLECTED_MIXIN(PipingClient); + + public: + explicit PipingClient( + scoped_refptr<base::SingleThreadTaskRunner> task_runner) + : task_runner_(std::move(task_runner)) {} + + void DidFetchDataStartedDataPipe( + mojo::ScopedDataPipeConsumerHandle handle) override { + DataPipeBytesConsumer::CompletionNotifier* notifier; + destination_ = MakeGarbageCollected<DataPipeBytesConsumer>( + task_runner_, std::move(handle), ¬ifier); + completion_notifier_ = notifier; + } + void DidFetchDataLoadedDataPipe() override { + completion_notifier_->SignalComplete(); + } + void DidFetchDataLoadFailed() override { + completion_notifier_->SignalError(BytesConsumer::Error()); + } + void Abort() override { + completion_notifier_->SignalError(BytesConsumer::Error()); + } + + BytesConsumer* GetDestination() { return destination_; } + + void Trace(Visitor* visitor) override { + visitor->Trace(destination_); + visitor->Trace(completion_notifier_); + FetchDataLoader::Client::Trace(visitor); + } + + private: + const scoped_refptr<base::SingleThreadTaskRunner> task_runner_; + Member<BytesConsumer> destination_; + Member<DataPipeBytesConsumer::CompletionNotifier> completion_notifier_; + }; +}; + +TEST_F(FetchDataLoaderTest, LoadAsBlob) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -107,7 +155,7 @@ EXPECT_EQ(String("text/test"), blob_data_handle->GetType()); } -TEST(FetchDataLoaderTest, LoadAsBlobFailed) { +TEST_F(FetchDataLoaderTest, LoadAsBlobFailed) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -150,7 +198,7 @@ checkpoint.Call(4); } -TEST(FetchDataLoaderTest, LoadAsBlobCancel) { +TEST_F(FetchDataLoaderTest, LoadAsBlobCancel) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -181,8 +229,8 @@ checkpoint.Call(3); } -TEST(FetchDataLoaderTest, - LoadAsBlobViaDrainAsBlobDataHandleWithSameContentType) { +TEST_F(FetchDataLoaderTest, + LoadAsBlobViaDrainAsBlobDataHandleWithSameContentType) { auto blob_data = std::make_unique<BlobData>(); blob_data->AppendBytes(kQuickBrownFox, kQuickBrownFoxLengthWithTerminatingNull); @@ -223,8 +271,8 @@ EXPECT_EQ(String("text/test"), blob_data_handle->GetType()); } -TEST(FetchDataLoaderTest, - LoadAsBlobViaDrainAsBlobDataHandleWithDifferentContentType) { +TEST_F(FetchDataLoaderTest, + LoadAsBlobViaDrainAsBlobDataHandleWithDifferentContentType) { auto blob_data = std::make_unique<BlobData>(); blob_data->AppendBytes(kQuickBrownFox, kQuickBrownFoxLengthWithTerminatingNull); @@ -265,7 +313,7 @@ EXPECT_EQ(String("text/test"), blob_data_handle->GetType()); } -TEST(FetchDataLoaderTest, LoadAsArrayBuffer) { +TEST_F(FetchDataLoaderTest, LoadAsArrayBuffer) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -311,7 +359,7 @@ EXPECT_STREQ(kQuickBrownFox, static_cast<const char*>(array_buffer->Data())); } -TEST(FetchDataLoaderTest, LoadAsArrayBufferFailed) { +TEST_F(FetchDataLoaderTest, LoadAsArrayBufferFailed) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -350,7 +398,7 @@ checkpoint.Call(4); } -TEST(FetchDataLoaderTest, LoadAsArrayBufferCancel) { +TEST_F(FetchDataLoaderTest, LoadAsArrayBufferCancel) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -377,7 +425,7 @@ checkpoint.Call(3); } -TEST(FetchDataLoaderTest, LoadAsFormData) { +TEST_F(FetchDataLoaderTest, LoadAsFormData) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -446,7 +494,7 @@ EXPECT_EQ(kQuickBrownFox, form_data->Entries()[3]->Value()); } -TEST(FetchDataLoaderTest, LoadAsFormDataPartialInput) { +TEST_F(FetchDataLoaderTest, LoadAsFormDataPartialInput) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -485,7 +533,7 @@ checkpoint.Call(4); } -TEST(FetchDataLoaderTest, LoadAsFormDataFailed) { +TEST_F(FetchDataLoaderTest, LoadAsFormDataFailed) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -524,7 +572,7 @@ checkpoint.Call(4); } -TEST(FetchDataLoaderTest, LoadAsFormDataCancel) { +TEST_F(FetchDataLoaderTest, LoadAsFormDataCancel) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -551,7 +599,7 @@ checkpoint.Call(3); } -TEST(FetchDataLoaderTest, LoadAsString) { +TEST_F(FetchDataLoaderTest, LoadAsString) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -590,7 +638,7 @@ checkpoint.Call(4); } -TEST(FetchDataLoaderTest, LoadAsStringWithNullBytes) { +TEST_F(FetchDataLoaderTest, LoadAsStringWithNullBytes) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -630,7 +678,7 @@ checkpoint.Call(4); } -TEST(FetchDataLoaderTest, LoadAsStringError) { +TEST_F(FetchDataLoaderTest, LoadAsStringError) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -668,7 +716,7 @@ checkpoint.Call(4); } -TEST(FetchDataLoaderTest, LoadAsStringCancel) { +TEST_F(FetchDataLoaderTest, LoadAsStringCancel) { Checkpoint checkpoint; BytesConsumer::Client* client = nullptr; auto* consumer = MakeGarbageCollected<MockBytesConsumer>(); @@ -694,6 +742,115 @@ checkpoint.Call(3); } +TEST_F(FetchDataLoaderTest, LoadAsDataPipeWithCopy) { + using Command = ReplayingBytesConsumer::Command; + auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>(); + auto* src = MakeGarbageCollected<ReplayingBytesConsumer>(task_runner); + src->Add(Command(Command::Name::kData, "hello, ")); + src->Add(Command(Command::Name::kDataAndDone, "world")); + + auto* loader = FetchDataLoader::CreateLoaderAsDataPipe(task_runner); + auto* client = MakeGarbageCollected<PipingClient>(task_runner); + loader->Start(src, client); + + BytesConsumer* dest = client->GetDestination(); + ASSERT_TRUE(dest); + + auto* reader = MakeGarbageCollected<BytesConsumerTestReader>(dest); + auto result = reader->Run(task_runner.get()); + + EXPECT_EQ(result.first, BytesConsumer::Result::kDone); + EXPECT_EQ(String(result.second.data(), result.second.size()), "hello, world"); +} + +TEST_F(FetchDataLoaderTest, LoadAsDataPipeWithCopyFailure) { + using Command = ReplayingBytesConsumer::Command; + auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>(); + auto* src = MakeGarbageCollected<ReplayingBytesConsumer>(task_runner); + src->Add(Command(Command::Name::kData, "hello, ")); + src->Add(Command(Command::Name::kError)); + + auto* loader = FetchDataLoader::CreateLoaderAsDataPipe(task_runner); + auto* client = MakeGarbageCollected<PipingClient>(task_runner); + loader->Start(src, client); + + BytesConsumer* dest = client->GetDestination(); + ASSERT_TRUE(dest); + + auto* reader = MakeGarbageCollected<BytesConsumerTestReader>(dest); + auto result = reader->Run(task_runner.get()); + + EXPECT_EQ(result.first, BytesConsumer::Result::kError); +} + +TEST_F(FetchDataLoaderTest, LoadAsDataPipeFromDataPipe) { + auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>(); + mojo::ScopedDataPipeConsumerHandle readable; + mojo::ScopedDataPipeProducerHandle writable; + MojoResult rv = mojo::CreateDataPipe(nullptr, &writable, &readable); + ASSERT_EQ(rv, MOJO_RESULT_OK); + + ASSERT_TRUE(mojo::BlockingCopyFromString("hello", writable)); + + DataPipeBytesConsumer::CompletionNotifier* completion_notifier = nullptr; + auto* src = MakeGarbageCollected<DataPipeBytesConsumer>( + task_runner, std::move(readable), &completion_notifier); + + auto* loader = FetchDataLoader::CreateLoaderAsDataPipe(task_runner); + auto* client = MakeGarbageCollected<PipingClient>(task_runner); + loader->Start(src, client); + + BytesConsumer* dest = client->GetDestination(); + ASSERT_TRUE(dest); + + const char* buffer = nullptr; + size_t available = 0; + auto result = dest->BeginRead(&buffer, &available); + ASSERT_EQ(result, BytesConsumer::Result::kOk); + EXPECT_EQ(available, 5u); + EXPECT_EQ(std::string(buffer, available), "hello"); + result = dest->EndRead(available); + ASSERT_EQ(result, BytesConsumer::Result::kOk); + + result = dest->BeginRead(&buffer, &available); + ASSERT_EQ(result, BytesConsumer::Result::kShouldWait); + + writable.reset(); + result = dest->BeginRead(&buffer, &available); + ASSERT_EQ(result, BytesConsumer::Result::kShouldWait); + + completion_notifier->SignalComplete(); + result = dest->BeginRead(&buffer, &available); + ASSERT_EQ(result, BytesConsumer::Result::kDone); +} + +TEST_F(FetchDataLoaderTest, LoadAsDataPipeFromDataPipeFailure) { + auto task_runner = base::MakeRefCounted<scheduler::FakeTaskRunner>(); + mojo::ScopedDataPipeConsumerHandle readable; + mojo::ScopedDataPipeProducerHandle writable; + MojoResult rv = mojo::CreateDataPipe(nullptr, &writable, &readable); + ASSERT_EQ(rv, MOJO_RESULT_OK); + + ASSERT_TRUE(mojo::BlockingCopyFromString("hello", writable)); + + DataPipeBytesConsumer::CompletionNotifier* completion_notifier = nullptr; + auto* src = MakeGarbageCollected<DataPipeBytesConsumer>( + task_runner, std::move(readable), &completion_notifier); + + auto* loader = FetchDataLoader::CreateLoaderAsDataPipe(task_runner); + auto* client = MakeGarbageCollected<PipingClient>(task_runner); + loader->Start(src, client); + + BytesConsumer* dest = client->GetDestination(); + ASSERT_TRUE(dest); + + completion_notifier->SignalError(BytesConsumer::Error()); + auto* reader = MakeGarbageCollected<BytesConsumerTestReader>(dest); + auto result = reader->Run(task_runner.get()); + + EXPECT_EQ(result.first, BytesConsumer::Result::kError); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc index 727cc79..cbb2f65 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy_fuzzer.cc
@@ -52,9 +52,8 @@ // Force a garbage collection. // Specify namespace explicitly. Otherwise it conflicts on Mac OS X with: // CoreServices.framework/Frameworks/CarbonCore.framework/Headers/Threads.h. - blink::ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); return 0; }
diff --git a/third_party/blink/renderer/core/html/canvas/text_metrics.idl b/third_party/blink/renderer/core/html/canvas/text_metrics.idl index b837104..367d5d53 100644 --- a/third_party/blink/renderer/core/html/canvas/text_metrics.idl +++ b/third_party/blink/renderer/core/html/canvas/text_metrics.idl
@@ -28,7 +28,7 @@ // TODO(foolip): Exposed=(Window,Worker) interface TextMetrics { // x-direction - readonly attribute float width; // advance width + readonly attribute double width; // advance width [RuntimeEnabled=ExtendedTextMetrics] readonly attribute FrozenArray<double> advances; [RuntimeEnabled=ExtendedTextMetrics] readonly attribute double actualBoundingBoxLeft; [RuntimeEnabled=ExtendedTextMetrics] readonly attribute double actualBoundingBoxRight;
diff --git a/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc b/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc index ebba576..d5ad417 100644 --- a/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc +++ b/third_party/blink/renderer/core/imagebitmap/image_bitmap_test.cc
@@ -90,9 +90,8 @@ // Garbage collection is required prior to switching out the // test's memory cache; image resources are released, evicting // them from the cache. - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); ReplaceMemoryCacheForTesting(global_memory_cache_.Release()); SharedGpuContext::ResetForTesting();
diff --git a/third_party/blink/renderer/core/paint/theme_painter_default.cc b/third_party/blink/renderer/core/paint/theme_painter_default.cc index d4f4e51b..02c262ed 100644 --- a/third_party/blink/renderer/core/paint/theme_painter_default.cc +++ b/third_party/blink/renderer/core/paint/theme_painter_default.cc
@@ -214,6 +214,15 @@ if (style.HasBorderRadius() || style.HasBackgroundImage()) return true; + // Don't use the theme painter if dark mode is enabled. It has a separate + // graphics pipeline that doesn't go through GraphicsContext and so does not + // currently know how to handle Dark Mode, causing elements to be rendered + // incorrectly (e.g. https://crbug.com/937872). + // TODO(gilmanmh): Implement a more permanent solution that allows use of + // native dark themes. + if (paint_info.context.dark_mode_settings().mode != DarkMode::kOff) + return true; + ControlPart part = style.Appearance(); WebThemeEngine::ExtraParams extra_params; @@ -466,8 +475,7 @@ // pixel off-center, it will be one pixel closer to the bottom of the field. // This tends to look better with the text. LayoutRect cancel_button_rect( - cancel_button_object.OffsetFromAncestor(&input_layout_box) - .Width(), + cancel_button_object.OffsetFromAncestor(&input_layout_box).Width(), input_content_box.Y() + (input_content_box.Height() - cancel_button_size + 1) / 2, cancel_button_size, cancel_button_size);
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.h b/third_party/blink/renderer/core/svg/graphics/svg_image.h index e2391c5..b02db39 100644 --- a/third_party/blink/renderer/core/svg/graphics/svg_image.h +++ b/third_party/blink/renderer/core/svg/graphics/svg_image.h
@@ -212,6 +212,14 @@ void LoadCompleted(); void NotifyAsyncLoadCompleted(); + // TODO(v.paturi): Implement an SVG classifier which can decide if a + // filter should be applied based on the image's content and it's + // visibility on a dark background. + DarkModeClassification ClassifyImageForDarkMode( + const FloatRect& src_rect) override { + return DarkModeClassification::kApplyDarkModeFilter; + } + class SVGImageLocalFrameClient; Persistent<SVGImageChromeClient> chrome_client_;
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h b/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h index 63e8dcf..6348dbd 100644 --- a/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h +++ b/third_party/blink/renderer/core/svg/graphics/svg_image_for_container.h
@@ -88,8 +88,6 @@ PaintImage PaintImageForCurrentFrame() override; - bool IsSVGImageForContainer() const override { return true; } - protected: void DrawPattern(GraphicsContext&, const FloatRect&, @@ -111,6 +109,14 @@ void DestroyDecodedData() override {} + // TODO(v.paturi): Implement an SVG classifier which can decide if a + // filter should be applied based on the image's content and it's + // visibility on a dark background. + DarkModeClassification ClassifyImageForDarkMode( + const FloatRect& src_rect) override { + return DarkModeClassification::kApplyDarkModeFilter; + } + SVGImage* image_; const FloatSize container_size_; const float zoom_;
diff --git a/third_party/blink/renderer/core/workers/worker_thread.h b/third_party/blink/renderer/core/workers/worker_thread.h index c82c19d..53bab65 100644 --- a/third_party/blink/renderer/core/workers/worker_thread.h +++ b/third_party/blink/renderer/core/workers/worker_thread.h
@@ -222,6 +222,7 @@ // and underlying thread. After the global scope is destroyed, queued tasks // are discarded and PostTask on the returned task runner just fails. This // function can be called on both the main thread and the worker thread. + // You must not call this after Terminate() is called. scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner(TaskType type) { return worker_scheduler_->GetTaskRunner(type); }
diff --git a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc index 648d3c46..ecfe1761 100644 --- a/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc +++ b/third_party/blink/renderer/modules/canvas/canvas2d/canvas_rendering_context_2d_test.cc
@@ -236,9 +236,9 @@ } void CanvasRenderingContext2DTest::TearDown() { - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); + ReplaceMemoryCacheForTesting(global_memory_cache_.Release()); SharedGpuContext::ResetForTesting(); }
diff --git a/third_party/blink/renderer/modules/crypto/crypto.cc b/third_party/blink/renderer/modules/crypto/crypto.cc index 7c5bf68..67328c7 100644 --- a/third_party/blink/renderer/modules/crypto/crypto.cc +++ b/third_party/blink/renderer/modules/crypto/crypto.cc
@@ -76,7 +76,7 @@ SubtleCrypto* Crypto::subtle() { if (!subtle_crypto_) - subtle_crypto_ = SubtleCrypto::Create(); + subtle_crypto_ = MakeGarbageCollected<SubtleCrypto>(); return subtle_crypto_.Get(); }
diff --git a/third_party/blink/renderer/modules/crypto/crypto_key.h b/third_party/blink/renderer/modules/crypto/crypto_key.h index 5ad7246..8b6d315 100644 --- a/third_party/blink/renderer/modules/crypto/crypto_key.h +++ b/third_party/blink/renderer/modules/crypto/crypto_key.h
@@ -47,10 +47,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static CryptoKey* Create(const WebCryptoKey& key) { - return MakeGarbageCollected<CryptoKey>(key); - } - explicit CryptoKey(const WebCryptoKey&); ~CryptoKey() override;
diff --git a/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc b/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc index a4de48e4..f10efd9 100644 --- a/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc +++ b/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc
@@ -129,10 +129,6 @@ resolver_ = nullptr; } -CryptoResultImpl* CryptoResultImpl::Create(ScriptState* script_state) { - return MakeGarbageCollected<CryptoResultImpl>(script_state); -} - void CryptoResultImpl::CompleteWithError(WebCryptoErrorType error_type, const WebString& error_details) { if (!resolver_) @@ -201,7 +197,7 @@ if (!resolver_) return; - resolver_->Resolve(CryptoKey::Create(key)); + resolver_->Resolve(MakeGarbageCollected<CryptoKey>(key)); ClearResolver(); } @@ -216,9 +212,11 @@ V8ObjectBuilder key_pair(script_state); key_pair.Add("publicKey", - ScriptValue::From(script_state, CryptoKey::Create(public_key))); + ScriptValue::From(script_state, + MakeGarbageCollected<CryptoKey>(public_key))); key_pair.Add("privateKey", - ScriptValue::From(script_state, CryptoKey::Create(private_key))); + ScriptValue::From(script_state, + MakeGarbageCollected<CryptoKey>(private_key))); resolver_->Resolve(key_pair.V8Value()); ClearResolver();
diff --git a/third_party/blink/renderer/modules/crypto/crypto_result_impl.h b/third_party/blink/renderer/modules/crypto/crypto_result_impl.h index f1e97954..0a059cd 100644 --- a/third_party/blink/renderer/modules/crypto/crypto_result_impl.h +++ b/third_party/blink/renderer/modules/crypto/crypto_result_impl.h
@@ -55,8 +55,6 @@ // m_resolver will be leaked until the ExecutionContext is destroyed. class MODULES_EXPORT CryptoResultImpl final : public CryptoResult { public: - static CryptoResultImpl* Create(ScriptState*); - explicit CryptoResultImpl(ScriptState*); ~CryptoResultImpl() override;
diff --git a/third_party/blink/renderer/modules/crypto/dom_window_crypto.cc b/third_party/blink/renderer/modules/crypto/dom_window_crypto.cc index 36dac7d0..97b16247 100644 --- a/third_party/blink/renderer/modules/crypto/dom_window_crypto.cc +++ b/third_party/blink/renderer/modules/crypto/dom_window_crypto.cc
@@ -56,7 +56,7 @@ Crypto* DOMWindowCrypto::crypto() const { if (!crypto_) - crypto_ = Crypto::Create(); + crypto_ = MakeGarbageCollected<Crypto>(); return crypto_.Get(); }
diff --git a/third_party/blink/renderer/modules/crypto/subtle_crypto.cc b/third_party/blink/renderer/modules/crypto/subtle_crypto.cc index 5f83946b..6dbc3f4 100644 --- a/third_party/blink/renderer/modules/crypto/subtle_crypto.cc +++ b/third_party/blink/renderer/modules/crypto/subtle_crypto.cc
@@ -167,7 +167,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-encrypt - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); // 14.3.1.2: Let data be the result of getting a copy of the bytes held by @@ -209,7 +209,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-decrypt - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); // 14.3.2.2: Let data be the result of getting a copy of the bytes held by @@ -251,7 +251,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-sign - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); // 14.3.3.2: Let data be the result of getting a copy of the bytes held by @@ -295,7 +295,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-verify - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); // 14.3.4.2: Let signature be the result of getting a copy of the bytes @@ -340,7 +340,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-digest - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); // 14.3.5.2: Let data be the result of getting a copy of the bytes held @@ -373,7 +373,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-generateKey - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); WebCryptoKeyUsageMask key_usages; @@ -413,7 +413,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-importKey - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); WebCryptoKeyFormat format; @@ -497,7 +497,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-exportKey - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); WebCryptoKeyFormat format; @@ -530,7 +530,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-wrapKey - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); WebCryptoKeyFormat format; @@ -595,7 +595,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-unwrapKey - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); WebCryptoKeyFormat format; @@ -667,7 +667,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#dfn-SubtleCrypto-method-deriveBits - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); // 14.3.8.2: Let normalizedAlgorithm be the result of normalizing an @@ -709,7 +709,7 @@ // Method described by: // https://w3c.github.io/webcrypto/Overview.html#SubtleCrypto-method-deriveKey - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); WebCryptoKeyUsageMask key_usages;
diff --git a/third_party/blink/renderer/modules/crypto/subtle_crypto.h b/third_party/blink/renderer/modules/crypto/subtle_crypto.h index 87185e6..e112079 100644 --- a/third_party/blink/renderer/modules/crypto/subtle_crypto.h +++ b/third_party/blink/renderer/modules/crypto/subtle_crypto.h
@@ -50,8 +50,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static SubtleCrypto* Create() { return MakeGarbageCollected<SubtleCrypto>(); } - SubtleCrypto(); ScriptPromise encrypt(ScriptState*,
diff --git a/third_party/blink/renderer/modules/crypto/worker_global_scope_crypto.cc b/third_party/blink/renderer/modules/crypto/worker_global_scope_crypto.cc index bec0df05..5f0b33f 100644 --- a/third_party/blink/renderer/modules/crypto/worker_global_scope_crypto.cc +++ b/third_party/blink/renderer/modules/crypto/worker_global_scope_crypto.cc
@@ -58,7 +58,7 @@ Crypto* WorkerGlobalScopeCrypto::crypto() const { if (!crypto_) - crypto_ = Crypto::Create(); + crypto_ = MakeGarbageCollected<Crypto>(); return crypto_.Get(); }
diff --git a/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc b/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc index c961997..a267772 100644 --- a/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc +++ b/third_party/blink/renderer/modules/csspaint/css_paint_definition.cc
@@ -33,19 +33,6 @@ } // namespace -CSSPaintDefinition* CSSPaintDefinition::Create( - ScriptState* script_state, - V8NoArgumentConstructor* constructor, - V8PaintCallback* paint, - const Vector<CSSPropertyID>& native_invalidation_properties, - const Vector<AtomicString>& custom_invalidation_properties, - const Vector<CSSSyntaxDescriptor>& input_argument_types, - const PaintRenderingContext2DSettings* context_settings) { - return MakeGarbageCollected<CSSPaintDefinition>( - script_state, constructor, paint, native_invalidation_properties, - custom_invalidation_properties, input_argument_types, context_settings); -} - CSSPaintDefinition::CSSPaintDefinition( ScriptState* script_state, V8NoArgumentConstructor* constructor, @@ -66,16 +53,12 @@ CSSPaintDefinition::~CSSPaintDefinition() = default; -scoped_refptr<Image> CSSPaintDefinition::Paint( - const ImageResourceObserver& client, +sk_sp<PaintRecord> CSSPaintDefinition::Paint( const FloatSize& container_size, + float zoom, + StylePropertyMapReadOnly* style_map, const CSSStyleValueVector* paint_arguments) { - // TODO: Break dependency on LayoutObject. Passing the Node should work. - const LayoutObject& layout_object = static_cast<const LayoutObject&>(client); - - float zoom = layout_object.StyleRef().EffectiveZoom(); const FloatSize specified_size = GetSpecifiedSize(container_size, zoom); - ScriptState::Scope scope(script_state_); MaybeCreatePaintInstance(); @@ -86,21 +69,15 @@ v8::Isolate* isolate = script_state_->GetIsolate(); - DCHECK(layout_object.GetNode()); CanvasColorParams color_params; if (!context_settings_->alpha()) { color_params.SetOpacityMode(kOpaque); } // Do subpixel snapping for the |container_size|. - PaintRenderingContext2D* rendering_context = PaintRenderingContext2D::Create( + auto* rendering_context = MakeGarbageCollected<PaintRenderingContext2D>( RoundedIntSize(container_size), color_params, context_settings_, zoom); - PaintSize* paint_size = PaintSize::Create(specified_size); - StylePropertyMapReadOnly* style_map = - MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>( - layout_object.GetDocument(), layout_object.StyleRef(), - layout_object.GetNode(), native_invalidation_properties_, - custom_invalidation_properties_); + PaintSize* paint_size = MakeGarbageCollected<PaintSize>(specified_size); CSSStyleValueVector empty_paint_arguments; if (!paint_arguments) @@ -118,8 +95,7 @@ return nullptr; } - return PaintGeneratedImage::Create(rendering_context->GetRecord(), - container_size); + return rendering_context->GetRecord(); } void CSSPaintDefinition::MaybeCreatePaintInstance() {
diff --git a/third_party/blink/renderer/modules/csspaint/css_paint_definition.h b/third_party/blink/renderer/modules/csspaint/css_paint_definition.h index abde5b64..c5becea 100644 --- a/third_party/blink/renderer/modules/csspaint/css_paint_definition.h +++ b/third_party/blink/renderer/modules/csspaint/css_paint_definition.h
@@ -14,14 +14,15 @@ #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" #include "third_party/blink/renderer/platform/geometry/float_size.h" +#include "third_party/blink/renderer/platform/graphics/paint/paint_record.h" #include "third_party/blink/renderer/platform/heap/handle.h" +#include "third_party/skia/include/core/SkRefCnt.h" #include "v8/include/v8.h" namespace blink { -class Image; -class ImageResourceObserver; class ScriptState; +class StylePropertyMapReadOnly; class V8NoArgumentConstructor; class V8PaintCallback; @@ -32,15 +33,6 @@ : public GarbageCollectedFinalized<CSSPaintDefinition>, public NameClient { public: - static CSSPaintDefinition* Create( - ScriptState*, - V8NoArgumentConstructor* constructor, - V8PaintCallback* paint, - const Vector<CSSPropertyID>&, - const Vector<AtomicString>& custom_invalidation_properties, - const Vector<CSSSyntaxDescriptor>& input_argument_types, - const PaintRenderingContext2DSettings*); - CSSPaintDefinition( ScriptState*, V8NoArgumentConstructor* constructor, @@ -59,9 +51,10 @@ // throws an error. // // The |container_size| is without subpixel snapping. - scoped_refptr<Image> Paint(const ImageResourceObserver&, - const FloatSize& container_size, - const CSSStyleValueVector*); + sk_sp<PaintRecord> Paint(const FloatSize& container_size, + float zoom, + StylePropertyMapReadOnly*, + const CSSStyleValueVector*); const Vector<CSSPropertyID>& NativeInvalidationProperties() const { return native_invalidation_properties_; }
diff --git a/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h b/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h index 762afc7..22d7629 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h +++ b/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d.h
@@ -26,15 +26,6 @@ USING_GARBAGE_COLLECTED_MIXIN(PaintRenderingContext2D); public: - static PaintRenderingContext2D* Create( - const IntSize& container_size, - const CanvasColorParams& color_params, - const PaintRenderingContext2DSettings* context_settings, - float zoom) { - return MakeGarbageCollected<PaintRenderingContext2D>( - container_size, color_params, context_settings, zoom); - } - PaintRenderingContext2D(const IntSize& container_size, const CanvasColorParams&, const PaintRenderingContext2DSettings*,
diff --git a/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc b/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc index 116fd82..a4ba95a 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_rendering_context_2d_test.cc
@@ -24,7 +24,7 @@ PaintRenderingContext2DSettings* context_settings = PaintRenderingContext2DSettings::Create(); context_settings->setAlpha(false); - ctx_ = PaintRenderingContext2D::Create( + ctx_ = MakeGarbageCollected<PaintRenderingContext2D>( IntSize(kWidth, kHeight), CanvasColorParams(), context_settings, kZoom); }
diff --git a/third_party/blink/renderer/modules/csspaint/paint_size.h b/third_party/blink/renderer/modules/csspaint/paint_size.h index 474dd2ce..7719929 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_size.h +++ b/third_party/blink/renderer/modules/csspaint/paint_size.h
@@ -16,10 +16,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static PaintSize* Create(FloatSize size) { - return MakeGarbageCollected<PaintSize>(size); - } - explicit PaintSize(FloatSize size) : size_(size) {} ~PaintSize() override = default;
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc index bc2d1f5..aba0caa 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
@@ -7,14 +7,17 @@ #include "base/atomic_sequence_num.h" #include "base/rand_util.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" +#include "third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h" #include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/dom/node_rare_data.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h" #include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h" #include "third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h" #include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h" -#include "third_party/blink/renderer/platform/graphics/image.h" +#include "third_party/blink/renderer/platform/graphics/paint_generated_image.h" namespace blink { @@ -36,17 +39,12 @@ PaintWorklet* supplement = Supplement<LocalDOMWindow>::From<PaintWorklet>(window); if (!supplement && window.GetFrame()) { - supplement = Create(window.GetFrame()); + supplement = MakeGarbageCollected<PaintWorklet>(window.GetFrame()); ProvideTo(window, supplement); } return supplement; } -// static -PaintWorklet* PaintWorklet::Create(LocalFrame* frame) { - return MakeGarbageCollected<PaintWorklet>(frame); -} - PaintWorklet::PaintWorklet(LocalFrame* frame) : Worklet(frame->GetDocument()), Supplement<LocalDOMWindow>(*frame->DomWindow()), @@ -121,7 +119,21 @@ CSSPaintDefinition* paint_definition = proxy->FindDefinition(name); if (!paint_definition) return nullptr; - return paint_definition->Paint(observer, container_size, data); + // TODO(crbug.com/946515): Break dependency on LayoutObject. + const LayoutObject& layout_object = + static_cast<const LayoutObject&>(observer); + float zoom = layout_object.StyleRef().EffectiveZoom(); + StylePropertyMapReadOnly* style_map = + MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>( + layout_object.GetDocument(), layout_object.StyleRef(), + layout_object.GetNode(), + paint_definition->NativeInvalidationProperties(), + paint_definition->CustomInvalidationProperties()); + sk_sp<PaintRecord> paint_record = + paint_definition->Paint(container_size, zoom, style_map, data); + if (!paint_record) + return nullptr; + return PaintGeneratedImage::Create(paint_record, container_size); } // static
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet.h b/third_party/blink/renderer/modules/csspaint/paint_worklet.h index c0d771f2..6fd1431 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet.h +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet.h
@@ -31,7 +31,6 @@ // At this moment, paint worklet allows at most two global scopes at any time. static const wtf_size_t kNumGlobalScopes; static PaintWorklet* From(LocalDOMWindow&); - static PaintWorklet* Create(LocalFrame*); explicit PaintWorklet(LocalFrame*); ~PaintWorklet() override;
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc index 1b908ce..ec592cc 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.cc
@@ -214,7 +214,7 @@ return; V8PaintCallback* paint = V8PaintCallback::Create(v8_paint); - CSSPaintDefinition* definition = CSSPaintDefinition::Create( + auto* definition = MakeGarbageCollected<CSSPaintDefinition>( ScriptController()->GetScriptState(), paint_ctor, paint, native_invalidation_properties, custom_invalidation_properties, input_argument_types, context_settings);
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc index f70f53e..17e16d9 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.cc
@@ -5,6 +5,7 @@ #include "third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h" #include "base/single_thread_task_runner.h" +#include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h" #include "third_party/blink/renderer/core/dom/document.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" @@ -85,6 +86,18 @@ state_ = RunState::kDisposed; } +sk_sp<PaintRecord> PaintWorkletProxyClient::Paint( + CompositorPaintWorkletInput* compositor_input) { + if (!global_scope_) + return sk_make_sp<PaintRecord>(); + PaintWorkletInput* input = static_cast<PaintWorkletInput*>(compositor_input); + CSSPaintDefinition* definition = + global_scope_->FindDefinition(input->NameCopy()); + + return definition->Paint(FloatSize(input->GetSize()), input->EffectiveZoom(), + nullptr, nullptr); +} + // static PaintWorkletProxyClient* PaintWorkletProxyClient::From(WorkerClients* clients) { return Supplement<WorkerClients>::From<PaintWorkletProxyClient>(clients);
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h index 639b999..94e604da 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client.h
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/modules/modules_export.h" #include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h" #include "third_party/blink/renderer/platform/graphics/paint_worklet_painter.h" +#include "third_party/blink/renderer/platform/graphics/platform_paint_worklet_layer_painter.h" namespace blink { @@ -44,6 +45,10 @@ void Trace(blink::Visitor*) override; + // PaintWorkletPainter implementation + int GetWorkletId() const override { return worklet_id_; } + sk_sp<PaintRecord> Paint(CompositorPaintWorkletInput*) override; + virtual void SetGlobalScope(WorkletGlobalScope*); void SetGlobalScopeForTesting(PaintWorkletGlobalScope*); void Dispose();
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client_test.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client_test.cc index 4c099d85d..be13087c 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client_test.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_proxy_client_test.cc
@@ -10,8 +10,12 @@ #include "base/synchronization/waitable_event.h" #include "base/test/test_simple_task_runner.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/bindings/core/v8/script_source_code.h" +#include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" +#include "third_party/blink/renderer/core/css/cssom/paint_worklet_input.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/core/workers/worker_reporting_proxy.h" +#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h" #include "third_party/blink/renderer/modules/worklet/worklet_thread_test_common.h" #include "third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h" @@ -40,6 +44,64 @@ waitable_event->Signal(); } + void SetGlobalScopeForTesting(WorkerThread* thread, + PaintWorkletProxyClient* proxy_client, + base::WaitableEvent* waitable_event) { + proxy_client->SetGlobalScopeForTesting( + static_cast<PaintWorkletGlobalScope*>( + To<WorkletGlobalScope>(thread->GlobalScope()))); + waitable_event->Signal(); + } + + using TestCallback = + void (PaintWorkletProxyClientTest::*)(WorkerThread*, + PaintWorkletProxyClient*, + base::WaitableEvent*); + void RunTestOnWorkletThread(TestCallback callback) { + std::unique_ptr<WorkerThread> worklet = + CreateThreadAndProvidePaintWorkletProxyClient( + &GetDocument(), reporting_proxy_.get(), proxy_client_); + + base::WaitableEvent waitable_event; + PostCrossThreadTask( + *worklet->GetTaskRunner(TaskType::kInternalTest), FROM_HERE, + CrossThreadBind( + callback, CrossThreadUnretained(this), + CrossThreadUnretained(worklet.get()), + CrossThreadPersistent<PaintWorkletProxyClient>(proxy_client_), + CrossThreadUnretained(&waitable_event))); + waitable_event.Wait(); + waitable_event.Reset(); + + worklet->Terminate(); + worklet->WaitForShutdownForTesting(); + } + + void RunPaintOnWorklet(WorkerThread* thread, + PaintWorkletProxyClient* proxy_client, + base::WaitableEvent* waitable_event) { + // The "registerPaint" script calls the real SetGlobalScope, so at this + // moment all we need is setting the |global_scope_| without any other + // things. + proxy_client->SetGlobalScopeForTesting( + static_cast<PaintWorkletGlobalScope*>( + To<WorkletGlobalScope>(thread->GlobalScope()))); + CrossThreadPersistent<PaintWorkletGlobalScope> global_scope = + proxy_client->global_scope_; + global_scope->ScriptController()->Evaluate( + ScriptSourceCode("registerPaint('foo', class { paint() { } });"), + SanitizeScriptErrors::kDoNotSanitize); + + PaintWorkletStylePropertyMap::CrossThreadData data; + scoped_refptr<PaintWorkletInput> input = + base::MakeRefCounted<PaintWorkletInput>("foo", FloatSize(100, 100), + 1.0f, 1, std::move(data)); + sk_sp<PaintRecord> record = proxy_client->Paint(input.get()); + EXPECT_NE(record, nullptr); + + waitable_event->Signal(); + } + scoped_refptr<PaintWorkletPaintDispatcher> dispatcher_; Persistent<PaintWorkletProxyClient> proxy_client_; std::unique_ptr<WorkerReportingProxy> reporting_proxy_; @@ -86,4 +148,9 @@ worklet_thread->WaitForShutdownForTesting(); } +TEST_F(PaintWorkletProxyClientTest, Paint) { + ScopedOffMainThreadCSSPaintForTest off_main_thread_css_paint(true); + RunTestOnWorkletThread(&PaintWorkletProxyClientTest::RunPaintOnWorklet); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc index 3d6790b..f96b0ac1 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_test.cc
@@ -11,12 +11,13 @@ #include "third_party/blink/renderer/bindings/core/v8/worker_or_worklet_script_controller.h" #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/local_frame.h" +#include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_view.h" #include "third_party/blink/renderer/core/testing/page_test_base.h" #include "third_party/blink/renderer/modules/csspaint/css_paint_definition.h" #include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h" #include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.h" -#include "third_party/blink/renderer/platform/graphics/image.h" +#include "third_party/blink/renderer/platform/graphics/paint_generated_image.h" namespace blink { class TestPaintWorklet : public PaintWorklet { @@ -122,8 +123,17 @@ ASSERT_TRUE(observer); const FloatSize container_size(100, 100); - scoped_refptr<Image> image = - definition->Paint(*observer, container_size, nullptr); + const LayoutObject& layout_object = + static_cast<const LayoutObject&>(*observer); + float zoom = layout_object.StyleRef().EffectiveZoom(); + StylePropertyMapReadOnly* style_map = + MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>( + layout_object.GetDocument(), layout_object.StyleRef(), + layout_object.GetNode(), definition->NativeInvalidationProperties(), + definition->CustomInvalidationProperties()); + scoped_refptr<Image> image = PaintGeneratedImage::Create( + definition->Paint(container_size, zoom, style_map, nullptr), + container_size); EXPECT_NE(image, nullptr); }
diff --git a/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc b/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc index 129e1f1..387f29e 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc
@@ -400,7 +400,8 @@ initializer->setBubbles(false); initializer->setCancelable(false); - return MediaEncryptedEvent::Create(event_type_names::kEncrypted, initializer); + return MakeGarbageCollected<MediaEncryptedEvent>(event_type_names::kEncrypted, + initializer); } void HTMLMediaElementEncryptedMedia::Encrypted(
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc index 2efd732..840e1b4 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
@@ -337,14 +337,6 @@ Member<MediaKeySession> session_; }; -MediaKeySession* MediaKeySession::Create( - ScriptState* script_state, - MediaKeys* media_keys, - WebEncryptedMediaSessionType session_type) { - return MakeGarbageCollected<MediaKeySession>(script_state, media_keys, - session_type); -} - MediaKeySession::MediaKeySession(ScriptState* script_state, MediaKeys* media_keys, WebEncryptedMediaSessionType session_type)
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h index 20ea68a..5991da690 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h +++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.h
@@ -71,10 +71,6 @@ USING_PRE_FINALIZER(MediaKeySession, Dispose); public: - static MediaKeySession* Create(ScriptState*, - MediaKeys*, - WebEncryptedMediaSessionType); - MediaKeySession(ScriptState*, MediaKeys*, WebEncryptedMediaSessionType); ~MediaKeySession() override;
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc index 8c930dcd..bd6825d 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_status_map.cc
@@ -20,10 +20,6 @@ class MediaKeyStatusMap::MapEntry final : public GarbageCollectedFinalized<MediaKeyStatusMap::MapEntry> { public: - static MapEntry* Create(WebData key_id, const String& status) { - return MakeGarbageCollected<MapEntry>(key_id, status); - } - MapEntry(WebData key_id, const String& status) : key_id_(DOMArrayBuffer::Create(scoped_refptr<SharedBuffer>(key_id))), status_(status) {} @@ -108,7 +104,7 @@ void MediaKeyStatusMap::AddEntry(WebData key_id, const String& status) { // Insert new entry into sorted list. - MapEntry* entry = MapEntry::Create(key_id, status); + auto* entry = MakeGarbageCollected<MapEntry>(key_id, status); uint32_t index = 0; while (index < entries_.size() && MapEntry::CompareLessThan(entries_[index], entry))
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc index f412eb8..568651b5 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.cc
@@ -55,7 +55,7 @@ return; // 2.9. Let media keys be a new MediaKeys object. - MediaKeys* media_keys = MediaKeys::Create( + auto* media_keys = MakeGarbageCollected<MediaKeys>( GetExecutionContext(), supported_session_types_, base::WrapUnique(cdm)); // 2.10. Resolve promise with media keys.
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc b/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc index 7550712a..3c7b9af 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
@@ -200,14 +200,6 @@ Member<MediaKeys> media_keys_; }; -MediaKeys* MediaKeys::Create( - ExecutionContext* context, - const WebVector<WebEncryptedMediaSessionType>& supported_session_types, - std::unique_ptr<WebContentDecryptionModule> cdm) { - return MakeGarbageCollected<MediaKeys>(context, supported_session_types, - std::move(cdm)); -} - MediaKeys::MediaKeys( ExecutionContext* context, const WebVector<WebEncryptedMediaSessionType>& supported_session_types, @@ -273,7 +265,8 @@ // follows: // (Initialization is performed in the constructor.) // 4. Return session. - return MediaKeySession::Create(script_state, this, session_type); + return MakeGarbageCollected<MediaKeySession>(script_state, this, + session_type); } ScriptPromise MediaKeys::setServerCertificate(
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_keys.h b/third_party/blink/renderer/modules/encryptedmedia/media_keys.h index 7549e59d..542e066 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/media_keys.h +++ b/third_party/blink/renderer/modules/encryptedmedia/media_keys.h
@@ -59,11 +59,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static MediaKeys* Create( - ExecutionContext*, - const WebVector<WebEncryptedMediaSessionType>& supported_session_types, - std::unique_ptr<WebContentDecryptionModule>); - MediaKeys( ExecutionContext*, const WebVector<WebEncryptedMediaSessionType>& supported_session_types,
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc index 5b4ce16..2fcbd13c 100644 --- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc +++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -181,16 +181,9 @@ pause_after_download_state_ = kDoPauseAfterDownload; devtools_worker_token_ = data.devtools_worker_token; - // S13nServiceWorker: |loader_factory| is null since all loads for new scripts - // go through (internal WebServiceWorkerNetworkProvider class in - // service_worker_context_client.cc)::script_loader_factory() rather than the - // shadow page's loader. This is different to shared workers, which use - // script_loader_factory() for the main script only, and the shadow page - // loader for importScripts(). - // - // Non-S13nServiceWorker: |loader_factory| is null since the main script load - // goes through the shadow page loader which uses the default loader that goes - // to ResourceDispatcherHost. + // |loader_factory| is null since all loads for new scripts go through + // ServiceWorkerNetworkProviderForServiceWorker::script_loader_factory() + // rather than the shadow page's loader. shadow_page_ = std::make_unique<WorkerShadowPage>( this, nullptr /* loader_factory */, std::move(worker_start_data_.privacy_preferences));
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad.cc b/third_party/blink/renderer/modules/gamepad/gamepad.cc index 7e17e6b..a351250 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad.cc
@@ -41,11 +41,6 @@ Gamepad::~Gamepad() = default; -// static -Gamepad* Gamepad::Create(ExecutionContext* context) { - return MakeGarbageCollected<Gamepad>(context); -} - const Gamepad::DoubleVector& Gamepad::axes() { is_axis_data_dirty_ = false; return axes_; @@ -82,7 +77,7 @@ if (buttons_.size() != count) { buttons_.resize(count); for (unsigned i = 0; i < count; ++i) - buttons_[i] = GamepadButton::Create(); + buttons_[i] = MakeGarbageCollected<GamepadButton>(); } for (unsigned i = 0; i < count; ++i) buttons_[i]->UpdateValuesFrom(data[i]); @@ -103,7 +98,7 @@ } if (!pose_) - pose_ = GamepadPose::Create(); + pose_ = MakeGarbageCollected<GamepadPose>(); pose_->SetPose(pose); }
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad.h b/third_party/blink/renderer/modules/gamepad/gamepad.h index a0ece959..5bf19a8 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad.h
@@ -45,8 +45,6 @@ USING_GARBAGE_COLLECTED_MIXIN(Gamepad); public: - static Gamepad* Create(ExecutionContext* context); - explicit Gamepad(ExecutionContext*); ~Gamepad() override;
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_button.cc b/third_party/blink/renderer/modules/gamepad/gamepad_button.cc index d60d596c..4d9a2b5 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_button.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad_button.cc
@@ -6,10 +6,6 @@ namespace blink { -GamepadButton* GamepadButton::Create() { - return MakeGarbageCollected<GamepadButton>(); -} - GamepadButton::GamepadButton() : value_(0.), pressed_(false), touched_(false) {} bool GamepadButton::IsEqual(const device::GamepadButton& device_button) const {
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_button.h b/third_party/blink/renderer/modules/gamepad/gamepad_button.h index c2838e0..35099bcb 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_button.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad_button.h
@@ -16,8 +16,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static GamepadButton* Create(); - GamepadButton(); double value() const { return value_; }
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_comparisons_test.cc b/third_party/blink/renderer/modules/gamepad/gamepad_comparisons_test.cc index de383a9..96877dea 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_comparisons_test.cc +++ b/third_party/blink/renderer/modules/gamepad/gamepad_comparisons_test.cc
@@ -44,14 +44,16 @@ InitGamepadVector(p.linear_acceleration); } - GamepadList* CreateEmptyGamepadList() { return GamepadList::Create(); } + GamepadList* CreateEmptyGamepadList() { + return MakeGarbageCollected<GamepadList>(); + } GamepadList* CreateGamepadListWithNeutralGamepad() { double axes[1] = {0.0}; device::GamepadButton buttons[1] = {{false, false, 0.0}}; device::GamepadPose null_pose; - auto* list = GamepadList::Create(); - auto* gamepad = Gamepad::Create(nullptr); + auto* list = MakeGarbageCollected<GamepadList>(); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); gamepad->SetId("gamepad"); gamepad->SetIndex(0); gamepad->SetAxes(1, axes); @@ -66,8 +68,8 @@ double axes[1] = {0.95}; device::GamepadButton buttons[1] = {{false, false, 0.0}}; - auto* list = GamepadList::Create(); - auto* gamepad = Gamepad::Create(nullptr); + auto* list = MakeGarbageCollected<GamepadList>(); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); gamepad->SetId("gamepad"); gamepad->SetIndex(0); gamepad->SetAxes(1, axes); @@ -81,8 +83,8 @@ double axes[1] = {0.0}; device::GamepadButton buttons[1] = {{true, true, 1.0}}; - auto* list = GamepadList::Create(); - auto* gamepad = Gamepad::Create(nullptr); + auto* list = MakeGarbageCollected<GamepadList>(); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); gamepad->SetId("gamepad"); gamepad->SetIndex(0); gamepad->SetAxes(1, axes); @@ -101,8 +103,8 @@ device::GamepadButton::kDefaultButtonPressedThreshold - 0.01, }}; - auto* list = GamepadList::Create(); - auto* gamepad = Gamepad::Create(nullptr); + auto* list = MakeGarbageCollected<GamepadList>(); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); gamepad->SetId("gamepad"); gamepad->SetIndex(0); gamepad->SetAxes(1, axes); @@ -121,8 +123,8 @@ device::GamepadButton::kDefaultButtonPressedThreshold + 0.01, }}; - auto* list = GamepadList::Create(); - auto* gamepad = Gamepad::Create(nullptr); + auto* list = MakeGarbageCollected<GamepadList>(); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); gamepad->SetId("gamepad"); gamepad->SetIndex(0); gamepad->SetAxes(1, axes); @@ -137,8 +139,8 @@ device::GamepadButton buttons[1] = {{false, false, 0.0}}; device::GamepadPose pose; InitGamepadPose(pose); - auto* list = GamepadList::Create(); - auto* gamepad = Gamepad::Create(nullptr); + auto* list = MakeGarbageCollected<GamepadList>(); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); gamepad->SetId("gamepad"); gamepad->SetIndex(0); gamepad->SetAxes(1, axes); @@ -156,8 +158,8 @@ InitGamepadPose(pose); // Modify the linear velocity. pose.linear_velocity.x = 100.f; - auto* list = GamepadList::Create(); - auto* gamepad = Gamepad::Create(nullptr); + auto* list = MakeGarbageCollected<GamepadList>(); + auto* gamepad = MakeGarbageCollected<Gamepad>(nullptr); gamepad->SetId("gamepad"); gamepad->SetIndex(0); gamepad->SetAxes(1, axes);
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_list.h b/third_party/blink/renderer/modules/gamepad/gamepad_list.h index 9bf5256..b4a203c7 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_list.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad_list.h
@@ -38,8 +38,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static GamepadList* Create() { return MakeGarbageCollected<GamepadList>(); } - GamepadList(); void Set(unsigned index, Gamepad*);
diff --git a/third_party/blink/renderer/modules/gamepad/gamepad_pose.h b/third_party/blink/renderer/modules/gamepad/gamepad_pose.h index 4bf4f6c4..0b4b2ef22 100644 --- a/third_party/blink/renderer/modules/gamepad/gamepad_pose.h +++ b/third_party/blink/renderer/modules/gamepad/gamepad_pose.h
@@ -17,8 +17,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static GamepadPose* Create() { return MakeGarbageCollected<GamepadPose>(); } - GamepadPose(); bool hasOrientation() const { return has_orientation_; }
diff --git a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc index c7f1a9b..7e32a770 100644 --- a/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc +++ b/third_party/blink/renderer/modules/gamepad/navigator_gamepad.cc
@@ -128,7 +128,7 @@ } else if (web_gamepad.connected) { Gamepad* gamepad = into->item(i); if (!gamepad) - gamepad = Gamepad::Create(context); + gamepad = MakeGarbageCollected<Gamepad>(context); SampleGamepad(i, *gamepad, web_gamepad, navigation_start, gamepads_start); into->Set(i, gamepad); } else { @@ -183,7 +183,7 @@ // Ensure |gamepads_| is not null. if (!gamepads_) - gamepads_ = GamepadList::Create(); + gamepads_ = MakeGarbageCollected<GamepadList>(); // Allow gamepad button presses to qualify as user activations if the page is // visible. @@ -331,7 +331,7 @@ if (GetPage()->IsPageVisible()) { // Allocate a buffer to hold the new gamepad state, if needed. if (!gamepads_back_) - gamepads_back_ = GamepadList::Create(); + gamepads_back_ = MakeGarbageCollected<GamepadList>(); bool include_xr_gamepads = ShouldIncludeXrGamepads(GetFrame());
diff --git a/third_party/blink/renderer/modules/geolocation/coordinates.h b/third_party/blink/renderer/modules/geolocation/coordinates.h index 6a5281a..6296150 100644 --- a/third_party/blink/renderer/modules/geolocation/coordinates.h +++ b/third_party/blink/renderer/modules/geolocation/coordinates.h
@@ -36,23 +36,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static Coordinates* Create(double latitude, - double longitude, - bool provides_altitude, - double altitude, - double accuracy, - bool provides_altitude_accuracy, - double altitude_accuracy, - bool provides_heading, - double heading, - bool provides_speed, - double speed) { - return MakeGarbageCollected<Coordinates>( - latitude, longitude, provides_altitude, altitude, accuracy, - provides_altitude_accuracy, altitude_accuracy, provides_heading, - heading, provides_speed, speed); - } - Coordinates(double latitude, double longitude, bool provides_altitude,
diff --git a/third_party/blink/renderer/modules/geolocation/geo_notifier.cc b/third_party/blink/renderer/modules/geolocation/geo_notifier.cc index 907b2bef..a7f2f6eb 100644 --- a/third_party/blink/renderer/modules/geolocation/geo_notifier.cc +++ b/third_party/blink/renderer/modules/geolocation/geo_notifier.cc
@@ -22,7 +22,7 @@ success_callback_(success_callback), error_callback_(error_callback), options_(options), - timer_(Timer::Create( + timer_(MakeGarbageCollected<Timer>( geolocation->GetDocument()->GetTaskRunner(TaskType::kMiscPlatformAPI), this, &GeoNotifier::TimerFired)), @@ -132,8 +132,8 @@ if (error_callback_) { error_callback_->InvokeAndReportException( - nullptr, - PositionError::Create(PositionError::kTimeout, "Timeout expired")); + nullptr, MakeGarbageCollected<PositionError>(PositionError::kTimeout, + "Timeout expired")); } DEFINE_STATIC_LOCAL(CustomCountHistogram, timeout_expired_histogram,
diff --git a/third_party/blink/renderer/modules/geolocation/geo_notifier.h b/third_party/blink/renderer/modules/geolocation/geo_notifier.h index beee26fe..a6a24e5 100644 --- a/third_party/blink/renderer/modules/geolocation/geo_notifier.h +++ b/third_party/blink/renderer/modules/geolocation/geo_notifier.h
@@ -22,14 +22,6 @@ class GeoNotifier final : public GarbageCollectedFinalized<GeoNotifier>, public NameClient { public: - static GeoNotifier* Create(Geolocation* geolocation, - V8PositionCallback* position_callback, - V8PositionErrorCallback* position_error_callback, - const PositionOptions* options) { - return MakeGarbageCollected<GeoNotifier>(geolocation, position_callback, - position_error_callback, options); - } - GeoNotifier(Geolocation*, V8PositionCallback*, V8PositionErrorCallback*, @@ -64,14 +56,6 @@ // timer should be stopped beforehand. class Timer final : public GarbageCollectedFinalized<Timer> { public: - static Timer* Create( - scoped_refptr<base::SingleThreadTaskRunner> web_task_runner, - GeoNotifier* notifier, - void (GeoNotifier::*member_func)(TimerBase*)) { - return MakeGarbageCollected<Timer>(web_task_runner, notifier, - member_func); - } - explicit Timer(scoped_refptr<base::SingleThreadTaskRunner> web_task_runner, GeoNotifier* notifier, void (GeoNotifier::*member_func)(TimerBase*))
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation.cc b/third_party/blink/renderer/modules/geolocation/geolocation.cc index 5d6de494..c37d3cb1 100644 --- a/third_party/blink/renderer/modules/geolocation/geolocation.cc +++ b/third_party/blink/renderer/modules/geolocation/geolocation.cc
@@ -56,15 +56,16 @@ Geoposition* CreateGeoposition( const device::mojom::blink::Geoposition& position) { - Coordinates* coordinates = Coordinates::Create( + auto* coordinates = MakeGarbageCollected<Coordinates>( position.latitude, position.longitude, // Lowest point on land is at approximately -400 meters. position.altitude > -10000., position.altitude, position.accuracy, position.altitude_accuracy >= 0., position.altitude_accuracy, position.heading >= 0. && position.heading <= 360., position.heading, position.speed >= 0., position.speed); - return Geoposition::Create(coordinates, ConvertSecondsToDOMTimeStamp( - position.timestamp.ToDoubleT())); + return MakeGarbageCollected<Geoposition>( + coordinates, + ConvertSecondsToDOMTimeStamp(position.timestamp.ToDoubleT())); } PositionError* CreatePositionError( @@ -83,7 +84,7 @@ NOTREACHED(); break; } - return PositionError::Create(error_code, error); + return MakeGarbageCollected<PositionError>(error_code, error); } static void ReportGeolocationViolation(Document* doc) { @@ -185,8 +186,8 @@ probe::BreakableLocation(GetDocument(), "Geolocation.getCurrentPosition"); - GeoNotifier* notifier = - GeoNotifier::Create(this, success_callback, error_callback, options); + auto* notifier = MakeGarbageCollected<GeoNotifier>(this, success_callback, + error_callback, options); one_shots_.insert(notifier); @@ -201,8 +202,8 @@ probe::BreakableLocation(GetDocument(), "Geolocation.watchPosition"); - GeoNotifier* notifier = - GeoNotifier::Create(this, success_callback, error_callback, options); + auto* notifier = MakeGarbageCollected<GeoNotifier>(this, success_callback, + error_callback, options); int watch_id; // Keep asking for the next id until we're given one that we don't already @@ -221,8 +222,8 @@ String error_message; if (!GetFrame()->GetSettings()->GetAllowGeolocationOnInsecureOrigins() && !GetExecutionContext()->IsSecureContext(error_message)) { - notifier->SetFatalError( - PositionError::Create(PositionError::kPermissionDenied, error_message)); + notifier->SetFatalError(MakeGarbageCollected<PositionError>( + PositionError::kPermissionDenied, error_message)); return; } @@ -231,7 +232,7 @@ ReportOptions::kReportOnFailure, kFeaturePolicyConsoleWarning)) { UseCounter::Count(GetDocument(), WebFeature::kGeolocationDisabledByFeaturePolicy); - notifier->SetFatalError(PositionError::Create( + notifier->SetFatalError(MakeGarbageCollected<PositionError>( PositionError::kPermissionDenied, kFeaturePolicyErrorMessage)); return; } @@ -509,8 +510,8 @@ StopUpdating(); // The only reason that we would fail to get a ConnectionError is if we lack // sufficient permission. - PositionError* error = PositionError::Create(PositionError::kPermissionDenied, - kPermissionDeniedErrorMessage); + auto* error = MakeGarbageCollected<PositionError>( + PositionError::kPermissionDenied, kPermissionDeniedErrorMessage); error->SetIsFatal(true); HandleError(error); }
diff --git a/third_party/blink/renderer/modules/geolocation/geolocation_error.h b/third_party/blink/renderer/modules/geolocation/geolocation_error.h index da1cfdf..d27b7ab 100644 --- a/third_party/blink/renderer/modules/geolocation/geolocation_error.h +++ b/third_party/blink/renderer/modules/geolocation/geolocation_error.h
@@ -34,10 +34,6 @@ public: enum ErrorCode { kPermissionDenied, kPositionUnavailable }; - static GeolocationError* Create(ErrorCode code, const String& message) { - return MakeGarbageCollected<GeolocationError>(code, message); - } - GeolocationError(ErrorCode code, const String& message) : code_(code), message_(message) {}
diff --git a/third_party/blink/renderer/modules/geolocation/geoposition.h b/third_party/blink/renderer/modules/geolocation/geoposition.h index 02b867b..9b39b62 100644 --- a/third_party/blink/renderer/modules/geolocation/geoposition.h +++ b/third_party/blink/renderer/modules/geolocation/geoposition.h
@@ -39,10 +39,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static Geoposition* Create(Coordinates* coordinates, DOMTimeStamp timestamp) { - return MakeGarbageCollected<Geoposition>(coordinates, timestamp); - } - Geoposition(Coordinates* coordinates, DOMTimeStamp timestamp) : coordinates_(coordinates), timestamp_(timestamp) { DCHECK(coordinates_);
diff --git a/third_party/blink/renderer/modules/geolocation/position_error.h b/third_party/blink/renderer/modules/geolocation/position_error.h index ae30a3a..5aea482 100644 --- a/third_party/blink/renderer/modules/geolocation/position_error.h +++ b/third_party/blink/renderer/modules/geolocation/position_error.h
@@ -42,10 +42,6 @@ kTimeout = 3 }; - static PositionError* Create(ErrorCode code, const String& message) { - return MakeGarbageCollected<PositionError>(code, message); - } - PositionError(ErrorCode code, const String& message) : code_(code), message_(message), is_fatal_(false) {}
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc index 47b3bd2..480a24e 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
@@ -1542,7 +1542,7 @@ crypto_algorithm, &error)) { // Reject generateCertificate with the same error as was produced by // WebCrypto. |result| is garbage collected, no need to delete. - CryptoResultImpl* result = CryptoResultImpl::Create(script_state); + auto* result = MakeGarbageCollected<CryptoResultImpl>(script_state); ScriptPromise promise = result->Promise(); result->CompleteWithError(error.error_type, error.error_details); return promise;
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image.cc b/third_party/blink/renderer/platform/graphics/bitmap_image.cc index a410eae7..f8a9f63 100644 --- a/third_party/blink/renderer/platform/graphics/bitmap_image.cc +++ b/third_party/blink/renderer/platform/graphics/bitmap_image.cc
@@ -34,6 +34,7 @@ #include "base/metrics/histogram_macros.h" #include "third_party/blink/renderer/platform/geometry/float_rect.h" #include "third_party/blink/renderer/platform/graphics/bitmap_image_metrics.h" +#include "third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h" #include "third_party/blink/renderer/platform/graphics/deferred_image_decoder.h" #include "third_party/blink/renderer/platform/graphics/image_observer.h" #include "third_party/blink/renderer/platform/graphics/paint/paint_canvas.h" @@ -431,4 +432,11 @@ ResetAnimation(); } +DarkModeClassification BitmapImage::ClassifyImageForDarkMode( + const FloatRect& src_rect) { + DarkModeImageClassifier dark_mode_image_classifier; + return dark_mode_image_classifier.ClassifyBitmapImageForDarkMode(*this, + src_rect); +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/bitmap_image.h b/third_party/blink/renderer/platform/graphics/bitmap_image.h index eb3d0f6..b99d1bb3 100644 --- a/third_party/blink/renderer/platform/graphics/bitmap_image.h +++ b/third_party/blink/renderer/platform/graphics/bitmap_image.h
@@ -144,6 +144,9 @@ int RepetitionCount(); + DarkModeClassification ClassifyImageForDarkMode( + const FloatRect& src_rect) override; + std::unique_ptr<DeferredImageDecoder> decoder_; mutable IntSize size_; // The size to use for the overall image (will just // be the size of the first image).
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc index ae1ed8a3..51cef1c 100644 --- a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc +++ b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.cc
@@ -39,43 +39,23 @@ DarkModeImageClassifier::DarkModeImageClassifier() : pixels_to_sample_(kPixelsToSample) {} -bool DarkModeImageClassifier::ShouldApplyDarkModeFilterToImage( +DarkModeClassification DarkModeImageClassifier::ClassifyBitmapImageForDarkMode( Image& image, const FloatRect& src_rect) { - DarkModeClassification result = image.GetDarkModeClassification(src_rect); - // Check if the image has already been classified. - if (result != DarkModeClassification::kNotClassified) - return result == DarkModeClassification::kApplyDarkModeFilter; - std::vector<SkColor> sampled_pixels; if (src_rect.Width() < kMinImageSizeForClassification1D || - src_rect.Height() < kMinImageSizeForClassification1D) { - result = DarkModeClassification::kApplyDarkModeFilter; - } else { - std::vector<float> features; - if (!ComputeImageFeatures(image, src_rect, &features, &sampled_pixels)) { - // TODO(v.paturi): Implement an SVG classifier which can decide if a - // filter should be applied based on the image's content and it's - // visibility on a dark background. - // Force this function to return true for any SVG image so that the - // filter will be set in the PaintFlags in GraphicsContext::DrawImage. - if (image.IsSVGImage() || image.IsSVGImageForContainer()) { - result = DarkModeClassification::kApplyDarkModeFilter; - } else { - result = DarkModeClassification::kDoNotApplyDarkModeFilter; - } - } else { - result = ClassifyImage(features); - } + src_rect.Height() < kMinImageSizeForClassification1D) + return DarkModeClassification::kApplyDarkModeFilter; + + std::vector<float> features; + if (!ComputeImageFeatures(image, src_rect, &features, &sampled_pixels)) { + // TODO(https://crbug.com/945434): Do not cache the classification when + // the correct resource is not loaded + image.SetShouldCacheDarkModeClassification(sampled_pixels.size() != 0); + return DarkModeClassification::kDoNotApplyDarkModeFilter; } - // Store the classification result in the image object using src_rect's - // location as a key for the map. - // TODO(https://crbug.com/945434): Do not cache the classification when - // the correct resource is not loaded - if (sampled_pixels.size() != 0) - image.AddDarkModeClassification(src_rect, result); - return result == DarkModeClassification::kApplyDarkModeFilter; + return ClassifyImage(features); } // This function computes a single feature vector based on a sample set of image @@ -108,7 +88,8 @@ bool DarkModeImageClassifier::GetBitmap(Image& image, const FloatRect& src_rect, SkBitmap* bitmap) { - if (!image.IsBitmapImage() || !src_rect.Width() || !src_rect.Height()) + DCHECK(image.IsBitmapImage()); + if (!src_rect.Width() || !src_rect.Height()) return false; SkScalar sx = SkFloatToScalar(src_rect.X());
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h index 6712493..5f2bbb4 100644 --- a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h +++ b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h
@@ -23,13 +23,9 @@ DarkModeImageClassifier(); ~DarkModeImageClassifier() = default; - // Decides if a dark mode filter should be applied to the image or not. - // |src_rect| is needed in case of image sprites for the location and - // size of the smaller images that the sprite holds. - // For images that come from sprites the |src_rect.X| and |src_rect.Y| - // can be non-zero. But for normal images they are both zero. - bool ShouldApplyDarkModeFilterToImage(Image& image, - const FloatRect& src_rect); + DarkModeClassification ClassifyBitmapImageForDarkMode( + Image& image, + const FloatRect& src_rect); bool ComputeImageFeaturesForTesting(Image& image, std::vector<float>* features) {
diff --git a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier_test.cc b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier_test.cc index bdd0ab8..66c0932 100644 --- a/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier_test.cc +++ b/third_party/blink/renderer/platform/graphics/dark_mode_image_classifier_test.cc
@@ -26,6 +26,16 @@ int GetMapSize() { return dark_mode_classifications_.size(); } + DarkModeClassification GetClassification(const FloatRect& src_rect) { + return GetDarkModeClassification(src_rect); + } + + void AddClassification( + const FloatRect& src_rect, + const DarkModeClassification dark_mode_classification) { + AddDarkModeClassification(src_rect, dark_mode_classification); + } + // Pure virtual functions that have to be overridden. bool CurrentFrameKnownToBeOpaque() override { return false; } IntSize Size() const override { return IntSize(0, 0); } @@ -49,8 +59,9 @@ SCOPED_TRACE(file_name); scoped_refptr<BitmapImage> image = LoadImage(file_name); classifier_.ComputeImageFeaturesForTesting(*image.get(), features); - return classifier_.ShouldApplyDarkModeFilterToImage( + DarkModeClassification result = classifier_.ClassifyBitmapImageForDarkMode( *image.get(), FloatRect(0, 0, image->width(), image->height())); + return result == DarkModeClassification::kApplyDarkModeFilter; } void AssertFeaturesEqual(const std::vector<float>& features, @@ -145,25 +156,25 @@ FloatRect src_rect2(5, 20, 100, 100); FloatRect src_rect3(6, -9, 50, 50); - EXPECT_EQ(image->GetDarkModeClassification(src_rect1), + EXPECT_EQ(image->GetClassification(src_rect1), DarkModeClassification::kNotClassified); - image->AddDarkModeClassification( - src_rect1, DarkModeClassification::kApplyDarkModeFilter); - EXPECT_EQ(image->GetDarkModeClassification(src_rect1), + image->AddClassification(src_rect1, + DarkModeClassification::kApplyDarkModeFilter); + EXPECT_EQ(image->GetClassification(src_rect1), DarkModeClassification::kApplyDarkModeFilter); - EXPECT_EQ(image->GetDarkModeClassification(src_rect2), + EXPECT_EQ(image->GetClassification(src_rect2), DarkModeClassification::kNotClassified); - image->AddDarkModeClassification( - src_rect2, DarkModeClassification::kDoNotApplyDarkModeFilter); - EXPECT_EQ(image->GetDarkModeClassification(src_rect2), + image->AddClassification(src_rect2, + DarkModeClassification::kDoNotApplyDarkModeFilter); + EXPECT_EQ(image->GetClassification(src_rect2), DarkModeClassification::kDoNotApplyDarkModeFilter); - EXPECT_EQ(image->GetDarkModeClassification(src_rect3), + EXPECT_EQ(image->GetClassification(src_rect3), DarkModeClassification::kNotClassified); - image->AddDarkModeClassification( - src_rect3, DarkModeClassification::kApplyDarkModeFilter); - EXPECT_EQ(image->GetDarkModeClassification(src_rect3), + image->AddClassification(src_rect3, + DarkModeClassification::kApplyDarkModeFilter); + EXPECT_EQ(image->GetClassification(src_rect3), DarkModeClassification::kApplyDarkModeFilter); EXPECT_EQ(image->GetMapSize(), 3);
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.cc b/third_party/blink/renderer/platform/graphics/graphics_context.cc index e11034e..2adf55d 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.cc +++ b/third_party/blink/renderer/platform/graphics/graphics_context.cc
@@ -1422,8 +1422,7 @@ switch (dark_mode_settings_.image_policy) { case DarkModeImagePolicy::kFilterSmart: - return dark_mode_image_classifier_.ShouldApplyDarkModeFilterToImage( - image, src_rect); + return image.ShouldApplyDarkModeFilter(src_rect); case DarkModeImagePolicy::kFilterAll: return true; default:
diff --git a/third_party/blink/renderer/platform/graphics/graphics_context.h b/third_party/blink/renderer/platform/graphics/graphics_context.h index 8c28c928..bc9f657 100644 --- a/third_party/blink/renderer/platform/graphics/graphics_context.h +++ b/third_party/blink/renderer/platform/graphics/graphics_context.h
@@ -33,7 +33,6 @@ #include "base/macros.h" #include "cc/paint/node_holder.h" #include "third_party/blink/renderer/platform/fonts/font.h" -#include "third_party/blink/renderer/platform/graphics/dark_mode_image_classifier.h" #include "third_party/blink/renderer/platform/graphics/dark_mode_settings.h" #include "third_party/blink/renderer/platform/graphics/dash_array.h" #include "third_party/blink/renderer/platform/graphics/draw_looper_builder.h" @@ -504,7 +503,6 @@ DarkModeSettings dark_mode_settings_; sk_sp<SkColorFilter> dark_mode_filter_; - DarkModeImageClassifier dark_mode_image_classifier_; unsigned printing_ : 1; unsigned in_drawing_recorder_ : 1;
diff --git a/third_party/blink/renderer/platform/graphics/image.cc b/third_party/blink/renderer/platform/graphics/image.cc index c7925e9..0390423 100644 --- a/third_party/blink/renderer/platform/graphics/image.cc +++ b/third_party/blink/renderer/platform/graphics/image.cc
@@ -393,4 +393,20 @@ dark_mode_classifications_[key] = dark_mode_classification; } +bool Image::ShouldApplyDarkModeFilter(const FloatRect& src_rect) { + // Check if the image has already been classified. + DarkModeClassification result = GetDarkModeClassification(src_rect); + if (result != DarkModeClassification::kNotClassified) + return result == DarkModeClassification::kApplyDarkModeFilter; + + result = ClassifyImageForDarkMode(src_rect); + + // Store the classification result using src_rect's location + // as a key for the map. + if (ShouldCacheDarkModeClassification()) + AddDarkModeClassification(src_rect, result); + + return result == DarkModeClassification::kApplyDarkModeFilter; +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/image.h b/third_party/blink/renderer/platform/graphics/image.h index c6738b7e..75394d5 100644 --- a/third_party/blink/renderer/platform/graphics/image.h +++ b/third_party/blink/renderer/platform/graphics/image.h
@@ -88,11 +88,6 @@ InterpolationQuality = kInterpolationNone); virtual bool IsSVGImage() const { return false; } - // TODO(v.paturi): Remove this function once - // |ShouldApplyDarkModeFilterToImage| is refactored. - // It's suggested that this function not be used anywhere - // else in the mean time. - virtual bool IsSVGImageForContainer() const { return false; } virtual bool IsBitmapImage() const { return false; } virtual bool IsStaticBitmapImage() const { return false; } virtual bool IsPlaceholderImage() const { return false; } @@ -241,13 +236,20 @@ return nullptr; } - DarkModeClassification GetDarkModeClassification(const FloatRect& src_rect); + void SetShouldCacheDarkModeClassification(bool should_cache_result) { + should_cache_dark_mode_classification_ = should_cache_result; + } - // Dark mode classification result is cached to be consistent and have - // higher performance for future paints. - void AddDarkModeClassification( - const FloatRect& src_rect, - const DarkModeClassification dark_mode_classification); + bool ShouldCacheDarkModeClassification() { + return should_cache_dark_mode_classification_; + } + + // Decides if a dark mode filter should be applied to the image or not. + // |src_rect| is needed in case of image sprites for the location and + // size of the smaller images that the sprite holds. + // For images that come from sprites the |src_rect.X| and |src_rect.Y| + // can be non-zero. But for other images they are both zero. + bool ShouldApplyDarkModeFilter(const FloatRect& src_rect); PaintImage::Id paint_image_id() const { return stable_image_id_; } @@ -272,11 +274,24 @@ // Whether or not size is available yet. virtual bool IsSizeAvailable() { return true; } + DarkModeClassification GetDarkModeClassification(const FloatRect& src_rect); + + // Dark mode classification result is cached to be consistent and have + // higher performance for future paints. + void AddDarkModeClassification( + const FloatRect& src_rect, + const DarkModeClassification dark_mode_classification); + typedef std::pair<float, float> ClassificationKey; std::map<ClassificationKey, DarkModeClassification> dark_mode_classifications_; private: + virtual DarkModeClassification ClassifyImageForDarkMode( + const FloatRect& src_rect) { + return DarkModeClassification::kDoNotApplyDarkModeFilter; + } + bool image_observer_disabled_; scoped_refptr<SharedBuffer> encoded_image_data_; // TODO(Oilpan): consider having Image on the Oilpan heap and @@ -289,6 +304,7 @@ WeakPersistent<ImageObserver> image_observer_; PaintImage::Id stable_image_id_; const bool is_multipart_; + bool should_cache_dark_mode_classification_ = true; DISALLOW_COPY_AND_ASSIGN(Image); };
diff --git a/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.cc b/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.cc index 71a24f2..92bc9e3 100644 --- a/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.cc +++ b/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.cc
@@ -6,12 +6,31 @@ #include <utility> +#include "base/synchronization/waitable_event.h" #include "third_party/blink/public/platform/platform.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" #include "third_party/blink/renderer/platform/graphics/paint/paint_record.h" #include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h" +#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" +#include "third_party/blink/renderer/platform/scheduler/public/thread.h" namespace blink { +namespace { +class AutoSignal { + public: + explicit AutoSignal(base::WaitableEvent* event) : event_(event) { + DCHECK(event); + } + ~AutoSignal() { event_->Signal(); } + + private: + base::WaitableEvent* event_; + + DISALLOW_COPY_AND_ASSIGN(AutoSignal); +}; +} // namespace + // static std::unique_ptr<PlatformPaintWorkletLayerPainter> PaintWorkletPaintDispatcher::CreateCompositorThreadPainter( @@ -31,6 +50,7 @@ "PaintWorkletPaintDispatcher::RegisterPaintWorkletPainter"); DCHECK(painter); + MutexLocker lock(painter_map_mutex_); DCHECK(painter_map_.find(painter) == painter_map_.end()); painter_map_.insert(painter, painter_runner); } @@ -41,6 +61,7 @@ "PaintWorkletPaintDispatcher::" "UnregisterPaintWorkletPainter"); DCHECK(painter); + MutexLocker lock(painter_map_mutex_); DCHECK(painter_map_.find(painter) != painter_map_.end()); painter_map_.erase(painter); } @@ -52,7 +73,43 @@ cc::PaintWorkletInput* input) { TRACE_EVENT0("cc", "PaintWorkletPaintDispatcher::Paint"); sk_sp<cc::PaintRecord> output = sk_make_sp<cc::PaintOpBuffer>(); - // TODO(xidachen): call the actual paint function in PaintWorkletProxyClient. + + PaintWorkletPainterToTaskRunnerMap copied_painter_map; + { + MutexLocker lock(painter_map_mutex_); + if (painter_map_.IsEmpty()) + return output; + // TODO(xidachen): copying is a temporary solution to prevent deadlock. It + // should be automatically solved with CC work. + copied_painter_map = painter_map_; + } + + base::WaitableEvent done_event; + + for (auto& pair : copied_painter_map) { + if (pair.key->GetWorkletId() != input->WorkletId()) + continue; + PaintWorkletPainter* painter = pair.key; + scoped_refptr<base::SingleThreadTaskRunner> task_runner = pair.value; + + DCHECK(!task_runner->BelongsToCurrentThread()); + std::unique_ptr<AutoSignal> done = + std::make_unique<AutoSignal>(&done_event); + + PostCrossThreadTask( + *task_runner, FROM_HERE, + CrossThreadBind( + [](PaintWorkletPainter* painter, cc::PaintWorkletInput* input, + std::unique_ptr<AutoSignal> completion, + sk_sp<cc::PaintRecord>* output) { + *output = painter->Paint(input); + }, + WrapCrossThreadPersistent(painter), CrossThreadUnretained(input), + WTF::Passed(std::move(done)), CrossThreadUnretained(&output))); + } + + done_event.Wait(); + return output; }
diff --git a/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h b/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h index a86eaeb..6534033 100644 --- a/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h +++ b/third_party/blink/renderer/platform/graphics/paint_worklet_paint_dispatcher.h
@@ -16,6 +16,7 @@ #include "third_party/blink/renderer/platform/heap/visitor.h" #include "third_party/blink/renderer/platform/wtf/hash_map.h" #include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" +#include "third_party/blink/renderer/platform/wtf/threading_primitives.h" namespace blink { @@ -51,6 +52,11 @@ PaintWorkletPainterToTaskRunnerMap painter_map_; + // The (Un)registerPaintWorkletPainter comes from the worklet thread, and the + // Paint call is initiated from the raster threads, this mutex ensures that + // accessing / updating the |painter_map_| is thread safe. + Mutex painter_map_mutex_; + DISALLOW_COPY_AND_ASSIGN(PaintWorkletPaintDispatcher); };
diff --git a/third_party/blink/renderer/platform/graphics/paint_worklet_painter.h b/third_party/blink/renderer/platform/graphics/paint_worklet_painter.h index d900eba3..23aeb4b 100644 --- a/third_party/blink/renderer/platform/graphics/paint_worklet_painter.h +++ b/third_party/blink/renderer/platform/graphics/paint_worklet_painter.h
@@ -29,6 +29,9 @@ class PLATFORM_EXPORT PaintWorkletPainter : public GarbageCollectedMixin { public: virtual ~PaintWorkletPainter() = default; + + virtual int GetWorkletId() const = 0; + virtual sk_sp<PaintRecord> Paint(cc::PaintWorkletInput*) = 0; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/graphics/platform_paint_worklet_layer_painter.h b/third_party/blink/renderer/platform/graphics/platform_paint_worklet_layer_painter.h index 53ea8e8..4cc7a0c6 100644 --- a/third_party/blink/renderer/platform/graphics/platform_paint_worklet_layer_painter.h +++ b/third_party/blink/renderer/platform/graphics/platform_paint_worklet_layer_painter.h
@@ -13,6 +13,8 @@ namespace blink { +using CompositorPaintWorkletInput = cc::PaintWorkletInput; + class PaintWorkletPaintDispatcher; // This class serves as a bridge which connects the compositor and the paint
diff --git a/third_party/blink/renderer/platform/heap/blink_gc.h b/third_party/blink/renderer/platform/heap/blink_gc.h index 59deeea..f1cda113 100644 --- a/third_party/blink/renderer/platform/heap/blink_gc.h +++ b/third_party/blink/renderer/platform/heap/blink_gc.h
@@ -92,11 +92,11 @@ // kIdleGC = 0, kPreciseGC = 1, kConservativeGC = 2, - kForcedGC = 3, + kForcedGCForTesting = 3, kMemoryPressureGC = 4, kPageNavigationGC = 5, kThreadTerminationGC = 6, - kTesting = 7, + // kTesting = 7, // kIncrementalIdleGC = 8, kIncrementalV8FollowupGC = 9, kUnifiedHeapGC = 10,
diff --git a/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc b/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc index deae8e9..e8ef8c4e 100644 --- a/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc +++ b/third_party/blink/renderer/platform/heap/blink_gc_memory_dump_provider.cc
@@ -52,7 +52,7 @@ if (level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { ThreadState::Current()->CollectGarbage( BlinkGC::kNoHeapPointersOnStack, BlinkGC::kTakeSnapshot, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGCForTesting); } DumpMemoryTotals(memory_dump);
diff --git a/third_party/blink/renderer/platform/heap/heap_compact.cc b/third_party/blink/renderer/platform/heap/heap_compact.cc index d1118188..8766f7f 100644 --- a/third_party/blink/renderer/platform/heap/heap_compact.cc +++ b/third_party/blink/renderer/platform/heap/heap_compact.cc
@@ -374,13 +374,12 @@ if (stack_state == BlinkGC::kHeapPointersOnStack) return false; - if (reason == BlinkGC::GCReason::kTesting) { + if (reason == BlinkGC::GCReason::kForcedGCForTesting) { UpdateHeapResidency(); return force_compaction_gc_; } - if (reason != BlinkGC::GCReason::kPreciseGC && - reason != BlinkGC::GCReason::kForcedGC) + if (reason != BlinkGC::GCReason::kPreciseGC) return false; // TODO(keishi): crbug.com/918064 Heap compaction for incremental marking
diff --git a/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc b/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc index a80200e..f92147b 100644 --- a/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc +++ b/third_party/blink/renderer/platform/heap/heap_stats_collector_test.cc
@@ -14,7 +14,7 @@ TEST(ThreadHeapStatsCollectorTest, InitialEmpty) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); for (int i = 0; i < ThreadHeapStatsCollector::kNumScopeIds; i++) { EXPECT_EQ(TimeDelta(), stats_collector.current().scope_data[i]); } @@ -24,7 +24,7 @@ TEST(ThreadHeapStatsCollectorTest, IncreaseScopeTime) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseScopeTime( ThreadHeapStatsCollector::kIncrementalMarkingStep, TimeDelta::FromMilliseconds(1)); @@ -37,7 +37,7 @@ TEST(ThreadHeapStatsCollectorTest, StopMovesCurrentToPrevious) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseScopeTime( ThreadHeapStatsCollector::kIncrementalMarkingStep, TimeDelta::FromMilliseconds(1)); @@ -50,7 +50,7 @@ TEST(ThreadHeapStatsCollectorTest, StopResetsCurrent) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseScopeTime( ThreadHeapStatsCollector::kIncrementalMarkingStep, TimeDelta::FromMilliseconds(1)); @@ -64,7 +64,7 @@ TEST(ThreadHeapStatsCollectorTest, StartStop) { ThreadHeapStatsCollector stats_collector; EXPECT_FALSE(stats_collector.is_started()); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); EXPECT_TRUE(stats_collector.is_started()); stats_collector.NotifyMarkingCompleted(); stats_collector.NotifySweepingCompleted(); @@ -79,16 +79,17 @@ TEST(ThreadHeapStatsCollectorTest, UpdateReason) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); - stats_collector.UpdateReason(BlinkGC::GCReason::kForcedGC); + stats_collector.UpdateReason(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifySweepingCompleted(); - EXPECT_EQ(BlinkGC::GCReason::kForcedGC, stats_collector.previous().reason); + EXPECT_EQ(BlinkGC::GCReason::kForcedGCForTesting, + stats_collector.previous().reason); } TEST(ThreadHeapStatsCollectorTest, InitialEstimatedObjectSizeInBytes) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); EXPECT_EQ(0u, stats_collector.object_size_in_bytes()); stats_collector.NotifyMarkingCompleted(); stats_collector.NotifySweepingCompleted(); @@ -96,7 +97,7 @@ TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeInBytesNoMarkedBytes) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseAllocatedObjectSize(512); EXPECT_EQ(512u, stats_collector.object_size_in_bytes()); stats_collector.NotifyMarkingCompleted(); @@ -105,11 +106,11 @@ TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeInBytesWithMarkedBytes) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseAllocatedObjectSize(512); EXPECT_EQ(640u, stats_collector.object_size_in_bytes()); @@ -119,11 +120,11 @@ TEST(ThreadHeapStatsCollectorTest, EstimatedObjectSizeInBytesDoNotCountCurrentlyMarkedBytes) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); // Currently marked bytes should not account to the estimated object size. @@ -136,7 +137,7 @@ // Checks that a marking time estimate can be retrieved before the first // garbage collection triggers. ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); EXPECT_LT(0u, stats_collector.estimated_marking_time_in_seconds()); stats_collector.NotifyMarkingCompleted(); stats_collector.NotifySweepingCompleted(); @@ -144,13 +145,13 @@ TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime1) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseScopeTime( ThreadHeapStatsCollector::kAtomicPhaseMarking, TimeDelta::FromSeconds(1)); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(1024); stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); EXPECT_DOUBLE_EQ(1.0, stats_collector.estimated_marking_time_in_seconds()); stats_collector.NotifyMarkingCompleted(); stats_collector.NotifySweepingCompleted(); @@ -158,13 +159,13 @@ TEST(ThreadHeapStatsCollectorTest, EstimatedMarkingTime2) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseScopeTime( ThreadHeapStatsCollector::kAtomicPhaseMarking, TimeDelta::FromSeconds(1)); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(1024); stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseAllocatedObjectSize(512); EXPECT_DOUBLE_EQ(1.5, stats_collector.estimated_marking_time_in_seconds()); stats_collector.NotifyMarkingCompleted(); @@ -174,7 +175,7 @@ TEST(ThreadHeapStatsCollectorTest, AllocatedSpaceInBytesInitialZero) { ThreadHeapStatsCollector stats_collector; EXPECT_EQ(0u, stats_collector.allocated_space_bytes()); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); EXPECT_EQ(0u, stats_collector.allocated_space_bytes()); stats_collector.NotifyMarkingCompleted(); EXPECT_EQ(0u, stats_collector.allocated_space_bytes()); @@ -201,7 +202,7 @@ TEST(ThreadHeapStatsCollectorTest, EventPrevGCMarkedObjectSize) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(1024); stats_collector.NotifySweepingCompleted(); @@ -210,7 +211,7 @@ TEST(ThreadHeapStatsCollectorTest, EventMarkingTimeInMsFromIncrementalGC) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseScopeTime( ThreadHeapStatsCollector::kIncrementalMarkingStartMarking, TimeDelta::FromMilliseconds(7)); @@ -231,7 +232,7 @@ TEST(ThreadHeapStatsCollectorTest, EventMarkingTimeInMsFromFullGC) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseScopeTime( ThreadHeapStatsCollector::kAtomicPhaseMarking, TimeDelta::FromMilliseconds(11)); @@ -242,7 +243,7 @@ TEST(ThreadHeapStatsCollectorTest, EventMarkingTimePerByteInS) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseMarkedObjectSize(1000); stats_collector.IncreaseScopeTime( ThreadHeapStatsCollector::kAtomicPhaseMarking, TimeDelta::FromSeconds(1)); @@ -254,7 +255,7 @@ TEST(ThreadHeapStatsCollectorTest, EventSweepingTimeInMs) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kLazySweepInIdle, TimeDelta::FromMilliseconds(1)); stats_collector.IncreaseScopeTime(ThreadHeapStatsCollector::kLazySweepInIdle, @@ -274,7 +275,7 @@ TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedBytes) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseCompactionFreedSize(512); stats_collector.NotifySweepingCompleted(); @@ -283,7 +284,7 @@ TEST(ThreadHeapStatsCollectorTest, EventCompactionFreedPages) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseCompactionFreedPages(3); stats_collector.NotifySweepingCompleted(); @@ -292,7 +293,7 @@ TEST(ThreadHeapStatsCollectorTest, EventInitialEstimatedLiveObjectRate) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); EXPECT_DOUBLE_EQ(0.0, stats_collector.previous().live_object_rate); @@ -301,11 +302,11 @@ TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateSameMarkedBytes) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); @@ -315,11 +316,11 @@ TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateHalfMarkedBytes) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(256); stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); @@ -328,11 +329,11 @@ TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateNoMarkedBytes) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(256); stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifySweepingCompleted(); EXPECT_DOUBLE_EQ(0.0, stats_collector.previous().live_object_rate); } @@ -340,12 +341,12 @@ TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateWithAllocatedBytes1) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); stats_collector.IncreaseAllocatedObjectSize(128); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); @@ -355,11 +356,11 @@ TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateWithAllocatedBytes2) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.NotifySweepingCompleted(); stats_collector.IncreaseAllocatedObjectSize(128); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); @@ -369,7 +370,7 @@ TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateWithAllocatedBytes3) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.NotifySweepingCompleted(); EXPECT_DOUBLE_EQ(0, stats_collector.previous().live_object_rate); @@ -378,11 +379,11 @@ TEST(ThreadHeapStatsCollectorTest, EventEstimatedLiveObjectRateWithAllocatedBytes4) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseMarkedObjectSize(128); stats_collector.NotifySweepingCompleted(); - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.NotifyMarkingCompleted(); stats_collector.NotifySweepingCompleted(); EXPECT_DOUBLE_EQ(0, stats_collector.previous().live_object_rate); @@ -390,7 +391,7 @@ TEST(ThreadHeapStatsCollectorTest, EventAllocatedSpaceBeforeSweeping1) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseAllocatedSpace(1024); stats_collector.NotifyMarkingCompleted(); stats_collector.IncreaseAllocatedSpace(2048); @@ -402,7 +403,7 @@ TEST(ThreadHeapStatsCollectorTest, EventAllocatedSpaceBeforeSweeping2) { ThreadHeapStatsCollector stats_collector; - stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kTesting); + stats_collector.NotifyMarkingStarted(BlinkGC::GCReason::kForcedGCForTesting); stats_collector.IncreaseAllocatedSpace(1024); stats_collector.NotifyMarkingCompleted(); stats_collector.DecreaseAllocatedSpace(1024);
diff --git a/third_party/blink/renderer/platform/heap/heap_test.cc b/third_party/blink/renderer/platform/heap/heap_test.cc index 285f8b18..422a25d 100644 --- a/third_party/blink/renderer/platform/heap/heap_test.cc +++ b/third_party/blink/renderer/platform/heap/heap_test.cc
@@ -377,7 +377,7 @@ : TestGCCollectGarbageScope(state), atomic_pause_scope_(ThreadState::Current()) { ThreadState::Current()->Heap().stats_collector()->NotifyMarkingStarted( - BlinkGC::GCReason::kTesting); + BlinkGC::GCReason::kForcedGCForTesting); ThreadState::Current()->AtomicPausePrologue(state, BlinkGC::kAtomicMarking, BlinkGC::GCReason::kPreciseGC); } @@ -1876,7 +1876,7 @@ MakeGarbageCollected<SimpleFinalizedObject>(); ThreadState::Current()->CollectGarbage( BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC); + BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGCForTesting); EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_); for (int i = 0; i < 10000; i++) MakeGarbageCollected<SimpleFinalizedObject>(); @@ -1904,7 +1904,7 @@ MakeGarbageCollected<LargeHeapObject>(); ThreadState::Current()->CollectGarbage( BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC); + BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGCForTesting); EXPECT_EQ(0, LargeHeapObject::destructor_calls_); for (int i = 0; i < 10; i++) { MakeGarbageCollected<LargeHeapObject>(); @@ -1915,7 +1915,7 @@ EXPECT_EQ(10, LargeHeapObject::destructor_calls_); ThreadState::Current()->CollectGarbage( BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC); + BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGCForTesting); EXPECT_EQ(10, LargeHeapObject::destructor_calls_); PreciselyCollectGarbage(); EXPECT_EQ(22, LargeHeapObject::destructor_calls_); @@ -1978,7 +1978,7 @@ MakeGarbageCollected<SimpleFinalizedObjectInstanceOfTemplate>(); ThreadState::Current()->CollectGarbage( BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC); + BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGCForTesting); EXPECT_EQ(0, SimpleFinalizedObject::destructor_calls_); EXPECT_EQ(100, SimpleFinalizedEagerObject::destructor_calls_); EXPECT_EQ(100, SimpleFinalizedObjectInstanceOfTemplate::destructor_calls_);
diff --git a/third_party/blink/renderer/platform/heap/heap_test_utilities.cc b/third_party/blink/renderer/platform/heap/heap_test_utilities.cc index 1d01f7b..2fb98c3 100644 --- a/third_party/blink/renderer/platform/heap/heap_test_utilities.cc +++ b/third_party/blink/renderer/platform/heap/heap_test_utilities.cc
@@ -13,13 +13,13 @@ void PreciselyCollectGarbage() { ThreadState::Current()->CollectGarbage( BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGCForTesting); } void ConservativelyCollectGarbage(BlinkGC::SweepingType sweeping_type) { - ThreadState::Current()->CollectGarbage(BlinkGC::kHeapPointersOnStack, - BlinkGC::kAtomicMarking, sweeping_type, - BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectGarbage( + BlinkGC::kHeapPointersOnStack, BlinkGC::kAtomicMarking, sweeping_type, + BlinkGC::GCReason::kForcedGCForTesting); } // Do several GCs to make sure that later GCs don't free up old memory from
diff --git a/third_party/blink/renderer/platform/heap/heap_thread_test.cc b/third_party/blink/renderer/platform/heap/heap_thread_test.cc index f5d687b6..9d6facd 100644 --- a/third_party/blink/renderer/platform/heap/heap_thread_test.cc +++ b/third_party/blink/renderer/platform/heap/heap_thread_test.cc
@@ -254,7 +254,7 @@ // Step 4: Run a GC. ThreadState::Current()->CollectGarbage( BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGCForTesting); SwitchToMainThread(); }
diff --git a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc index 7abd302..b947057 100644 --- a/third_party/blink/renderer/platform/heap/incremental_marking_test.cc +++ b/third_party/blink/renderer/platform/heap/incremental_marking_test.cc
@@ -1542,7 +1542,8 @@ } void Start() { - thread_state_->IncrementalMarkingStart(BlinkGC::GCReason::kTesting); + thread_state_->IncrementalMarkingStart( + BlinkGC::GCReason::kForcedGCForTesting); } bool SingleStep(BlinkGC::StackState stack_state =
diff --git a/third_party/blink/renderer/platform/heap/thread_state.cc b/third_party/blink/renderer/platform/heap/thread_state.cc index c0b40b37..bc8242b 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.cc +++ b/third_party/blink/renderer/platform/heap/thread_state.cc
@@ -105,16 +105,14 @@ return "PreciseGC"; case BlinkGC::GCReason::kConservativeGC: return "ConservativeGC"; - case BlinkGC::GCReason::kForcedGC: - return "ForcedGC"; + case BlinkGC::GCReason::kForcedGCForTesting: + return "ForcedGCForTesting"; case BlinkGC::GCReason::kMemoryPressureGC: return "MemoryPressureGC"; case BlinkGC::GCReason::kPageNavigationGC: return "PageNavigationGC"; case BlinkGC::GCReason::kThreadTerminationGC: return "ThreadTerminationGC"; - case BlinkGC::GCReason::kTesting: - return "TestingGC"; case BlinkGC::GCReason::kIncrementalV8FollowupGC: return "IncrementalV8FollowupGC"; case BlinkGC::GCReason::kUnifiedHeapGC: @@ -171,7 +169,7 @@ end_of_stack_(reinterpret_cast<intptr_t*>(WTF::GetStackStart())), gc_state_(kNoGCScheduled), gc_phase_(GCPhase::kNone), - reason_for_scheduled_gc_(BlinkGC::GCReason::kMaxValue), + reason_for_scheduled_gc_(BlinkGC::GCReason::kForcedGCForTesting), #if defined(ADDRESS_SANITIZER) asan_fake_stack_(__asan_get_current_fake_stack()), #endif @@ -638,7 +636,7 @@ RuntimeEnabledFeatures::HeapIncrementalMarkingStressEnabled()) { VLOG(2) << "[state:" << this << "] " << "ScheduleGCIfNeeded: Scheduled incremental marking for testing"; - IncrementalMarkingStart(BlinkGC::GCReason::kTesting); + IncrementalMarkingStart(BlinkGC::GCReason::kForcedGCForTesting); return; } } @@ -953,7 +951,8 @@ SweepForbiddenScope scope(this); ThreadHeapStatsCollector::EnabledScope stats_scope( Heap().stats_collector(), ThreadHeapStatsCollector::kCompleteSweep, - "forced", current_gc_data_.reason == BlinkGC::GCReason::kForcedGC); + "forced", + current_gc_data_.reason == BlinkGC::GCReason::kForcedGCForTesting); Heap().CompleteSweep(); if (!was_in_atomic_pause) LeaveAtomicPause(); @@ -1156,11 +1155,10 @@ // COUNT_BY_GC_REASON(IdleGC) COUNT_BY_GC_REASON(PreciseGC) COUNT_BY_GC_REASON(ConservativeGC) - COUNT_BY_GC_REASON(ForcedGC) + COUNT_BY_GC_REASON(ForcedGCForTesting) COUNT_BY_GC_REASON(MemoryPressureGC) COUNT_BY_GC_REASON(PageNavigationGC) COUNT_BY_GC_REASON(ThreadTerminationGC) - COUNT_BY_GC_REASON(Testing) COUNT_BY_GC_REASON(IncrementalV8FollowupGC) COUNT_BY_GC_REASON(UnifiedHeapGC) @@ -1464,7 +1462,8 @@ // mentioned below. In this case we will follow up with a regular full // garbage collection. const bool should_do_full_gc = - !was_incremental_marking || reason == BlinkGC::GCReason::kForcedGC || + !was_incremental_marking || + reason == BlinkGC::GCReason::kForcedGCForTesting || reason == BlinkGC::GCReason::kMemoryPressureGC || reason == BlinkGC::GCReason::kThreadTerminationGC; if (should_do_full_gc) { @@ -1489,11 +1488,10 @@ switch (reason) { COUNT_BY_GC_REASON(PreciseGC) COUNT_BY_GC_REASON(ConservativeGC) - COUNT_BY_GC_REASON(ForcedGC) + COUNT_BY_GC_REASON(ForcedGCForTesting) COUNT_BY_GC_REASON(MemoryPressureGC) COUNT_BY_GC_REASON(PageNavigationGC) COUNT_BY_GC_REASON(ThreadTerminationGC) - COUNT_BY_GC_REASON(Testing) COUNT_BY_GC_REASON(IncrementalV8FollowupGC) COUNT_BY_GC_REASON(UnifiedHeapGC) } @@ -1553,7 +1551,7 @@ { ThreadHeapStatsCollector::DevToolsScope stats1( Heap().stats_collector(), ThreadHeapStatsCollector::kAtomicPhase, - "forced", reason == BlinkGC::GCReason::kForcedGC); + "forced", reason == BlinkGC::GCReason::kForcedGCForTesting); { AtomicPauseScope atomic_pause_scope(this); ThreadHeapStatsCollector::EnabledScope stats2( @@ -1737,12 +1735,13 @@ Heap().VerifyMarking(); } -void ThreadState::CollectAllGarbageForTesting() { +void ThreadState::CollectAllGarbageForTesting(BlinkGC::StackState stack_state) { // We need to run multiple GCs to collect a chain of persistent handles. size_t previous_live_objects = 0; for (int i = 0; i < 5; ++i) { - CollectGarbage(BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + CollectGarbage(stack_state, BlinkGC::kAtomicMarking, + BlinkGC::kEagerSweeping, + BlinkGC::GCReason::kForcedGCForTesting); const size_t live_objects = Heap().stats_collector()->previous().marked_bytes; if (live_objects == previous_live_objects)
diff --git a/third_party/blink/renderer/platform/heap/thread_state.h b/third_party/blink/renderer/platform/heap/thread_state.h index b9cadd1..4c91b5d 100644 --- a/third_party/blink/renderer/platform/heap/thread_state.h +++ b/third_party/blink/renderer/platform/heap/thread_state.h
@@ -375,11 +375,16 @@ v8::Isolate* GetIsolate() const { return isolate_; } + // Use CollectAllGarbageForTesting below for testing! void CollectGarbage(BlinkGC::StackState, BlinkGC::MarkingType, BlinkGC::SweepingType, BlinkGC::GCReason); - void CollectAllGarbageForTesting(); + + // Forced garbage collection for testing. + void CollectAllGarbageForTesting( + BlinkGC::StackState stack_state = + BlinkGC::StackState::kNoHeapPointersOnStack); // Register the pre-finalizer for the |self| object. The class T must have // USING_PRE_FINALIZER().
diff --git a/third_party/blink/renderer/platform/heap/thread_state_scheduling_test.cc b/third_party/blink/renderer/platform/heap/thread_state_scheduling_test.cc index 415b358a..1cb35b56 100644 --- a/third_party/blink/renderer/platform/heap/thread_state_scheduling_test.cc +++ b/third_party/blink/renderer/platform/heap/thread_state_scheduling_test.cc
@@ -28,7 +28,7 @@ void StartIncrementalMarking() { RuntimeEnabledFeatures::SetHeapIncrementalMarkingEnabled(true); EXPECT_EQ(ThreadState::kNoGCScheduled, state_->GetGCState()); - state_->ScheduleIncrementalGC(BlinkGC::GCReason::kTesting); + state_->ScheduleIncrementalGC(BlinkGC::GCReason::kForcedGCForTesting); state_->RunScheduledGC(BlinkGC::kNoHeapPointersOnStack); EXPECT_EQ(ThreadState::kIncrementalMarkingStepScheduled, state_->GetGCState());
diff --git a/third_party/blink/renderer/platform/lifecycle_context_test.cc b/third_party/blink/renderer/platform/lifecycle_context_test.cc index 3b407dee..373e4e5 100644 --- a/third_party/blink/renderer/platform/lifecycle_context_test.cc +++ b/third_party/blink/renderer/platform/lifecycle_context_test.cc
@@ -145,7 +145,7 @@ bool was_enabled = RuntimeEnabledFeatures::HeapIncrementalMarkingEnabled(); RuntimeEnabledFeatures::SetHeapIncrementalMarkingEnabled(true); ThreadState* thread_state = ThreadState::Current(); - thread_state->IncrementalMarkingStart(BlinkGC::GCReason::kTesting); + thread_state->IncrementalMarkingStart(BlinkGC::GCReason::kForcedGCForTesting); DummyContext* context = DummyContext::Create();
diff --git a/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc b/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc index 79ae10c..9031a51 100644 --- a/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/memory_cache_test.cc
@@ -320,9 +320,8 @@ WeakPersistent<Resource> resource1_weak = resource1; WeakPersistent<Resource> resource2_weak = resource2; - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); // Resources are garbage-collected (WeakMemoryCache) and thus removed // from MemoryCache. EXPECT_FALSE(resource1_weak);
diff --git a/third_party/blink/renderer/platform/timer_test.cc b/third_party/blink/renderer/platform/timer_test.cc index fa9e765..4ff74e0 100644 --- a/third_party/blink/renderer/platform/timer_test.cc +++ b/third_party/blink/renderer/platform/timer_test.cc
@@ -636,9 +636,8 @@ owner->StartOneShot(TimeDelta(), FROM_HERE); owner = nullptr; - ThreadState::Current()->CollectGarbage( - BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kEagerSweeping, BlinkGC::GCReason::kForcedGC); + ThreadState::Current()->CollectAllGarbageForTesting( + BlinkGC::kNoHeapPointersOnStack); EXPECT_TRUE(record->OwnerIsDestructed()); EXPECT_FALSE(record->TimerHasFired()); @@ -656,9 +655,11 @@ owner->StartOneShot(TimeDelta(), FROM_HERE); owner = nullptr; + // Explicit regular GC call to allow lazy sweeping. ThreadState::Current()->CollectGarbage( BlinkGC::kNoHeapPointersOnStack, BlinkGC::kAtomicMarking, - BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGC); + BlinkGC::kLazySweeping, BlinkGC::GCReason::kForcedGCForTesting); + // Since the heap is laziy swept, owner is not yet destructed. EXPECT_FALSE(record->OwnerIsDestructed()); {
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 747f0559..6d231b94 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -3026,6 +3026,33 @@ crbug.com/939181 virtual/not-site-per-process/external/wpt/html/browsers/origin/cross-origin-objects/cross-origin-objects.html [ Failure Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-048-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-046a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-082-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-048a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-085-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-044-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-097a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-001-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-090-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-092-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-095-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-095a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-040a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-096a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-002-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-045-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-091-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-092a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-004-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-096-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-040-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-003-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-091a-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-097-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-041-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-049-manual.html [ Skip ] +crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-line-090a-manual.html [ Skip ] crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-090a-manual.html [ Skip ] crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-046a-manual.html [ Skip ] crbug.com/626703 external/wpt/css/css-text-decor/text-decoration-091-manual.html [ Skip ] @@ -5904,6 +5931,11 @@ crbug.com/926170 external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html [ Pass Timeout ] crbug.com/926170 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCIceConnectionState-candidate-pair.https.html [ Pass Timeout ] +# TODO(guidou): Remove these expectations once crbug.com/740501 is fixed in third_party/webrtc. +crbug.com/740501 external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html [ Pass Failure Timeout ] +crbug.com/740501 virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html [ Pass Failure Timeout ] +crbug.com/740501 fast/peerconnection/RTCPeerConnection-AddRemoveStream.html [ Pass Failure Timeout ] + # Sheriff 2019-01-18 crbug.com/922970 external/wpt/css/css-transitions/CSSTransition-startTime.tentative.html [ Failure Pass ] @@ -6211,3 +6243,6 @@ crbug.com/949444 [ Mac10.13 Debug ] virtual/mouseevent_fractional/fast/events/sequential-focus-navigation-starting-point.html [ Pass Crash ] crbug.com/949444 [ Mac10.13 Debug ] virtual/user-activation-v2/fast/events/sequential-focus-navigation-starting-point.html [ Pass Crash ] crbug.com/949445 [ Mac ] fast/forms/text/input-text-scroll-left-on-blur.html [ Failure ] + +# Sheriff 2019-04-05 +crbug.com/ [ Win7 ] virtual/streams-native/http/tests/fetch/serviceworker/referrer-base-https-other-https.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index cd00ea6..552c4c70 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -481,6 +481,16 @@ "args": ["--blink-settings=darkMode=3,darkModePagePolicy=1"] }, { + "prefix": "dark-mode", + "base": "paint/dark-mode/native-theme-off", + "args": ["--blink-settings=darkMode=3"] + }, + { + "prefix": "dark-mode", + "base": "paint/dark-mode/native-theme-on", + "args": ["--blink-settings=darkMode=3"] + }, + { "prefix": "outofblink-cors", "base": "external/wpt/fetch", "args": ["--enable-features=OutOfBlinkCors,NetworkService"]
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities-expected.txt deleted file mode 100644 index 4ced9348..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -Test that XMLSerializer quotes the attribute characters specified in the W3C spec. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS htmlElement.outerHTML is "<div quoteme=\"< > & " ' \"></div>" -PASS (new XMLSerializer()).serializeToString(xmlElement) is "<div xmlns=\"http://www.w3.org/1999/xhtml\" quoteme=\"< > & " ' \xA0\"></div>" -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities.html index e5a89cd..a3ecdd9 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-entities.html
@@ -1,9 +1,8 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> - +<title>Test that XMLSerializer quotes the attribute characters specified in 'https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#dfn-concept-serialize-xml-attributes', the W3C spec</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <script> -description('Test that XMLSerializer quotes the attribute characters specified in <a href="https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#dfn-concept-serialize-xml-attributes">the W3C spec</a>.'); - var attrValue = '< > & " \' \xA0'; // HTML case. @@ -11,7 +10,7 @@ // Steps 1-3 under the "Escaping a string" heading are relevant to attributes. window.htmlElement = document.createElement('div'); htmlElement.setAttribute('quoteme', attrValue); -shouldBe('htmlElement.outerHTML', '"<div quoteme=\\"< > & " \' \\"><' + '/div>"'); +assert_equals(htmlElement.outerHTML, "<div quoteme=\"< > & " ' \"></div>"); // XML case. // DOM parsing and serialization: https://dvcs.w3.org/hg/innerhtml/raw-file/tip/index.html#dfn-concept-serialize-xml-attributes @@ -19,5 +18,6 @@ var xmlDocument = document.implementation.createDocument('http://www.w3.org/1999/xhtml', 'html', null); window.xmlElement = xmlDocument.createElement('div'); xmlElement.setAttribute('quoteme', attrValue); -shouldBe('(new XMLSerializer()).serializeToString(xmlElement)', '"<div xmlns=\\"http://www.w3.org/1999/xhtml\\" quoteme=\\"< > & " \' \\xA0\\"><' + '/div>"'); +assert_equals((new XMLSerializer()).serializeToString(xmlElement), "<div xmlns=\"http://www.w3.org/1999/xhtml\" quoteme=\"< > & " ' \xA0\"></div>"); +done(); </script>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-namespace-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-namespace-expected.txt deleted file mode 100644 index 533ffaa..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-namespace-expected.txt +++ /dev/null
@@ -1,30 +0,0 @@ -Tests the serialization of XML namespaces on attributes, as reported in bug 248044. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS doc.documentElement.getAttributeNS(null, "attr1") is "value1" -PASS doc.documentElement.getAttributeNS("http://www.example.com", "foo") is "bar" -PASS doc.documentElement.getAttributeNS("http://www.example.com", "foo2") is "bar2" -PASS doc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz") is "buzz" -PASS doc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz2") is "buzz2" -PASS doc.documentElement.getAttributeNS("http://www.example.com/ns2", "name") is "value" -PASS doc.documentElement.getAttributeNS("http://www.example.com/ns2", "name2") is "value2" -PASS doc.documentElement.getAttributeNS("http://www.w3.org/XML/1998/namespace", "id") is "outer" -PASS doc.querySelector("inner").localName is "inner" -PASS doc.querySelector("inner").namespaceURI is "http://www.example.com" -PASS doc.querySelector("inner").getAttributeNS(null, "id") is "inner" -PASS parsedDoc.documentElement.getAttributeNS(null, "attr1") is "value1" -PASS parsedDoc.documentElement.getAttributeNS("http://www.example.com", "foo") is "bar" -PASS parsedDoc.documentElement.getAttributeNS("http://www.example.com", "foo2") is "bar2" -PASS parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz") is "buzz" -PASS parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz2") is "buzz2" -PASS parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns2", "name") is "value" -PASS parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns2", "name2") is "value2" -PASS parsedDoc.documentElement.getAttributeNS("http://www.w3.org/XML/1998/namespace", "id") is "outer" -PASS parsedDoc.querySelector("inner").localName is "inner" -PASS parsedDoc.querySelector("inner").namespaceURI is "http://www.example.com" -PASS parsedDoc.querySelector("inner").getAttributeNS(null, "id") is "inner" -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-namespace.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-namespace.html index be727ee..215a79a5 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-namespace.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-namespace.html
@@ -1,7 +1,8 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> +<title>Tests the serialization of XML namespaces on attributes, as reported in 'http://crbug.com/248044', bug 248044</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <script> -description('Tests the serialization of XML namespaces on attributes, as reported in <a href="http://crbug.com/248044">bug 248044</a>.'); window.doc = (new DOMParser()).parseFromString('<outer attr1="value1" xmlns="http://www.example.com"/>', 'text/xml'); // XML-namespaced attributes should get the "xml" prefix. doc.documentElement.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'id', 'outer'); @@ -24,31 +25,32 @@ innerElement.setAttributeNS(null, 'id', 'inner'); // Check the DOM construction. -shouldBe('doc.documentElement.getAttributeNS(null, "attr1")', '"value1"'); -shouldBe('doc.documentElement.getAttributeNS("http://www.example.com", "foo")', '"bar"'); -shouldBe('doc.documentElement.getAttributeNS("http://www.example.com", "foo2")', '"bar2"'); -shouldBe('doc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz")', '"buzz"'); -shouldBe('doc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz2")', '"buzz2"'); -shouldBe('doc.documentElement.getAttributeNS("http://www.example.com/ns2", "name")', '"value"'); -shouldBe('doc.documentElement.getAttributeNS("http://www.example.com/ns2", "name2")', '"value2"'); -shouldBe('doc.documentElement.getAttributeNS("http://www.w3.org/XML/1998/namespace", "id")', '"outer"'); -shouldBe('doc.querySelector("inner").localName', '"inner"'); -shouldBe('doc.querySelector("inner").namespaceURI', '"http://www.example.com"'); -shouldBe('doc.querySelector("inner").getAttributeNS(null, "id")', '"inner"'); +assert_equals(doc.documentElement.getAttributeNS(null, "attr1"), "value1"); +assert_equals(doc.documentElement.getAttributeNS("http://www.example.com", "foo"), "bar"); +assert_equals(doc.documentElement.getAttributeNS("http://www.example.com", "foo2"), "bar2"); +assert_equals(doc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz"), "buzz"); +assert_equals(doc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz2"), "buzz2"); +assert_equals(doc.documentElement.getAttributeNS("http://www.example.com/ns2", "name"), "value"); +assert_equals(doc.documentElement.getAttributeNS("http://www.example.com/ns2", "name2"), "value2"); +assert_equals(doc.documentElement.getAttributeNS("http://www.w3.org/XML/1998/namespace", "id"), "outer"); +assert_equals(doc.querySelector("inner").localName, "inner"); +assert_equals(doc.querySelector("inner").namespaceURI, "http://www.example.com"); +assert_equals(doc.querySelector("inner").getAttributeNS(null, "id"), "inner"); window.xmlText = (new XMLSerializer()).serializeToString(doc); // exported for debugging window.parsedDoc = (new DOMParser()).parseFromString(xmlText, 'text/xml'); // Check the serialization result. -shouldBe('parsedDoc.documentElement.getAttributeNS(null, "attr1")', '"value1"'); -shouldBe('parsedDoc.documentElement.getAttributeNS("http://www.example.com", "foo")', '"bar"'); -shouldBe('parsedDoc.documentElement.getAttributeNS("http://www.example.com", "foo2")', '"bar2"'); -shouldBe('parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz")', '"buzz"'); -shouldBe('parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz2")', '"buzz2"'); -shouldBe('parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns2", "name")', '"value"'); -shouldBe('parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns2", "name2")', '"value2"'); -shouldBe('parsedDoc.documentElement.getAttributeNS("http://www.w3.org/XML/1998/namespace", "id")', '"outer"'); -shouldBe('parsedDoc.querySelector("inner").localName', '"inner"'); -shouldBe('parsedDoc.querySelector("inner").namespaceURI', '"http://www.example.com"'); -shouldBe('parsedDoc.querySelector("inner").getAttributeNS(null, "id")', '"inner"'); +assert_equals(parsedDoc.documentElement.getAttributeNS(null, "attr1"), "value1"); +assert_equals(parsedDoc.documentElement.getAttributeNS("http://www.example.com", "foo"), "bar"); +assert_equals(parsedDoc.documentElement.getAttributeNS("http://www.example.com", "foo2"), "bar2"); +assert_equals(parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz"), "buzz"); +assert_equals(parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns1", "fizz2"), "buzz2"); +assert_equals(parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns2", "name"), "value"); +assert_equals(parsedDoc.documentElement.getAttributeNS("http://www.example.com/ns2", "name2"), "value2"); +assert_equals(parsedDoc.documentElement.getAttributeNS("http://www.w3.org/XML/1998/namespace", "id"), "outer"); +assert_equals(parsedDoc.querySelector("inner").localName, "inner"); +assert_equals(parsedDoc.querySelector("inner").namespaceURI, "http://www.example.com"); +assert_equals(parsedDoc.querySelector("inner").getAttributeNS(null, "id"), "inner"); +done(); </script>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-ns-prefix-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-ns-prefix-expected.txt deleted file mode 100644 index b35326d7..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-ns-prefix-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -This tests that XMLSerializer emits a correct namespace declaration for the element. The first line is serialized as part of a DocumentFragment. The second line is serialized as part of the Document. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image xlink:href="blah"/></svg> -<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><image xlink:href="blah"/></svg> -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-ns-prefix.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-ns-prefix.html index 5131ea1..9004ece 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-ns-prefix.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-ns-prefix.html
@@ -1,9 +1,13 @@ <!DOCTYPE html> +<title>This tests that XMLSerializer emits a correct namespace declaration for the <image> element. The first line is serialized as part of a DocumentFragment. The second line is serialized as part of the Document</title> <body> -<script src="../../resources/js-test.js"></script> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <script> - -description('This tests that XMLSerializer emits a correct namespace declaration for the <image> element. The first line is serialized as part of a DocumentFragment. The second line is serialized as part of the Document.'); +function escapeHTML(text) +{ + return text.replace(/&/g, "&").replace(/</g, "<").replace(/\0/g, "\\0"); +} var svgDoc = new DOMParser().parseFromString('<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"></svg>', 'text/xml'); var svgEl = svgDoc.firstChild; @@ -13,9 +17,13 @@ var serializer = new XMLSerializer(); -debug(escapeHTML(serializer.serializeToString(svgEl))); +var span = document.createElement("div"); +span.innerHTML = escapeHTML(serializer.serializeToString(svgEl)); +assert_equals(span.textContent, "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><image xlink:href=\"blah\"/></svg>"); document.body.appendChild(svgDoc.removeChild(svgEl)); -debug(escapeHTML(serializer.serializeToString(svgEl))); +span.innerHTML = escapeHTML(serializer.serializeToString(svgEl)); +assert_equals(span.textContent, "<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"><image xlink:href=\"blah\"/></svg>"); document.body.removeChild(svgEl); +done(); </script>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-special-namespaces-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-special-namespaces-expected.txt deleted file mode 100644 index 2ff9fa4..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-special-namespaces-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -Tests the serialization of special XML namespaces on attributes, as reported in bug 395950. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS xmlDocument.querySelector("inner1").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr") is "value" -PASS xmlDocument.querySelector("inner2").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr") is "value" -PASS xmlDocument.querySelector("inner2").getAttribute("xml:attr") is "value" -PASS parsedDoc.querySelector("inner1").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr") is "value" -PASS parsedDoc.querySelector("inner2").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr") is "value" -PASS parsedDoc.querySelector("inner2").getAttribute("xml:attr") is "value" -PASS xmlString.indexOf("xmlns:xml") is -1 -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-special-namespaces.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-special-namespaces.html index f4fe193..0256c490 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-special-namespaces.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-attribute-special-namespaces.html
@@ -1,8 +1,8 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> +<title>Tests the serialization of special XML namespaces on attributes, as reported in http://crbug.com/395950, bug 395950</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <script> -description('Tests the serialization of special XML namespaces on attributes, as reported in <a href="http://crbug.com/395950">bug 395950</a>.'); - var xmlDocument = (new DOMParser()).parseFromString('<outer />', 'text/xml'); var inner1 = xmlDocument.createElementNS(null, 'inner1'); @@ -16,18 +16,19 @@ xmlDocument.firstChild.appendChild(inner2); // Check the DOM construction. -shouldBeEqualToString('xmlDocument.querySelector("inner1").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr")', 'value'); -shouldBeEqualToString('xmlDocument.querySelector("inner2").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr")', 'value'); -shouldBeEqualToString('xmlDocument.querySelector("inner2").getAttribute("xml:attr")', 'value'); +assert_equals(xmlDocument.querySelector("inner1").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr"), 'value'); +assert_equals(xmlDocument.querySelector("inner2").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr"), 'value'); +assert_equals(xmlDocument.querySelector("inner2").getAttribute("xml:attr"), 'value'); var xmlString = (new XMLSerializer()).serializeToString(xmlDocument); // Check the serialization result. var parsedDoc = (new DOMParser()).parseFromString(xmlString, 'text/xml'); -shouldBeEqualToString('parsedDoc.querySelector("inner1").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr")', 'value'); -shouldBeEqualToString('parsedDoc.querySelector("inner2").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr")', 'value'); -shouldBeEqualToString('parsedDoc.querySelector("inner2").getAttribute("xml:attr")', 'value'); +assert_equals(parsedDoc.querySelector("inner1").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr"), 'value'); +assert_equals(parsedDoc.querySelector("inner2").getAttributeNS("http://www.w3.org/XML/1998/namespace", "attr"), 'value'); +assert_equals(parsedDoc.querySelector("inner2").getAttribute("xml:attr"), 'value'); // Check that the correct xmlns definitions were emitted. -shouldBeEqualToNumber('xmlString.indexOf("xmlns:xml")', -1); +assert_equals(xmlString.indexOf("xmlns:xml"), -1); +done(); </script>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype-expected.txt deleted file mode 100644 index 79cc065..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype-expected.txt +++ /dev/null
@@ -1,2 +0,0 @@ -This tests XMLSerializer.serializeToString() on a DocumentType node that has a document associated with it. -PASS: the DocumentType node has been successfully serialize to "<!DOCTYPE aDocTypeName PUBLIC "aPublicID" "aSystemID">".
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype.html index c4e984b..134631f 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype.html
@@ -1,33 +1,19 @@ <html> <head> + <script src="../../resources/testharness.js"></script> + <script src="../../resources/testharnessreport.js"></script> <script> - function debug(str) { - li = document.createElement('li'); - li.appendChild(document.createTextNode(str)); - document.getElementById('console').appendChild(li); - } - - function runTests() { - if (window.testRunner) { - testRunner.dumpAsText(); - } - + test(() => { var docType = window.document.implementation.createDocumentType("aDocTypeName", "aPublicID", "aSystemID"); var doc = window.document.implementation.createDocument("", "", docType); var serializer = new XMLSerializer(); var result = serializer.serializeToString(docType); - if (result == '<!DOCTYPE aDocTypeName PUBLIC "aPublicID" "aSystemID">') - debug('PASS: the DocumentType node has been successfully serialize to "' + result + '".'); - else - debug('FAIL: the DocumentType node has not been successfully serialized.'); - } + assert_equals(result, '<!DOCTYPE aDocTypeName PUBLIC "aPublicID" "aSystemID">', 'The DocumentType node should serialize to "' + result + '"'); + }, "This tests XMLSerializer.serializeToString() on a DocumentType node that has a document associated with it"); </script> </head> -<body onload="runTests()"> -This tests XMLSerializer.serializeToString() on a DocumentType node that has a document associated with it. -<ul id="console"> -</ul> +<body> </body> </html>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype2-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype2-expected.txt deleted file mode 100644 index c0c51298..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype2-expected.txt +++ /dev/null
@@ -1,14 +0,0 @@ -This tests XMLSerializer.serializeToString() on a newly created DocumentType node does not throw since the node has an associated document. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS text = serializer.serializeToString(docType) did not throw exception. -PASS text is "<!DOCTYPE aDocTypeName PUBLIC \"aPublicID\" \"aSystemID\">" -PASS successfullyParsed is true - -TEST COMPLETE - -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype2.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype2.html index 749a03a..4b0f6d8 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype2.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-doctype2.html
@@ -1,18 +1,22 @@ <html> <head> -<script src="../../resources/js-test.js"></script> +<title>This tests XMLSerializer.serializeToString() on a newly created DocumentType node does not throw since the node has an associated document</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> </head> <body> <script> -description("This tests XMLSerializer.serializeToString() on a newly created DocumentType node does not throw since the node has an associated document."); - var docType = window.document.implementation.createDocumentType("aDocTypeName", "aPublicID", "aSystemID"); var serializer = new XMLSerializer(); var text; -shouldNotThrow("text = serializer.serializeToString(docType)"); -shouldBeEqualToString("text", "<!DOCTYPE aDocTypeName PUBLIC \"aPublicID\" \"aSystemID\">"); +try { + text = serializer.serializeToString(docType); +} catch (e) { + assert_unreached('Should not throw exception'); +} +assert_equals(text, "<!DOCTYPE aDocTypeName PUBLIC \"aPublicID\" \"aSystemID\">"); +done(); </script> -<script src="../../resources/js-test.js"></script> </body> </html>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-double-xmlns-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-double-xmlns-expected.txt deleted file mode 100644 index 369445d..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-double-xmlns-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -Checks that attributes created setAttributeNS() don't cause two identical xmlns attributes to be serialized - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS doc.documentElement.getAttributeNS("http://www.example.com", "attr") is "value" -PASS parsedDoc.documentElement.getAttributeNS("http://www.example.com", "attr") is "value" -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-double-xmlns.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-double-xmlns.html index b15fb1b..f15bd7a 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-double-xmlns.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-double-xmlns.html
@@ -1,17 +1,19 @@ <!DOCTYPE html> -<script src="../../resources/js-test.js"></script> +<title>Checks that attributes created setAttributeNS() don't cause two identical xmlns attributes to be serialized</title> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> <script> -description("Checks that attributes created setAttributeNS() don't cause two identical xmlns attributes to be serialized"); window.doc = (new DOMParser()).parseFromString('<test/>', 'text/xml'); doc.documentElement.setAttributeNS('http://www.example.com', 'ns:attr', 'value'); doc.documentElement.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:ns', 'http://www.example.com'); // Check the DOM construction. -shouldBe('doc.documentElement.getAttributeNS("http://www.example.com", "attr")', '"value"'); +assert_equals(doc.documentElement.getAttributeNS("http://www.example.com", "attr"), "value"); window.xmlText = (new XMLSerializer()).serializeToString(doc); // exported for debugging window.parsedDoc = (new DOMParser()).parseFromString(xmlText, 'text/xml'); // Check the serialization result. -shouldBe('parsedDoc.documentElement.getAttributeNS("http://www.example.com", "attr")', '"value"'); +assert_equals(parsedDoc.documentElement.getAttributeNS("http://www.example.com", "attr"), "value"); +done(); </script>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-entities-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-entities-expected.txt deleted file mode 100644 index 4d19c89..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-entities-expected.txt +++ /dev/null
@@ -1 +0,0 @@ -<html xmlns="http://www.w3.org/1999/xhtml"><p>(0 < 1 && 1 > 0)</p><script>if (0 < 1 && 1 > 0) { };</script><style>/* < > & */</style></html>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-entities.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-entities.html index dd1ad68..db82f85 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-entities.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-entities.html
@@ -1,11 +1,9 @@ <html> <head> + <script src="../../resources/testharness.js"></script> + <script src="../../resources/testharnessreport.js"></script> <script type="text/javascript"> - function runTest() - { - if (window.testRunner) - testRunner.dumpAsText(); - + test(() => { var ns = 'http://www.w3.org/1999/xhtml'; var xhtml = document.implementation.createDocument(ns , 'html', null); @@ -24,12 +22,10 @@ var serializer = new XMLSerializer(); var xmlString = serializer.serializeToString(xhtml); - var outputText = document.getElementById("output"); - outputText.textContent = xmlString; - } + assert_equals(xmlString, "<html xmlns=\"http://www.w3.org/1999/xhtml\"><p>(0 < 1 && 1 > 0)</p><script>if (0 < 1 && 1 > 0) { };<\/script><style>/* < > & */</style></html>"); + }, 'XMLSerializer: Serializes entities to XML-compatible format'); </script> </head> - <body onload="runTest()"> - <div id="output"/> + <body> </body> </html>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-serialize-to-string-exception-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-serialize-to-string-exception-expected.txt deleted file mode 100644 index c35e094..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-serialize-to-string-exception-expected.txt +++ /dev/null
@@ -1,66 +0,0 @@ -This tests XMLSerializer.serializeToString() throwing exception when node value is invalid and passing otherwise. - - -1. Verifying XMLSerializer.serializeToString() should THROW exception with no argument -Exception thrown = [TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': 1 argument required, but only 0 present.] -PASS - - -2. Verifying XMLSerializer.serializeToString() should THROW exception with argument null -Exception thrown = [TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.] -PASS - - -3. Verifying XMLSerializer.serializeToString() should THROW exception with argument undefined -Exception thrown = [TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.] -PASS - - -4. Verifying XMLSerializer.serializeToString() should THROW exception with argument <html><title>Hello World</title></html> -Exception thrown = [TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.] -PASS - - -5. Verifying XMLSerializer.serializeToString() should THROW exception with argument [object HTMLCollection] -Exception thrown = [TypeError: Failed to execute 'serializeToString' on 'XMLSerializer': parameter 1 is not of type 'Node'.] -PASS - - -6. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object HTMLDocument] -PASS - - -7. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object HTMLHtmlElement] -PASS - - -8. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object HTMLHtmlElement] -PASS - - -9. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object HTMLDivElement] -PASS - - -10. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object HTMLHeadingElement] -PASS - - -11. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object HTMLUnknownElement] -PASS - - -12. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object HTMLDocument] -PASS - - -13. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object HTMLHtmlElement] -PASS - - -14. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object XMLDocument] -PASS - - -15. Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument [object Element] -PASS
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-serialize-to-string-exception.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-serialize-to-string-exception.html index 4783a0c..ac18ee2 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-serialize-to-string-exception.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-serialize-to-string-exception.html
@@ -11,69 +11,32 @@ font-weight: bold; } </style> +<script src=../../resources/testharness.js></script> +<script src=../../resources/testharnessreport.js></script> +</head> +<body> +<h1 id="heading"/> <script> -if (window.testRunner) - testRunner.dumpAsText(); var count = 0; function shouldThrowException(node) { - document.body.appendChild(document.createElement("br")); - var header = document.createElement("div"); - header.textContent = ++count + ". Verifying XMLSerializer.serializeToString() should THROW exception with " + (arguments.length ? "argument " + node : "no argument"); - document.body.appendChild(header); - var xs = new XMLSerializer(); - try { - var str = xs.serializeToString.apply(xs, arguments); - - var result = document.createElement("div"); - result.className = "failed" - result.textContent = "FAIL"; - document.body.appendChild(result); - } catch (exception) { - var err = "Exception thrown = [" + exception.name + ": " + exception.message + "]"; - var content = document.createElement("div"); - content.textContent = err; - document.body.appendChild(content); - - var result = document.createElement("div"); - result.className = "passed" - result.textContent = "PASS"; - document.body.appendChild(result); - } + assert_throws(new TypeError(), () => { xs.serializeToString.apply(xs, arguments); }, ++count + ". Verifying XMLSerializer.serializeToString() should THROW exception with " + (arguments.length ? "argument " + node : "no argument")); } function shouldNOTThrowException(node) { - document.body.appendChild(document.createElement("br")); - var header = document.createElement("div"); - header.textContent = ++count + ". Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument " + node; - document.body.appendChild(header); - var xs = new XMLSerializer(); + ++count; try { var str = xs.serializeToString(node); - - var result = document.createElement("div"); - result.className = "passed" - result.textContent = "PASS"; - document.body.appendChild(result); } catch (exception) { - var err = "Exception thrown = [" + exception.name + ": " + exception.message + "]"; - var content = document.createElement("div"); - content.textContent = err; - document.body.appendChild(content); - - var result = document.createElement("div"); - result.className = "failed" - result.textContent = "FAIL"; - document.body.appendChild(result); + assert_unreached(count + ". Verifying XMLSerializer.serializeToString() should NOT-THROW exception with argument " + node); } } -function runTest() -{ +test(() => { shouldThrowException(); shouldThrowException(null); shouldThrowException(undefined); @@ -96,11 +59,7 @@ var xmlDoc = domParser.parseFromString("<root/>", "text/xml"); shouldNOTThrowException(xmlDoc); shouldNOTThrowException(xmlDoc.lastChild); -} +}, "This tests XMLSerializer.serializeToString() throwing exception when node value is invalid and passing otherwise"); </script> -</head> -<body onload="runTest();"> -This tests XMLSerializer.serializeToString() throwing exception when node value is invalid and passing otherwise. -<h1 id="heading"/> </body> </html>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-xml-namespace-expected.txt b/third_party/blink/web_tests/dom/domparsing/xmlserializer-xml-namespace-expected.txt deleted file mode 100644 index e1c183d..0000000 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-xml-namespace-expected.txt +++ /dev/null
@@ -1 +0,0 @@ -<div xmlns="http://www.w3.org/1999/xhtml" id="target"> <div id="output"> </div><xml:foo xml:space="preserve"/><xml:bar xml:space="default"/></div>
diff --git a/third_party/blink/web_tests/dom/domparsing/xmlserializer-xml-namespace.html b/third_party/blink/web_tests/dom/domparsing/xmlserializer-xml-namespace.html index 509b7ea..8586c4a 100644 --- a/third_party/blink/web_tests/dom/domparsing/xmlserializer-xml-namespace.html +++ b/third_party/blink/web_tests/dom/domparsing/xmlserializer-xml-namespace.html
@@ -1,11 +1,12 @@ <html xmlns="http://www.w3.org/1999/xhtml"> <head> + <script src=../../resources/testharness.js></script> + <script src=../../resources/testharnessreport.js></script> +</head> +<body> + <div id="target"></div> <script type="text/javascript"> - function runTest() - { - if (window.testRunner) - testRunner.dumpAsText(); - + test(() => { var target = document.getElementById("target"); var xmlns = "http://www.w3.org/XML/1998/namespace"; @@ -23,13 +24,11 @@ var serializer = new XMLSerializer(); var xmlString = serializer.serializeToString(target); - var outputText = document.getElementById("output"); + var outputText = document.createElement('div'); outputText.textContent = xmlString; - } + + assert_equals(outputText.textContent, "<div xmlns=\"http://www.w3.org/1999/xhtml\" id=\"target\"><xml:foo xml:space=\"preserve\"/><xml:bar xml:space=\"default\"/></div>"); + }, 'XMLSerializer with xml namespace'); </script> -</head> - <body onload="runTest()"> - <div id="target"/> - <div id="output"/> - </body> +</body> </html>
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json index df57fe4b..e07cff4 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_5.json
@@ -1837,12 +1837,174 @@ {} ] ], + "css/css-text-decor/text-decoration-line-001-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-001-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-002-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-002-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-003-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-003-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-004-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-004-manual.html", + {} + ] + ], "css/css-text-decor/text-decoration-line-014.xht": [ [ "/css/css-text-decor/text-decoration-line-014.xht", {} ] ], + "css/css-text-decor/text-decoration-line-040-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-040-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-040a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-040a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-041-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-041-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-044-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-044-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-045-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-045-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-046a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-046a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-048-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-048-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-048a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-048a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-049-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-049-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-082-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-082-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-085-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-085-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-090-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-090-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-090a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-090a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-091-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-091-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-091a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-091a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-092-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-092-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-092a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-092a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-095-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-095-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-095a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-095a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-096-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-096-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-096a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-096a-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-097-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-097-manual.html", + {} + ] + ], + "css/css-text-decor/text-decoration-line-097a-manual.html": [ + [ + "/css/css-text-decor/text-decoration-line-097a-manual.html", + {} + ] + ], "css/css-text/text-transform/text-transform-copy-paste-001-manual.html": [ [ "/css/css-text/text-transform/text-transform-copy-paste-001-manual.html", @@ -64115,6 +64277,30 @@ {} ] ], + "css/css-text/line-breaking/line-breaking-013.html": [ + [ + "/css/css-text/line-breaking/line-breaking-013.html", + [ + [ + "/css/css-text/line-breaking/reference/line-breaking-013-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-text/line-breaking/line-breaking-014.html": [ + [ + "/css/css-text/line-breaking/line-breaking-014.html", + [ + [ + "/css/css-text/line-breaking/reference/line-breaking-013-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-text/line-breaking/line-breaking-ic-001.html": [ [ "/css/css-text/line-breaking/line-breaking-ic-001.html", @@ -146700,6 +146886,11 @@ {} ] ], + "css/css-text/line-breaking/reference/line-breaking-013-ref.html": [ + [ + {} + ] + ], "css/css-text/line-breaking/reference/line-breaking-ic-001-ref.html": [ [ {} @@ -219990,6 +220181,12 @@ {} ] ], + "css/css-contain/contain-size-multicol-as-flex-item.html": [ + [ + "/css/css-contain/contain-size-multicol-as-flex-item.html", + {} + ] + ], "css/css-contain/inheritance.html": [ [ "/css/css-contain/inheritance.html", @@ -349800,6 +349997,10 @@ "81465c02d6114aa4a27637b2e77b3d62161c0864", "reftest" ], + "css/css-contain/contain-size-multicol-as-flex-item.html": [ + "19aa12262f9a7dc35f3682b1f7baa3c12949a906", + "testharness" + ], "css/css-contain/contain-size-replaced-001.html": [ "b0dba02f1cd56f4fccc772cfb948dbabb1d600e2", "reftest" @@ -373788,6 +373989,22 @@ "fd5bc5da3a800a7f7e97211e8cb2438bfdc0c462", "reftest" ], + "css/css-text-decor/text-decoration-line-001-manual.html": [ + "76a8f5401494b508b14fc5cc19f07108f53b12a1", + "manual" + ], + "css/css-text-decor/text-decoration-line-002-manual.html": [ + "0e41fd1fcfe713c4b63f7c3d8ed34ea6aee1fe71", + "manual" + ], + "css/css-text-decor/text-decoration-line-003-manual.html": [ + "2e94e8e946b553c02e9c09460723afdc93e741dc", + "manual" + ], + "css/css-text-decor/text-decoration-line-004-manual.html": [ + "5c6da02d1e0e3aa097120a2da527139e9cfdbe3b", + "manual" + ], "css/css-text-decor/text-decoration-line-010.xht": [ "f4b16e32aa185d204c1793f9ca1b0eda502c60fd", "reftest" @@ -373808,6 +374025,98 @@ "7d5f0570b324b81761a1b5dfdc24e3bcc5b66869", "manual" ], + "css/css-text-decor/text-decoration-line-040-manual.html": [ + "c93f4b99084a9c8f54dee6130493c3cc631b434a", + "manual" + ], + "css/css-text-decor/text-decoration-line-040a-manual.html": [ + "5020a1fd118ea0e8bd81994c4e38449b2b33826a", + "manual" + ], + "css/css-text-decor/text-decoration-line-041-manual.html": [ + "7c7c920e990688518acab7aeb054ef713d36f36e", + "manual" + ], + "css/css-text-decor/text-decoration-line-044-manual.html": [ + "2d9048d3d1d5e5a5d97ea3127ae08f38054f9b1e", + "manual" + ], + "css/css-text-decor/text-decoration-line-045-manual.html": [ + "b9d688387569958283f24c3811cd97d8210a48bb", + "manual" + ], + "css/css-text-decor/text-decoration-line-046a-manual.html": [ + "67f2b89ea23576cf51a8654859f5d9d47a8215fc", + "manual" + ], + "css/css-text-decor/text-decoration-line-048-manual.html": [ + "f3a6e137e2d7ae5bc9ab3e930392a7c347661cd5", + "manual" + ], + "css/css-text-decor/text-decoration-line-048a-manual.html": [ + "9bd48defaf03432a5e0acddd4d68aa81a7ea20c4", + "manual" + ], + "css/css-text-decor/text-decoration-line-049-manual.html": [ + "31f9aa762183f604bbdb5964b79052084a1c7f40", + "manual" + ], + "css/css-text-decor/text-decoration-line-082-manual.html": [ + "c4425f90729ca688bd38283a8e5dc1ea42806e49", + "manual" + ], + "css/css-text-decor/text-decoration-line-085-manual.html": [ + "88a5fc02a048dfc12aa981938379c50c59675570", + "manual" + ], + "css/css-text-decor/text-decoration-line-090-manual.html": [ + "f4484c0ee282bb8bdcfc5130a7275a3878fe2cbc", + "manual" + ], + "css/css-text-decor/text-decoration-line-090a-manual.html": [ + "e98688521ffcc4508befe9b9dc019339d6f9c08b", + "manual" + ], + "css/css-text-decor/text-decoration-line-091-manual.html": [ + "94405c0362bc231c2092401fbd066d291a63fed9", + "manual" + ], + "css/css-text-decor/text-decoration-line-091a-manual.html": [ + "e1ba036c257eb4bc4670c3856f86381146641cf0", + "manual" + ], + "css/css-text-decor/text-decoration-line-092-manual.html": [ + "4dffcf6a00efffdfdb042f28cb5994be029fbf00", + "manual" + ], + "css/css-text-decor/text-decoration-line-092a-manual.html": [ + "7f803a35f1603795a6709ee052cd9e544dfabd3d", + "manual" + ], + "css/css-text-decor/text-decoration-line-095-manual.html": [ + "62ca5d1a19e40dfa59fadf8353629686de0894d1", + "manual" + ], + "css/css-text-decor/text-decoration-line-095a-manual.html": [ + "f5bab19374f94fe60c07f7742222ec27180d5881", + "manual" + ], + "css/css-text-decor/text-decoration-line-096-manual.html": [ + "01eaf87875b47897164e7407c01aba59024f7e19", + "manual" + ], + "css/css-text-decor/text-decoration-line-096a-manual.html": [ + "233006c904ebc8568ca18547f48749315847727a", + "manual" + ], + "css/css-text-decor/text-decoration-line-097-manual.html": [ + "9502b2367aca0bae91d2cac7ace69a2dfcd8e96d", + "manual" + ], + "css/css-text-decor/text-decoration-line-097a-manual.html": [ + "e037e15d73c445a72bd81e5fd4971c9e17eba456", + "manual" + ], "css/css-text-decor/text-decoration-line-recalc.html": [ "321aea9f3d93f31685878a14bfc67f9c3e9cf63e", "reftest" @@ -376416,6 +376725,14 @@ "08f956c9166df4770cdd1d2d60aac9c8acd675d2", "reftest" ], + "css/css-text/line-breaking/line-breaking-013.html": [ + "448a41d88f1ff099866f1597edec3ebf5128ecb6", + "reftest" + ], + "css/css-text/line-breaking/line-breaking-014.html": [ + "ea9956362beecb2da890dbef24362a6e9a8be905", + "reftest" + ], "css/css-text/line-breaking/line-breaking-ic-001.html": [ "6cfe6f86a452c19eae31a076710f02dfc8c4ec4e", "reftest" @@ -376436,6 +376753,10 @@ "463dc2287ea251750e0c542873011c9c8707dd30", "support" ], + "css/css-text/line-breaking/reference/line-breaking-013-ref.html": [ + "816015adeab54895037530b8e4d410f81082931f", + "support" + ], "css/css-text/line-breaking/reference/line-breaking-ic-001-ref.html": [ "421002818f6d5f9837c5de3967a1c3d7b441244f", "support" @@ -407313,7 +407634,7 @@ "testharness" ], "dom/events/Event-dispatch-on-disabled-elements.html": [ - "72e63c4d1e97f1113dd7db357921fd1b0ab9372b", + "361006a7240496e9be747faca5056fe2a62a2cff", "testharness" ], "dom/events/Event-dispatch-order.html": [ @@ -437305,7 +437626,7 @@ "support" ], "interfaces/wake-lock.idl": [ - "202dc6b09f7e6aa56289b62bb810ed0fb2e289d0", + "4c11b695f49986e7e9852348f21fe9bd5e68d185", "support" ], "interfaces/wasm-js-api.idl": [ @@ -437361,7 +437682,7 @@ "support" ], "interfaces/webrtc-stats.idl": [ - "0992b341e1fe3cede699c09eeb5838bd1e7a3999", + "d9d20191ad851f4b6d85cd09e8a53b8697bc840e", "support" ], "interfaces/webrtc.idl": [ @@ -437377,7 +437698,7 @@ "support" ], "interfaces/webxr.idl": [ - "8a3264073e8268282c3db6a891b860d57bfcdb28", + "4c74fdac384299ed22a9b9244411c3755a8741db", "support" ], "interfaces/worklets.idl": [ @@ -475869,7 +476190,7 @@ "support" ], "wake-lock/idlharness.https.any-expected.txt": [ - "ca88133a56777e7b0c5b4b65741aae208cf0d904", + "3930e1230bde2cf7199b566c5963cbcb12f35bec", "support" ], "wake-lock/idlharness.https.any.js": [ @@ -475877,7 +476198,7 @@ "testharness" ], "wake-lock/idlharness.https.any.worker-expected.txt": [ - "78381b7e21fc484f22d9c055ab9341356f856601", + "a17dfea9f40571d8a150f1bf9dd2fa492691d469", "support" ], "wake-lock/wakelock-applicability-manual.https-expected.txt": [ @@ -485077,7 +485398,7 @@ "support" ], "webxr/idlharness.https.window-expected.txt": [ - "a00bc3610a5f316dd8cf94aa659d28b471ee09a1", + "93f6ab5a8da7b4a9740101195dae3fc8c158911a", "support" ], "webxr/idlharness.https.window.js": [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-001-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-001-manual.html new file mode 100644 index 0000000..76a8f5401 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-001-manual.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline</title> +<meta name="assert" content="text-decoration-line:underline; there is a line at or under the alphabetic baseline"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline; +} +</style> +</head> +<body> +<p class="instructions">Test passes if there is a line at or under the alphabetic baseline.</p> +<div id="htmlsrc"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-002-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-002-manual.html new file mode 100644 index 0000000..0e41fd1f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-002-manual.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line overline</title> +<meta name="assert" content="text-decoration-line:overline; there is an overline"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is an overline.</p> +<div id="htmlsrc"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-003-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-003-manual.html new file mode 100644 index 0000000..2e94e8e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-003-manual.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line line-through</title> +<meta name="assert" content="text-decoration-line:line-through; there is a solid line through the centre of the characters"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:line-through; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a solid line through the centre of the characters.</p> +<div id="htmlsrc"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-004-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-004-manual.html new file mode 100644 index 0000000..5c6da02d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-004-manual.html
@@ -0,0 +1,32 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline overline</title> +<meta name="assert" content="text-decoration-line:underline overline; there is an overline and an underline"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is an overline and an underline.</p> +<div id="htmlsrc"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-040-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-040-manual.html new file mode 100644 index 0000000..c93f4b99 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-040-manual.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline tbrl hor scripts</title> +<meta name="assert" content="text-decoration-line:underline; there is a line to the LEFT of the characters for horizontal scripts set vertically using writing-mode: vertical-rl"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +:lang(mn) { font-family: "Mongolian Baiti", "Noto sans Mongolian", serif; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the LEFT of the characters for all lines.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-rl"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p--> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-040a-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-040a-manual.html new file mode 100644 index 0000000..5020a1f --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-040a-manual.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline tbrl mixed</title> +<meta name="assert" content="text-decoration-line:underline; there is an unbroken line to the LEFT of the characters for each lines"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 3.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +:lang(mn) { font-family: "Mongolian Baiti", "Noto sans Mongolian", serif; } +</style> +<!-- the test --> +<style> +div p { +text-decoration-line:underline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is an unbroken line to the LEFT of the characters for all lines.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-rl"> + +<div> +<p lang="zh">引发<span lang="en">quick brown fox</span>网络<span lang="ar">جهانی سازیم</span>的全<span lang="my">အပြည်ပြည်</span>部潜<span lang="th">ปิ้งอยู่ในถ้ำ</span>能引<span lang="bo">འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་</span>發網<span lang="hi">विश्वव्यापी बना रहें हैं絡</span>的全<span lang="ja">部潛能</span></p> +</div> +</div> +</body> +</html> +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-041-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-041-manual.html new file mode 100644 index 0000000..7c7c920e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-041-manual.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline tbrl (zh)</title> +<meta name="assert" content="text-decoration-line:underline; there is a line to the LEFT of the characters"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the LEFT of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-rl"> + +<div> +<p lang="zh"><span>引发网络的全部潜能引發網絡的全部潛能</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-044-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-044-manual.html new file mode 100644 index 0000000..2d9048d3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-044-manual.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line overline tbrl hor scripts</title> +<meta name="assert" content="text-decoration-line-line:overline; there is a line to the RIGHT of the characters for horizontal scripts set vertically using writing-mode: vertical-rl"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +:lang(mn) { font-family: "Mongolian Baiti", "Noto sans Mongolian", serif; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the RIGHT of the characters for all lines.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-rl"> +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-045-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-045-manual.html new file mode 100644 index 0000000..b9d68838 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-045-manual.html
@@ -0,0 +1,33 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line overline tbrl (zh)</title> +<meta name="assert" content="text-decoration-line-line:overline; there is a line to the RIGHT of the characters"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the RIGHT of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-rl"> +<div> +<p lang="zh"><span>引发网络的全部潜能引發網絡的全部潛能</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-046a-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-046a-manual.html new file mode 100644 index 0000000..67f2b89 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-046a-manual.html
@@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line overline tbrl mixed</title> +<meta name="assert" content="text-decoration-line-line:overline; there is an unbroken line to the RIGHT of the characters for all lines"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 3.5; + } +:lang(mn) { font-family: "Mongolian Baiti", "Noto sans Mongolian", serif; } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div p { +text-decoration-line:overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is an unbroken line to the RIGHT of the characters for each line.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-rl"> + +<div> +<p lang="zh">引发<span lang="en">quick brown fox</span>网络<span lang="ar">جهانی سازیم</span>的全<span lang="my">အပြည်ပြည်</span>部潜<span lang="th">ปิ้งอยู่ในถ้ำ</span>能引<span lang="bo">འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་</span>發網<span lang="hi">विश्वव्यापी बना रहें हैं絡</span>的全<span lang="ja">部潛能</span></p> +</div> +</div> +</body> +</html> +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-048-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-048-manual.html new file mode 100644 index 0000000..f3a6e13 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-048-manual.html
@@ -0,0 +1,35 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line line-through vertical-rl</title> +<meta name="assert" content="text-decoration-line:line-through; there is a solid vertical line through the centre of the characters"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:line-through; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a solid vertical line through the centre of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-rl"> + +<div> +<p lang="zh"><span>引发网络的全部潜能引發網絡的全部潛能</span></p> +<p lang="ja"><span>可能性を最大限に導き出すために</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-048a-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-048a-manual.html new file mode 100644 index 0000000..9bd48def --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-048a-manual.html
@@ -0,0 +1,40 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line line-through vertical-rl hor scripts</title> +<meta name="assert" content="text-decoration-line:line-through; there is a solid vertical line through the centre of the characters"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:line-through; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a solid vertical line through the centre of the characters.<br/><span class="hint">Skip the test if the text the text fails for the Chinese line, or is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-rl"> + +<div> +<p lang="zh"><span>引发网络的全部潜能引發網絡的全部潛能</span></p> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-049-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-049-manual.html new file mode 100644 index 0000000..31f9aa7 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-049-manual.html
@@ -0,0 +1,41 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line vertical-rl over+under</title> +<meta name="assert" content="text-decoration-line:underline overline; there is a vertical line on both sides of the characters"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +:lang(mn) { font-family: "Mongolian Baiti", "Noto sans Mongolian", serif; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a vertical line on both sides of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-rl"> +<div> +<p lang="zh"><span>引发网络的全部潜能引發網絡的全部潛能</span></p> +<p lang="ja"><span>可能性を最大限に導き出すために</span></p> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-082-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-082-manual.html new file mode 100644 index 0000000..c4425f9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-082-manual.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline overline tblr</title> +<meta name="assert" content="text-decoration-line:underline overline; there is a line on both sides of the characters"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +:lang(mn) { font-family: "Mongolian Baiti", "Noto sans Mongolian", serif; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line on both sides of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-lr"> +<div> +<p lang="mn"><span>ᠣᠯᠠᠨ ᠦᠨᠳᠦᠰᠦᠲᠡᠨ ᠦ ᠪᠣᠯᠭᠠᠬᠤ ᠦᠢᠯᠡ ᠠᠵᠢᠯᠯᠠᠭᠠ</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-085-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-085-manual.html new file mode 100644 index 0000000..88a5fc02 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-085-manual.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line line-through tblr</title> +<meta name="assert" content="text-decoration-line:line-through; there is a solid vertical line through the centre of the characters."> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +:lang(mn) { font-family: "Mongolian Baiti", "Noto sans Mongolian", serif; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:line-through; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a solid vertical line through the centre of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:vertical-lr"> +<div> +<p lang="mn"><span>ᠣᠯᠠᠨ ᠦᠨᠳᠦᠰᠦᠲᠡᠨ ᠦ ᠪᠣᠯᠭᠠᠬᠤ ᠦᠢᠯᠡ ᠠᠵᠢᠯᠯᠠᠭᠠ</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-090-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-090-manual.html new file mode 100644 index 0000000..f4484c0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-090-manual.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline sideways-rl</title> +<meta name="assert" content="text-decoration-line:underline; there is a line to the LEFT of the characters for horizontal scripts set vertically using writing-mode: sideways-rl"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the LEFT of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-rl"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-090a-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-090a-manual.html new file mode 100644 index 0000000..e986885 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-090a-manual.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline sideways-rl non-Latin</title> +<meta name="assert" content="text-decoration-line:underline; there is a line to the LEFT of the characters for horizontal scripts set vertically using writing-mode: sideways-rl"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the LEFT of the characters for all lines.<br/><span class="hint">Skip the test if it fails for the English text, or if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-rl"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p--> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-091-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-091-manual.html new file mode 100644 index 0000000..94405c03 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-091-manual.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line overline sideways-rl</title> +<meta name="assert" content="text-decoration-line:overline; there is a line to the RIGHT of the characters for horizontal scripts set vertically using writing-mode: sideways-rl"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the RIGHT of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-rl"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-091a-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-091a-manual.html new file mode 100644 index 0000000..e1ba036 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-091a-manual.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line overline sideways-rl non-Latin</title> +<meta name="assert" content="text-decoration-line:overline; there is a line to the RIGHT of the characters for horizontal scripts set vertically using writing-mode: sideways-rl"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the RIGHT of the characters for all lines.<br/><span class="hint">Skip the test if it fails for the English sentence, or if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-rl"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p--> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-092-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-092-manual.html new file mode 100644 index 0000000..4dffcf6 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-092-manual.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line line-through sideways-rl</title> +<meta name="assert" content="text-decoration-line:line-through; there is a line through the CENTRE of the characters for horizontal scripts set vertically using writing-mode: sideways-rl"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:line-through; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line through the CENTRE of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-rl"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-092a-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-092a-manual.html new file mode 100644 index 0000000..7f803a35 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-092a-manual.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line line-through sideways-rl non-Latin</title> +<meta name="assert" content="text-decoration-line:line-through; there is a line through the CENTRE of the characters for horizontal scripts set vertically using writing-mode: sideways-rl"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:line-through; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line through the CENTRE of the characters for all lines.<br/><span class="hint">Skip the test if it fails for the English sentence, or if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-rl"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p--> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-095-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-095-manual.html new file mode 100644 index 0000000..62ca5d1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-095-manual.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline sideways-lr</title> +<meta name="assert" content="text-decoration-line:underline; there is a line to the LEFT of the characters for horizontal scripts set vertically using writing-mode: sideways-rl"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the RIGHT of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-lr"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-095a-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-095a-manual.html new file mode 100644 index 0000000..f5bab19 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-095a-manual.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line underline sideways-lr non-Latin</title> +<meta name="assert" content="text-decoration-line:underline; there is a line to the RIGHT of the characters for horizontal scripts set vertically using writing-mode: sideways-lr"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:underline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the RIGHT of the characters for all lines.<br/><span class="hint">Skip the test if it fails for the English sentence, or if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-lr"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p--> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-096-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-096-manual.html new file mode 100644 index 0000000..01eaf87 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-096-manual.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line overline sideways-lr</title> +<meta name="assert" content="text-decoration-line:overline; there is a line to the LEFT of the characters for horizontal scripts set vertically using writing-mode: sideways-lr"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the LEFT of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-lr"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-096a-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-096a-manual.html new file mode 100644 index 0000000..233006c9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-096a-manual.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line overline sideways-lr non-Latin</title> +<meta name="assert" content="text-decoration-line:overline; there is a line to the LEFT of the characters for horizontal scripts set vertically using writing-mode: sideways-lr"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:overline; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line to the LEFT of the characters for all lines.<br/><span class="hint">Skip the test if it fails for the English sentence, or if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-lr"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p--> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-097-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-097-manual.html new file mode 100644 index 0000000..9502b23 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-097-manual.html
@@ -0,0 +1,34 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line line-through sideways-lr</title> +<meta name="assert" content="text-decoration-line:line-through; there is a line through the CENTRE of the characters for horizontal scripts set vertically using writing-mode: sideways-lr"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:line-through; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line through the CENTRE of the characters.<br/><span class="hint">Skip the test if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-lr"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-097a-manual.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-097a-manual.html new file mode 100644 index 0000000..e037e15 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-decoration-line-097a-manual.html
@@ -0,0 +1,39 @@ +<!DOCTYPE html> +<html> +<head> +<meta charset="utf-8"> +<title>text-decoration-line line-through sideways-lr non-Latin</title> +<meta name="assert" content="text-decoration-line:line-through; there is a line through the CENTRE of the characters for horizontal scripts set vertically using writing-mode: sideways-lr"> +<link rel="author" title="Richard Ishida" href="mailto:ishida@w3.org"> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-3/#line-decoration"> +<!-- cosmetic styling --> +<style> +#htmlsrc { margin: 2em; } +#htmlsrc p { + font-size: 28px; + border-radius: 5px; + line-height: 1.5; + } +.hint { color: brown; font-family: sans-serif; font-size: 90%; } +.hint:before { content: '❗ '; } +</style> +<!-- the test --> +<style> +div span { +text-decoration-line:line-through; +}</style> +</head> +<body> +<p class="instructions">Test passes if there is a line through the CENTRE of the characters for all lines.<br/><span class="hint">Skip the test if it fails for the English sentence, or if the text is not vertical.</span></p> +<div id="htmlsrc" style="writing-mode:sideways-lr"> + +<div> +<p lang="en"><span>The quick brown fox jumps over the lazy dog.</span></p> +<p lang="ar"><span>وب جهانی را بهدرستی جهانی سازیم!</span></p> +<p lang="my"><span>အပြည်ပြည်ဆိုင်ရာလှုပ်ရှားမှု၊</span></p> +<p lang="th"><span>กูกินกุ้งปิ้งอยู่ในถ้ำ กูกินกุ้งปิ้งอยู่ในถ้ำ</span></p> +<p lang="bo"><span>འཛམ་གླིང་ཡོངས་འབྲེལ་འདི་ ངོ་མ་འབད་རང་ འཛམ་གླིང་ཡོངས་ལུ་ཁྱབ་ཚུགསཔ་བཟོ་བ།</span></p> +<p lang="hi"><span>वर्ल्ड वाईड वेब को सचमुच विश्वव्यापी बना रहें हैं !</span></p--> +</div> </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/line-breaking/line-breaking-013.html b/third_party/blink/web_tests/external/wpt/css/css-text/line-breaking/line-breaking-013.html new file mode 100644 index 0000000..448a41d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/line-breaking/line-breaking-013.html
@@ -0,0 +1,60 @@ +<!doctype html> +<html> +<meta charset="utf-8"> +<title>CSS Text — line breaking of emoji sequences that should form single clusters</title> +<meta name=assert content="A UA must use the extended grapheme cluster (not legacy grapheme cluster), as defined in [UAX29], as the basis for its typographic character unit."> +<link rel=help href="https://www.w3.org/TR/css-text-3/#characters"> +<link rel=match href="reference/line-breaking-013-ref.html"> +<link rel=author title="Jonathan Kew" href="mailto:jkew@mozilla.com"> +<style> +div { + line-height: 1em; + font-size: 30px; +} +.container { + position: relative; + margin: .5em; +} +.ref { + background-color: white; + padding: .25em; +} +.test { + color: transparent; + background-color: red; + position: absolute; + width: .5em; + left: 0; + top: 0; + padding: .25em; + z-index: -1; +} +</style> +<body> + <p>Each emoji should appear on a single line with no red background.</p> + <div class=container> + <div class=ref>👨‍💻</div><!-- man technologist --> + <div class=test>👨‍💻</div> + </div> + <div class=container> + <div class=ref>👩‍👧‍👦</div><!-- family with mother, son and daughter --> + <div class=test>👩‍👧‍👦</div> + </div> + <div class=container> + <div class=ref>🤹‍♀️</div><!-- woman juggling --> + <div class=test>🤹‍♀️</div> + </div> + <div class=container> + <div class=ref>⛹🏿‍♀️</div><!-- woman basketball player (fitzpatrick type 6) --> + <div class=test>⛹🏿‍♀️</div> + </div> + <div class=container> + <div class=ref>🏳️‍🌈</div><!-- rainbow flag --> + <div class=test>🏳️‍🌈</div> + </div> + <div class=container> + <div class=ref>🏴󠁧󠁢󠁷󠁬󠁳󠁿</div><!-- flag of Wales --> + <div class=test>🏴󠁧󠁢󠁷󠁬󠁳󠁿</div> + </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/line-breaking/line-breaking-014.html b/third_party/blink/web_tests/external/wpt/css/css-text/line-breaking/line-breaking-014.html new file mode 100644 index 0000000..ea99563 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/line-breaking/line-breaking-014.html
@@ -0,0 +1,61 @@ +<!doctype html> +<html> +<meta charset="utf-8"> +<title>CSS Text — line breaking (with word-break:break-all) of emoji sequences that should form single clusters</title> +<meta name=assert content="A UA must use the extended grapheme cluster (not legacy grapheme cluster), as defined in [UAX29], as the basis for its typographic character unit."> +<link rel=help href="https://www.w3.org/TR/css-text-3/#characters"> +<link rel=match href="reference/line-breaking-013-ref.html"> +<link rel=author title="Jonathan Kew" href="mailto:jkew@mozilla.com"> +<style> +div { + line-height: 1em; + font-size: 30px; +} +.container { + position: relative; + margin: .5em; +} +.ref { + background-color: white; + padding: .25em; +} +.test { + word-break: break-all; + color: transparent; + background-color: red; + position: absolute; + width: .5em; + left: 0; + top: 0; + padding: .25em; + z-index: -1; +} +</style> +<body> + <p>Each emoji should appear on a single line with no red background.</p> + <div class=container> + <div class=ref>👨‍💻</div><!-- man technologist --> + <div class=test>👨‍💻</div> + </div> + <div class=container> + <div class=ref>👩‍👧‍👦</div><!-- family with mother, son and daughter --> + <div class=test>👩‍👧‍👦</div> + </div> + <div class=container> + <div class=ref>🤹‍♀️</div><!-- woman juggling --> + <div class=test>🤹‍♀️</div> + </div> + <div class=container> + <div class=ref>⛹🏿‍♀️</div><!-- woman basketball player (fitzpatrick type 6) --> + <div class=test>⛹🏿‍♀️</div> + </div> + <div class=container> + <div class=ref>🏳️‍🌈</div><!-- rainbow flag --> + <div class=test>🏳️‍🌈</div> + </div> + <div class=container> + <div class=ref>🏴󠁧󠁢󠁷󠁬󠁳󠁿</div><!-- flag of Wales --> + <div class=test>🏴󠁧󠁢󠁷󠁬󠁳󠁿</div> + </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text/line-breaking/reference/line-breaking-013-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text/line-breaking/reference/line-breaking-013-ref.html new file mode 100644 index 0000000..816015a --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text/line-breaking/reference/line-breaking-013-ref.html
@@ -0,0 +1,41 @@ +<!doctype html> +<html> +<meta charset="utf-8"> +<title>CSS Text — reference file for emoji sequence line-breaking test</title> +<link rel=author title="Jonathan Kew" href="mailto:jkew@mozilla.com"> +<style> +div { + line-height: 1em; + font-size: 30px; +} +.container { + position: relative; + margin: .5em; +} +.ref { + background-color: white; + padding: .25em; +} +</style> +<body> + <p>Each emoji should appear on a single line with no red background.</p> + <div class=container> + <div class=ref>👨‍💻</div><!-- man technologist --> + </div> + <div class=container> + <div class=ref>👩‍👧‍👦</div><!-- family with mother, son and daughter --> + </div> + <div class=container> + <div class=ref>🤹‍♀️</div><!-- woman juggling --> + </div> + <div class=container> + <div class=ref>⛹🏿‍♀️</div><!-- woman basketball player (fitzpatrick type 6) --> + </div> + <div class=container> + <div class=ref>🏳️‍🌈</div><!-- rainbow flag --> + </div> + <div class=container> + <div class=ref>🏴󠁧󠁢󠁷󠁬󠁳󠁿</div><!-- flag of Wales --> + </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-on-disabled-elements.html b/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-on-disabled-elements.html index 72e63c4..361006a 100644 --- a/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-on-disabled-elements.html +++ b/third_party/blink/web_tests/external/wpt/dom/events/Event-dispatch-on-disabled-elements.html
@@ -165,19 +165,30 @@ const elem = document.createElement(localName); document.body.appendChild(elem); elem.disabled = true; - const eventPromises = [ - "animationstart", - "animationiteration", - "animationend", - ].map(eventType => { - return new Promise(r => { - elem.addEventListener(eventType, r, { once: true }); + const animationStartPromise = new Promise(r => { + elem.addEventListener("animationstart", () => { + // Seek to the second iteration to trigger the animationiteration event + elem.style.animationDelay = "-100s" + r(); }); }); - elem.style.animation = "fade .1s 2"; + const animationIterationPromise = new Promise(r => { + elem.addEventListener("animationiteration", ()=>{ + elem.style.animationDelay = "-200s" + r(); + }); + }); + const animationEndPromise = new Promise(r => { + elem.addEventListener("animationend", r); + }); + elem.style.animation = "fade 100s 2"; elem.classList.add("animate"); // All the events fire... - await Promise.all(eventPromises); + await Promise.all([ + animationStartPromise, + animationIterationPromise, + animationEndPromise, + ]); elem.remove(); } }, "CSS Animation animationstart, animationiteration, animationend fire on disabled form elements");
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl b/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl index 202dc6b0..4c11b69 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/wake-lock.idl
@@ -11,13 +11,19 @@ [Constructor(WakeLockType type), SecureContext, Exposed=(DedicatedWorker,Window)] interface WakeLock : EventTarget { - [Exposed=Window] static Promise<PermissionState> requestPermission(WakeLockType type); readonly attribute WakeLockType type; readonly attribute boolean active; attribute EventHandler onactivechange; Promise<void> request(optional WakeLockRequestOptions options); + static sequence<WakeLock> query(optional WakeLockQueryFilter filter); + [Exposed=Window] static Promise<PermissionState> requestPermission(WakeLockType type); }; dictionary WakeLockRequestOptions { AbortSignal? signal; }; + +dictionary WakeLockQueryFilter { + WakeLockType? type; + boolean? active; +};
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl b/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl index 0992b341..d9d2019 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/webrtc-stats.idl
@@ -102,7 +102,10 @@ DOMString senderId; DOMString remoteId; DOMHighResTimeStamp lastPacketSentTimestamp; + unsigned long long retransmittedPacketsSent; + unsigned long long retransmittedBytesSent; double targetBitrate; + unsigned long long totalEncodedBytesTarget; unsigned long framesEncoded; unsigned long long qpSum; double totalEncodeTime;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl index 8a32640..4c74fdac 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/webxr.idl
@@ -188,6 +188,13 @@ readonly attribute XRTargetRayMode targetRayMode; readonly attribute XRSpace targetRaySpace; readonly attribute XRSpace? gripSpace; + readonly attribute Gamepad? gamepad; +}; + +enum GamepadMappingType { + "", // Defined in the Gamepad API + "standard", // Defined in the Gamepad API + "xr-standard", }; [SecureContext, Exposed=Window] interface XRLayer {}; @@ -254,11 +261,13 @@ interface XRInputSourceEvent : Event { readonly attribute XRFrame frame; readonly attribute XRInputSource inputSource; + readonly attribute long? buttonIndex; }; dictionary XRInputSourceEventInit : EventInit { required XRFrame frame; required XRInputSource inputSource; + long? buttonIndex = null; }; [SecureContext, Exposed=Window, Constructor(DOMString type, XRReferenceSpaceEventInit eventInitDict)]
diff --git a/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json b/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json index 26b8ea2..bf4e2a7 100644 --- a/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json +++ b/third_party/blink/web_tests/external/wpt/url/resources/urltestdata.json
@@ -4633,6 +4633,22 @@ "search": "", "hash": "" }, + "# unknown scheme with non-URL characters in the path", + { + "input": "wow:\uFFFF", + "base": "about:blank", + "href": "wow:%EF%BF%BF", + "origin": "null", + "protocol": "wow:", + "username": "", + "password": "", + "host": "", + "hostname": "", + "port": "", + "pathname": "%EF%BF%BF", + "search": "", + "hash": "" + }, "# Hosts and percent-encoding", { "input": "ftp://example.com%80/",
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt index ca88133a..3930e12 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt +++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any-expected.txt
@@ -6,19 +6,22 @@ PASS WakeLock interface: existence and properties of interface prototype object PASS WakeLock interface: existence and properties of interface prototype object's "constructor" property PASS WakeLock interface: existence and properties of interface prototype object's @@unscopables property -FAIL WakeLock interface: operation requestPermission(WakeLockType) assert_own_property: interface object missing static operation expected property "requestPermission" missing PASS WakeLock interface: attribute type PASS WakeLock interface: attribute active PASS WakeLock interface: attribute onactivechange FAIL WakeLock interface: operation request(WakeLockRequestOptions) assert_own_property: interface prototype object missing non-static operation expected property "request" missing +FAIL WakeLock interface: operation query(WakeLockQueryFilter) assert_own_property: interface object missing static operation expected property "query" missing +FAIL WakeLock interface: operation requestPermission(WakeLockType) assert_own_property: interface object missing static operation expected property "requestPermission" missing FAIL WakeLock must be primary interface of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL Stringification of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" -FAIL WakeLock interface: new WakeLock("screen") must inherit property "requestPermission(WakeLockType)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" -FAIL WakeLock interface: calling requestPermission(WakeLockType) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: new WakeLock("screen") must inherit property "type" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: new WakeLock("screen") must inherit property "active" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: new WakeLock("screen") must inherit property "onactivechange" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: new WakeLock("screen") must inherit property "request(WakeLockRequestOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" FAIL WakeLock interface: calling request(WakeLockRequestOptions) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" +FAIL WakeLock interface: new WakeLock("screen") must inherit property "query(WakeLockQueryFilter)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" +FAIL WakeLock interface: calling query(WakeLockQueryFilter) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" +FAIL WakeLock interface: new WakeLock("screen") must inherit property "requestPermission(WakeLockType)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" +FAIL WakeLock interface: calling requestPermission(WakeLockType) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "TypeError: Illegal constructor" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt index 78381b7..a17dfea9 100644 --- a/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt +++ b/third_party/blink/web_tests/external/wpt/wake-lock/idlharness.https.any.worker-expected.txt
@@ -6,18 +6,21 @@ FAIL WakeLock interface: existence and properties of interface prototype object assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: existence and properties of interface prototype object's "constructor" property assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: existence and properties of interface prototype object's @@unscopables property assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing -FAIL WakeLock interface: member requestPermission Cannot use 'in' operator to search for 'requestPermission' in undefined FAIL WakeLock interface: attribute type assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: attribute active assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: attribute onactivechange assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing FAIL WakeLock interface: operation request(WakeLockRequestOptions) assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing +FAIL WakeLock interface: operation query(WakeLockQueryFilter) assert_own_property: self does not have own property "WakeLock" expected property "WakeLock" missing +FAIL WakeLock interface: member requestPermission Cannot use 'in' operator to search for 'requestPermission' in undefined FAIL WakeLock must be primary interface of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL Stringification of new WakeLock("screen") assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" -FAIL WakeLock interface: new WakeLock("screen") must not have property "requestPermission" assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: new WakeLock("screen") must inherit property "type" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: new WakeLock("screen") must inherit property "active" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: new WakeLock("screen") must inherit property "onactivechange" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: new WakeLock("screen") must inherit property "request(WakeLockRequestOptions)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" FAIL WakeLock interface: calling request(WakeLockRequestOptions) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" +FAIL WakeLock interface: new WakeLock("screen") must inherit property "query(WakeLockQueryFilter)" with the proper type assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" +FAIL WakeLock interface: calling query(WakeLockQueryFilter) on new WakeLock("screen") with too few arguments must throw TypeError assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" +FAIL WakeLock interface: new WakeLock("screen") must not have property "requestPermission" assert_equals: Unexpected exception when evaluating object expected null but got object "ReferenceError: WakeLock is not defined" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt deleted file mode 100644 index 62c3abf..0000000 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded-expected.txt +++ /dev/null
@@ -1,10 +0,0 @@ -This is a testharness.js-based test. -PASS Creating first data channel should fire negotiationneeded event -PASS calling createDataChannel twice should fire negotiationneeded event once -PASS addTransceiver() should fire negotiationneeded event -FAIL Calling addTransceiver() twice should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code -FAIL Calling both addTransceiver() and createDataChannel() should fire negotiationneeded event once assert_unreached: Pending promise should never be resolved. Instead it is fulfilled with: [object Object] Reached unreachable code -PASS negotiationneeded event should not fire if signaling state is not stable -FAIL negotiationneeded event should fire only after signaling state go back to stable assert_false: negotiationneeded should not fire until the next iteration of the event loop after returning to stable expected false got true -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html index f7bf8bd3..336b100 100644 --- a/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html +++ b/third_party/blink/web_tests/external/wpt/webrtc/RTCPeerConnection-onnegotiationneeded.html
@@ -199,10 +199,133 @@ pc.onnegotiationneeded = e => fired = true; pc.createDataChannel('test'); const answer = await generateAnswer(offer); - await pc.setRemoteDescription(answer); + pc.setRemoteDescription(answer); assert_false(fired, "negotiationneeded should not fire until the next iteration of the event loop after returning to stable"); await new Promise(resolve => pc.onnegotiationneeded = resolve); - }, 'negotiationneeded event should fire only after signaling state go back to stable'); + }, 'negotiationneeded event should fire only after signaling state go back to stable after setRemoteDescription'); + + promise_test(async t => { + const callee = new RTCPeerConnection(); + t.add_cleanup(() => callee.close()); + + const caller = new RTCPeerConnection(); + t.add_cleanup(() => caller.close()); + + callee.addTransceiver('audio'); + + const offer = await caller.createOffer(); + let fired = false; + callee.onnegotiationneeded = e => fired = true; + await callee.setRemoteDescription(offer); + callee.createDataChannel('test'); + + const answer = await callee.createAnswer(offer); + callee.setLocalDescription(answer); + assert_false(fired, "negotiationneeded should not fire until the next iteration of the event loop after returning to stable"); + + await new Promise(resolve => callee.onnegotiationneeded = resolve); + }, 'negotiationneeded event should fire only after signaling state go back to stable after setLocalDescription'); + + /* + 5.1. RTCPeerConnection Interface Extensions + + addTrack + 10. Update the negotiation-needed flag for connection. + */ + promise_test(async t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + + const stream = await getNoiseStream({ audio: true }); + t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); + const [track] = stream.getTracks(); + pc.addTrack(track, stream); + + await new Promise(resolve => pc.onnegotiationneeded = resolve); + }, 'addTrack should cause negotiationneeded to fire'); + + /* + 5.1. RTCPeerConnection Interface Extensions + + removeTrack + 12. Update the negotiation-needed flag for connection. + */ + async_test(async t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + + const stream = await getNoiseStream({ audio: true }); + t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); + const [track] = stream.getTracks(); + const sender = pc.addTrack(track, stream); + pc.onnegotiationneeded = t.step_func(async () => { + pc.onnegotiationneeded = t.step_func(async () => { + assert_unreached('onnegotiationneeded misfired'); + }); + const offer = await pc.createOffer(); + await pc.setLocalDescription(offer); + + const answer = await generateAnswer(offer); + await pc.setRemoteDescription(answer); + + pc.removeTrack(sender); + await new Promise(resolve => pc.onnegotiationneeded = resolve) + t.done(); + }); + }, 'removeTrack should cause negotiationneeded to fire on the caller'); + + /* + 5.1. RTCPeerConnection Interface Extensions + + removeTrack + 12. Update the negotiation-needed flag for connection. + */ + async_test(async t => { + const caller = new RTCPeerConnection(); + t.add_cleanup(() => caller.close()); + caller.addTransceiver('audio', {direction:'recvonly'}); + const offer = await caller.createOffer(); + + const callee = new RTCPeerConnection(); + t.add_cleanup(() => callee.close()); + + const stream = await getNoiseStream({ audio: true }); + t.add_cleanup(() => stream.getTracks().forEach(track => track.stop())); + const [track] = stream.getTracks(); + const sender = callee.addTrack(track, stream); + + callee.onnegotiationneeded = t.step_func(async () => { + callee.onnegotiationneeded = t.step_func(async () => { + assert_unreached('onnegotiationneeded misfired'); + }); + await callee.setRemoteDescription(offer); + const answer = await callee.createAnswer(offer); + callee.setLocalDescription(answer); + + callee.removeTrack(sender); + await new Promise(resolve => callee.onnegotiationneeded = resolve) + t.done(); + }); + }, 'removeTrack should cause negotiationneeded to fire on the callee'); + + /* + 5.4. RTCRtpTransceiver Interface + + setDirection + 7. Update the negotiation-needed flag for connection. + */ + promise_test(async t => { + const pc = new RTCPeerConnection(); + t.add_cleanup(() => pc.close()); + + const transceiver = pc.addTransceiver('audio', {direction:'sendrecv'}); + const offer = await pc.createOffer(); + await pc.setLocalDescription(offer); + const answer = await generateAnswer(offer); + await pc.setRemoteDescription(answer); + transceiver.direction = 'recvonly'; + await new Promise(resolve => pc.onnegotiationneeded = resolve); + }, 'Updating the direction of the transceiver should cause negotiationneeded to fire'); /* TODO @@ -243,19 +366,8 @@ When the RTCPeerConnection() constructor is invoked 7. Let connection have a [[needNegotiation]] internal slot, initialized to false. - 5.1. RTCPeerConnection Interface Extensions - - addTrack - 10. Update the negotiation-needed flag for connection. - - removeTrack - 12. Update the negotiation-needed flag for connection. - 5.4. RTCRtpTransceiver Interface - setDirection - 7. Update the negotiation-needed flag for connection. - stop 11. Update the negotiation-needed flag for connection.
diff --git a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt index a00bc36..93f6ab5a 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt +++ b/third_party/blink/web_tests/external/wpt/webxr/idlharness.https.window-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 216 tests; 203 PASS, 13 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 218 tests; 203 PASS, 15 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS idl_test setup PASS Partial interface Navigator: original interface defined PASS Partial dictionary WebGLContextAttributes: original dictionary defined @@ -159,6 +159,7 @@ PASS XRInputSource interface: attribute targetRayMode PASS XRInputSource interface: attribute targetRaySpace PASS XRInputSource interface: attribute gripSpace +FAIL XRInputSource interface: attribute gamepad assert_true: The prototype object must have a property "gamepad" expected true got false PASS XRLayer interface: existence and properties of interface object PASS XRLayer interface object length PASS XRLayer interface object name @@ -205,6 +206,7 @@ PASS XRInputSourceEvent interface: existence and properties of interface prototype object's @@unscopables property PASS XRInputSourceEvent interface: attribute frame PASS XRInputSourceEvent interface: attribute inputSource +FAIL XRInputSourceEvent interface: attribute buttonIndex assert_true: The prototype object must have a property "buttonIndex" expected true got false FAIL XRReferenceSpaceEvent interface: existence and properties of interface object assert_own_property: self does not have own property "XRReferenceSpaceEvent" expected property "XRReferenceSpaceEvent" missing FAIL XRReferenceSpaceEvent interface object length assert_own_property: self does not have own property "XRReferenceSpaceEvent" expected property "XRReferenceSpaceEvent" missing FAIL XRReferenceSpaceEvent interface object name assert_own_property: self does not have own property "XRReferenceSpaceEvent" expected property "XRReferenceSpaceEvent" missing
diff --git a/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-AddRemoveStream.html b/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-AddRemoveStream.html index b830577..acc0209 100644 --- a/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-AddRemoveStream.html +++ b/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-AddRemoveStream.html
@@ -17,24 +17,22 @@ assert_false(stream1.id === stream2.id); pc = new RTCPeerConnection(); + testRTC.add_cleanup(() => pc.close()); pc.onnegotiationneeded = (event) => { assert_array_equals(pc.getLocalStreams(), [stream1]); - pc.onnegotiationneeded = () => { + pc.onnegotiationneeded = testRTC.step_func(() => { assert_unreached('onErroneousNegotiationNeeded was called.'); - }; + }); pc.addStream(stream1); assert_equals(pc.getLocalStreams().length, 1); pc.removeStream(stream2); assert_equals(pc.getLocalStreams().length, 1); - pc.onnegotiationneeded = (event) => { - assert_equals(pc.getLocalStreams().length, 0); - testRTC.done(); - }; pc.removeStream(stream1); + setTimeout(() => testRTC.done()); }; pc.addStream(stream1);
diff --git a/third_party/blink/web_tests/paint/dark-mode/native-theme-off/text-input-elements.html b/third_party/blink/web_tests/paint/dark-mode/native-theme-off/text-input-elements.html new file mode 100644 index 0000000..846b0912f --- /dev/null +++ b/third_party/blink/web_tests/paint/dark-mode/native-theme-off/text-input-elements.html
@@ -0,0 +1 @@ +<input style="border-width: thick"><textarea style="border-width: thick"></textarea>
diff --git a/third_party/blink/web_tests/paint/dark-mode/native-theme-on/text-input-elements.html b/third_party/blink/web_tests/paint/dark-mode/native-theme-on/text-input-elements.html new file mode 100644 index 0000000..f2e3d4c --- /dev/null +++ b/third_party/blink/web_tests/paint/dark-mode/native-theme-on/text-input-elements.html
@@ -0,0 +1 @@ +<input><textarea></textarea>
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-expected.txt index 667b500..a9c7a84 100644 --- a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-expected.txt +++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 516 tests; 334 PASS, 182 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 517 tests; 334 PASS, 183 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -360,6 +360,7 @@ PASS Parsing: <sc::a@example.net> against <about:blank> PASS Parsing: <wow:%NBD> against <about:blank> PASS Parsing: <wow:%1G> against <about:blank> +FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" FAIL Parsing: <ftp://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%80/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <ftp://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%A0/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <https://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%80/" but got "https://example.com%EF%BF%BD/"
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-expected.txt index 6a59534..2eff1d990 100644 --- a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-expected.txt +++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 303 tests; 299 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 304 tests; 300 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing origin: <http://example . org> against <http://example.org/foo/bar> @@ -262,6 +262,7 @@ PASS Parsing origin: <sc::a@example.net> against <about:blank> PASS Parsing origin: <wow:%NBD> against <about:blank> PASS Parsing origin: <wow:%1G> against <about:blank> +PASS Parsing origin: <wow:> against <about:blank> PASS Parsing origin: <ftp://%e2%98%83> against <about:blank> PASS Parsing origin: <https://%e2%98%83> against <about:blank> PASS Parsing origin: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-xhtml-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-xhtml-expected.txt index 6a59534..2eff1d990 100644 --- a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-xhtml-expected.txt +++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-origin-xhtml-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 303 tests; 299 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 304 tests; 300 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing origin: <http://example . org> against <http://example.org/foo/bar> @@ -262,6 +262,7 @@ PASS Parsing origin: <sc::a@example.net> against <about:blank> PASS Parsing origin: <wow:%NBD> against <about:blank> PASS Parsing origin: <wow:%1G> against <about:blank> +PASS Parsing origin: <wow:> against <about:blank> PASS Parsing origin: <ftp://%e2%98%83> against <about:blank> PASS Parsing origin: <https://%e2%98%83> against <about:blank> PASS Parsing origin: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml-expected.txt index 667b500..a9c7a84 100644 --- a/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml-expected.txt +++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/a-element-xhtml-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 516 tests; 334 PASS, 182 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 517 tests; 334 PASS, 183 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -360,6 +360,7 @@ PASS Parsing: <sc::a@example.net> against <about:blank> PASS Parsing: <wow:%NBD> against <about:blank> PASS Parsing: <wow:%1G> against <about:blank> +FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" FAIL Parsing: <ftp://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%80/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <ftp://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%A0/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <https://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%80/" but got "https://example.com%EF%BF%BD/"
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor-expected.txt index 4450c6f..1938487b 100644 --- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor-expected.txt +++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-constructor-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 516 tests; 400 PASS, 116 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 517 tests; 400 PASS, 117 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -400,6 +400,7 @@ PASS Parsing: <sc::a@example.net> against <about:blank> PASS Parsing: <wow:%NBD> against <about:blank> PASS Parsing: <wow:%1G> against <about:blank> +FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" PASS Parsing: <ftp://example.com%80/> against <about:blank> PASS Parsing: <ftp://example.com%A0/> against <about:blank> PASS Parsing: <https://example.com%80/> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin-expected.txt b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin-expected.txt index 7880e90..72594ff 100644 --- a/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin-expected.txt +++ b/third_party/blink/web_tests/platform/linux/external/wpt/url/url-origin-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 303 tests; 296 PASS, 7 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 304 tests; 297 PASS, 7 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Origin parsing: <http://example . org> against <http://example.org/foo/bar> @@ -262,6 +262,7 @@ PASS Origin parsing: <sc::a@example.net> against <about:blank> PASS Origin parsing: <wow:%NBD> against <about:blank> PASS Origin parsing: <wow:%1G> against <about:blank> +PASS Origin parsing: <wow:> against <about:blank> PASS Origin parsing: <ftp://%e2%98%83> against <about:blank> PASS Origin parsing: <https://%e2%98%83> against <about:blank> PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-off/text-input-elements-expected.png new file mode 100644 index 0000000..9adc149 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-off/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-on/text-input-elements-expected.png new file mode 100644 index 0000000..8315438 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/paint/dark-mode/native-theme-on/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png new file mode 100644 index 0000000..0e3e22f0 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png new file mode 100644 index 0000000..310a6f2 --- /dev/null +++ b/third_party/blink/web_tests/platform/linux/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-expected.txt index 667b500..a9c7a84 100644 --- a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-expected.txt +++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 516 tests; 334 PASS, 182 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 517 tests; 334 PASS, 183 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -360,6 +360,7 @@ PASS Parsing: <sc::a@example.net> against <about:blank> PASS Parsing: <wow:%NBD> against <about:blank> PASS Parsing: <wow:%1G> against <about:blank> +FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" FAIL Parsing: <ftp://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%80/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <ftp://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%A0/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <https://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%80/" but got "https://example.com%EF%BF%BD/"
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-expected.txt index 6a59534..2eff1d990 100644 --- a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-expected.txt +++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 303 tests; 299 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 304 tests; 300 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing origin: <http://example . org> against <http://example.org/foo/bar> @@ -262,6 +262,7 @@ PASS Parsing origin: <sc::a@example.net> against <about:blank> PASS Parsing origin: <wow:%NBD> against <about:blank> PASS Parsing origin: <wow:%1G> against <about:blank> +PASS Parsing origin: <wow:> against <about:blank> PASS Parsing origin: <ftp://%e2%98%83> against <about:blank> PASS Parsing origin: <https://%e2%98%83> against <about:blank> PASS Parsing origin: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-xhtml-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-xhtml-expected.txt index 6a59534..2eff1d990 100644 --- a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-xhtml-expected.txt +++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-origin-xhtml-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 303 tests; 299 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 304 tests; 300 PASS, 4 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing origin: <http://example . org> against <http://example.org/foo/bar> @@ -262,6 +262,7 @@ PASS Parsing origin: <sc::a@example.net> against <about:blank> PASS Parsing origin: <wow:%NBD> against <about:blank> PASS Parsing origin: <wow:%1G> against <about:blank> +PASS Parsing origin: <wow:> against <about:blank> PASS Parsing origin: <ftp://%e2%98%83> against <about:blank> PASS Parsing origin: <https://%e2%98%83> against <about:blank> PASS Parsing origin: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-xhtml-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-xhtml-expected.txt index 667b500..a9c7a84 100644 --- a/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-xhtml-expected.txt +++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/a-element-xhtml-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 516 tests; 334 PASS, 182 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 517 tests; 334 PASS, 183 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -360,6 +360,7 @@ PASS Parsing: <sc::a@example.net> against <about:blank> PASS Parsing: <wow:%NBD> against <about:blank> PASS Parsing: <wow:%1G> against <about:blank> +FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" FAIL Parsing: <ftp://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%80/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <ftp://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%A0/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <https://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%80/" but got "https://example.com%EF%BF%BD/"
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor-expected.txt index 4450c6f..1938487b 100644 --- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor-expected.txt +++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-constructor-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 516 tests; 400 PASS, 116 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 517 tests; 400 PASS, 117 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -400,6 +400,7 @@ PASS Parsing: <sc::a@example.net> against <about:blank> PASS Parsing: <wow:%NBD> against <about:blank> PASS Parsing: <wow:%1G> against <about:blank> +FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" PASS Parsing: <ftp://example.com%80/> against <about:blank> PASS Parsing: <ftp://example.com%A0/> against <about:blank> PASS Parsing: <https://example.com%80/> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin-expected.txt b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin-expected.txt index 7880e90..72594ff 100644 --- a/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin-expected.txt +++ b/third_party/blink/web_tests/platform/mac/external/wpt/url/url-origin-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 303 tests; 296 PASS, 7 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 304 tests; 297 PASS, 7 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Origin parsing: <http://example . org> against <http://example.org/foo/bar> @@ -262,6 +262,7 @@ PASS Origin parsing: <sc::a@example.net> against <about:blank> PASS Origin parsing: <wow:%NBD> against <about:blank> PASS Origin parsing: <wow:%1G> against <about:blank> +PASS Origin parsing: <wow:> against <about:blank> PASS Origin parsing: <ftp://%e2%98%83> against <about:blank> PASS Origin parsing: <https://%e2%98%83> against <about:blank> PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-off/text-input-elements-expected.png new file mode 100644 index 0000000..0d5bd5a --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-off/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-on/text-input-elements-expected.png new file mode 100644 index 0000000..b71efac --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/paint/dark-mode/native-theme-on/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png new file mode 100644 index 0000000..8dd35947 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png new file mode 100644 index 0000000..80b2276 --- /dev/null +++ b/third_party/blink/web_tests/platform/mac/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-expected.txt index 57dca08..ac76307 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 516 tests; 330 PASS, 186 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 517 tests; 330 PASS, 187 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -360,6 +360,7 @@ PASS Parsing: <sc::a@example.net> against <about:blank> PASS Parsing: <wow:%NBD> against <about:blank> PASS Parsing: <wow:%1G> against <about:blank> +FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" FAIL Parsing: <ftp://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%80/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <ftp://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%A0/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <https://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%80/" but got "https://example.com%EF%BF%BD/"
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-expected.txt index f56cdf4..1955d9f 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 303 tests; 297 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 304 tests; 298 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing origin: <http://example . org> against <http://example.org/foo/bar> @@ -262,6 +262,7 @@ PASS Parsing origin: <sc::a@example.net> against <about:blank> PASS Parsing origin: <wow:%NBD> against <about:blank> PASS Parsing origin: <wow:%1G> against <about:blank> +PASS Parsing origin: <wow:> against <about:blank> PASS Parsing origin: <ftp://%e2%98%83> against <about:blank> PASS Parsing origin: <https://%e2%98%83> against <about:blank> PASS Parsing origin: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-xhtml-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-xhtml-expected.txt index f56cdf4..1955d9f 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-xhtml-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-origin-xhtml-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 303 tests; 297 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 304 tests; 298 PASS, 6 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing origin: <http://example . org> against <http://example.org/foo/bar> @@ -262,6 +262,7 @@ PASS Parsing origin: <sc::a@example.net> against <about:blank> PASS Parsing origin: <wow:%NBD> against <about:blank> PASS Parsing origin: <wow:%1G> against <about:blank> +PASS Parsing origin: <wow:> against <about:blank> PASS Parsing origin: <ftp://%e2%98%83> against <about:blank> PASS Parsing origin: <https://%e2%98%83> against <about:blank> PASS Parsing origin: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml-expected.txt index 57dca08..ac76307 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/a-element-xhtml-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 516 tests; 330 PASS, 186 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 517 tests; 330 PASS, 187 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -360,6 +360,7 @@ PASS Parsing: <sc::a@example.net> against <about:blank> PASS Parsing: <wow:%NBD> against <about:blank> PASS Parsing: <wow:%1G> against <about:blank> +FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" FAIL Parsing: <ftp://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%80/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <ftp://example.com%A0/> against <about:blank> assert_equals: failure should set href to input expected "ftp://example.com%A0/" but got "ftp://example.com%EF%BF%BD/" FAIL Parsing: <https://example.com%80/> against <about:blank> assert_equals: failure should set href to input expected "https://example.com%80/" but got "https://example.com%EF%BF%BD/"
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor-expected.txt index 1d9467c..2aa72cb 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-constructor-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 516 tests; 394 PASS, 122 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 517 tests; 394 PASS, 123 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Parsing: <http://example . org> against <http://example.org/foo/bar> @@ -400,6 +400,7 @@ PASS Parsing: <sc::a@example.net> against <about:blank> PASS Parsing: <wow:%NBD> against <about:blank> PASS Parsing: <wow:%1G> against <about:blank> +FAIL Parsing: <wow:> against <about:blank> assert_equals: href expected "wow:%EF%BF%BF" but got "wow:%EF%BF%BD" PASS Parsing: <ftp://example.com%80/> against <about:blank> PASS Parsing: <ftp://example.com%A0/> against <about:blank> PASS Parsing: <https://example.com%80/> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin-expected.txt b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin-expected.txt index e7b1e0122..616310c9 100644 --- a/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin-expected.txt +++ b/third_party/blink/web_tests/platform/win/external/wpt/url/url-origin-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 303 tests; 294 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 304 tests; 295 PASS, 9 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Loading data… PASS Origin parsing: <http://example . org> against <http://example.org/foo/bar> @@ -262,6 +262,7 @@ PASS Origin parsing: <sc::a@example.net> against <about:blank> PASS Origin parsing: <wow:%NBD> against <about:blank> PASS Origin parsing: <wow:%1G> against <about:blank> +PASS Origin parsing: <wow:> against <about:blank> PASS Origin parsing: <ftp://%e2%98%83> against <about:blank> PASS Origin parsing: <https://%e2%98%83> against <about:blank> PASS Origin parsing: <http://127.0.0.1:10100/relative_import.html> against <about:blank>
diff --git a/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-off/text-input-elements-expected.png new file mode 100644 index 0000000..67a425c --- /dev/null +++ b/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-off/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-on/text-input-elements-expected.png new file mode 100644 index 0000000..c52b4fd --- /dev/null +++ b/third_party/blink/web_tests/platform/win/paint/dark-mode/native-theme-on/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png new file mode 100644 index 0000000..5b4aadf --- /dev/null +++ b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-off/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png new file mode 100644 index 0000000..8257781 --- /dev/null +++ b/third_party/blink/web_tests/platform/win/virtual/dark-mode/paint/dark-mode/native-theme-on/text-input-elements-expected.png Binary files differ
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-off/README.txt b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-off/README.txt new file mode 100644 index 0000000..cb49f2e --- /dev/null +++ b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-off/README.txt
@@ -0,0 +1,3 @@ +# This suite runs the tests in LayoutTests/paint/dark-mode +# with --blink-settings="darkMode=3" +# See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-on/README.txt b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-on/README.txt new file mode 100644 index 0000000..cb49f2e --- /dev/null +++ b/third_party/blink/web_tests/virtual/dark-mode/paint/dark-mode/native-theme-on/README.txt
@@ -0,0 +1,3 @@ +# This suite runs the tests in LayoutTests/paint/dark-mode +# with --blink-settings="darkMode=3" +# See the virtual_test_suites() method in tools/blinkpy/web_tests/port/base.py.
diff --git a/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn b/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn index 3bbb844e..fc92fb5 100644 --- a/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn +++ b/third_party/cacheinvalidation/src/google/cacheinvalidation/BUILD.gn
@@ -23,5 +23,6 @@ ] } - proto_out_dir = "google/cacheinvalidation" + proto_out_dir = "$target_gen_dir/google/cacheinvalidation" + public_include_dirs = [ target_gen_dir ] }
diff --git a/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc b/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc index 4116f5d..8afbe82 100644 --- a/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc +++ b/third_party/libaddressinput/chromium/chrome_address_validator_unittest.cc
@@ -50,6 +50,7 @@ using ::i18n::addressinput::MISSING_REQUIRED_FIELD; using ::i18n::addressinput::UNEXPECTED_FIELD; using ::i18n::addressinput::UNKNOWN_VALUE; +using ::i18n::addressinput::UNSUPPORTED_FIELD; using ::i18n::addressinput::USES_P_O_BOX; // This class should always succeed in getting the rules. @@ -248,55 +249,51 @@ FieldProblemMap problems; EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_TRUE(problems.empty()); + FieldProblemMap expected; + expected.emplace(LOCALITY, UNSUPPORTED_FIELD); + expected.emplace(DEPENDENT_LOCALITY, UNSUPPORTED_FIELD); + EXPECT_EQ(expected, problems); problems.clear(); // An extended, valid Californian zip code. address.postal_code = "90210-1234"; EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_TRUE(problems.empty()); - + EXPECT_EQ(expected, problems); problems.clear(); // New York zip code (which is invalid for California). address.postal_code = "12345"; EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_EQ(1U, problems.size()); - EXPECT_EQ(problems.begin()->first, POSTAL_CODE); - EXPECT_EQ(problems.begin()->second, MISMATCHING_VALUE); - + expected.emplace(POSTAL_CODE, MISMATCHING_VALUE); + EXPECT_EQ(expected, problems); problems.clear(); // A zip code with a "90" in the middle. address.postal_code = "12903"; EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_EQ(1U, problems.size()); - EXPECT_EQ(problems.begin()->first, POSTAL_CODE); - EXPECT_EQ(problems.begin()->second, MISMATCHING_VALUE); - + EXPECT_EQ(expected, problems); problems.clear(); // Invalid zip code (too many digits). address.postal_code = "902911"; EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_EQ(1U, problems.size()); - EXPECT_EQ(problems.begin()->first, POSTAL_CODE); - EXPECT_EQ(problems.begin()->second, INVALID_FORMAT); - + expected.clear(); + expected.emplace(LOCALITY, UNSUPPORTED_FIELD); + expected.emplace(DEPENDENT_LOCALITY, UNSUPPORTED_FIELD); + expected.emplace(POSTAL_CODE, INVALID_FORMAT); + EXPECT_EQ(expected, problems); problems.clear(); // Invalid zip code (too few digits). address.postal_code = "9029"; EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_EQ(1U, problems.size()); - EXPECT_EQ(problems.begin()->first, POSTAL_CODE); - EXPECT_EQ(problems.begin()->second, INVALID_FORMAT); + EXPECT_EQ(expected, problems); } TEST_F(AddressValidatorTest, BasicValidation) { @@ -313,35 +310,39 @@ FieldProblemMap problems; EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_TRUE(problems.empty()); + + FieldProblemMap expected; + expected.emplace(LOCALITY, UNSUPPORTED_FIELD); + expected.emplace(DEPENDENT_LOCALITY, UNSUPPORTED_FIELD); + EXPECT_EQ(expected, problems); // The display name works as well as the key. address.administrative_area = "Texas"; problems.clear(); EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_TRUE(problems.empty()); + EXPECT_EQ(expected, problems); // Ignore capitalization. address.administrative_area = "tx"; problems.clear(); EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_TRUE(problems.empty()); + EXPECT_EQ(expected, problems); // Ignore capitalization. address.administrative_area = "teXas"; problems.clear(); EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_TRUE(problems.empty()); + EXPECT_EQ(expected, problems); // Ignore diacriticals. address.administrative_area = base::WideToUTF8(L"T\u00E9xas"); problems.clear(); EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - EXPECT_TRUE(problems.empty()); + EXPECT_EQ(expected, problems); } TEST_F(AddressValidatorTest, BasicValidationFailure) { @@ -359,9 +360,13 @@ EXPECT_EQ(AddressValidator::SUCCESS, validator_->ValidateAddress(address, NULL, &problems)); - ASSERT_EQ(1U, problems.size()); - EXPECT_EQ(UNKNOWN_VALUE, problems.begin()->second); - EXPECT_EQ(ADMIN_AREA, problems.begin()->first); + ASSERT_EQ(3U, problems.size()); + + FieldProblemMap expected; + expected.emplace(ADMIN_AREA, UNKNOWN_VALUE); + expected.emplace(LOCALITY, UNSUPPORTED_FIELD); + expected.emplace(DEPENDENT_LOCALITY, UNSUPPORTED_FIELD); + EXPECT_EQ(expected, problems); } TEST_F(AddressValidatorTest, NoNullSuggestionsCrash) { @@ -912,7 +917,8 @@ private: // LoadRulesListener implementation. - void OnAddressValidationRulesLoaded(const std::string&, bool success) override { + void OnAddressValidationRulesLoaded(const std::string&, + bool success) override { load_rules_success_ = success; }
diff --git a/third_party/protobuf/proto_library.gni b/third_party/protobuf/proto_library.gni index 5c4ffa01..9798fd68 100644 --- a/third_party/protobuf/proto_library.gni +++ b/third_party/protobuf/proto_library.gni
@@ -16,8 +16,8 @@ # # proto_out_dir (optional) # Specifies the path suffix that output files are generated under. -# This path will be appended to |root_gen_dir|, but for python stubs -# it will be appended to |root_build_dir|/pyproto. +# If a relative path is provided, it be appended to |root_gen_dir|. +# For python stubs it will be appended to |root_build_dir|/pyproto. # # generate_python (optional, default true) # Generate Python protobuf stubs. @@ -98,6 +98,9 @@ # A list of config labels that will be removed from the configs apllying # to the source set. # +# public_include_dirs (optional) +# Add a public config with given include_dirs. +# # Example: # proto_library("mylib") { # sources = [ @@ -107,6 +110,11 @@ import("//build/config/sanitizers/sanitizers.gni") +declare_args() { + # TODO(agrieve): Remove arg after all offenders have been fixed. + allow_proto_library_outside_of_target_gen_dir = true +} + template("proto_library") { assert(defined(invoker.sources), "Need sources for proto_library") proto_sources = invoker.sources @@ -188,22 +196,65 @@ if (defined(invoker.proto_out_dir)) { proto_out_dir = invoker.proto_out_dir - } else { - # Absolute path to the directory of current BUILD.gn file excluding "//". - proto_out_dir = rebase_path(".", "//") - if (proto_in_dir != ".") { - proto_out_dir += "/$proto_in_dir" - } + + # TODO(agrieve): Remove special case once perfetto is updated. + # Note: Other perfetto paths already pass this check because + # get_path_info normalizes "a//b" -> "a/b". + proto_out_dir_is_abs = + proto_out_dir != "//third_party/perfetto/" && + get_path_info(proto_out_dir, "abspath") == proto_out_dir } # We need both absolute path to use in GN statements and a relative one # to pass to external script. if (generate_cc || generate_with_plugin) { - cc_out_dir = "$root_gen_dir/" + proto_out_dir + if (defined(proto_out_dir)) { + if (!proto_out_dir_is_abs) { + proto_out_dir = "$root_gen_dir/$proto_out_dir" + } + + if (!allow_proto_library_outside_of_target_gen_dir) { + # Use sources filter to test the prefix of proto_out_dir. + set_sources_assignment_filter([ + target_gen_dir, + "$target_gen_dir/*", + ]) + sources = [ + proto_out_dir, + ] + set_sources_assignment_filter([]) + if (sources != []) { + # TODO(agrieve): Change this to an assert. + print( + "proto_out_dir must be subdirectory of \$target_gen_dir (https://crbug.com/944928)") + print(" target_gen_dir=$target_gen_dir") + print(" proto_out_dir=$proto_out_dir") + sources = [] + } + } + + cc_out_dir = proto_out_dir + } else { + cc_out_dir = target_gen_dir + if (rebase_path(".", "//") != ".") { + cc_out_dir += "/$proto_in_dir" + } + } rel_cc_out_dir = rebase_path(cc_out_dir, root_build_dir) } if (generate_python) { - py_out_dir = "$root_out_dir/pyproto/" + proto_out_dir + if (defined(proto_out_dir) && proto_out_dir_is_abs) { + py_out_dir = proto_out_dir + } else { + if (!defined(proto_out_dir)) { + # Absolute path to the directory of current BUILD.gn file excluding "//". + proto_out_dir = rebase_path(".", "//") + if (proto_in_dir != ".") { + proto_out_dir += "/$proto_in_dir" + } + } + py_out_dir = "$root_out_dir/pyproto/" + proto_out_dir + } rel_py_out_dir = rebase_path(py_out_dir, root_build_dir) } @@ -232,7 +283,7 @@ } } - action_name = "${target_name}_gen" + action_name = "${target_name}__gen" source_set_name = target_name # Generate protobuf stubs. @@ -344,15 +395,21 @@ # use relative paths starting at |cc_out_dir|. # However there is no necessity to add an additional directory, if all protos # are located in the same directory which is in the search path by default. - config_name = "${target_name}_config" - config(config_name) { - include_dirs = [] - if (has_nested_dirs) { - include_dirs += [ cc_out_dir ] - } - if (defined(invoker.import_dirs)) { - foreach(path, invoker.import_dirs) { - include_dirs += [ "$root_gen_dir/" + rebase_path(path, "//") ] + if (has_nested_dirs || defined(invoker.import_dirs) || + defined(invoker.public_include_dirs)) { + config_name = "${target_name}__config" + config(config_name) { + include_dirs = [] + if (has_nested_dirs) { + include_dirs += [ cc_out_dir ] + } + if (defined(invoker.import_dirs)) { + foreach(path, invoker.import_dirs) { + include_dirs += [ "$root_gen_dir/" + rebase_path(path, "//") ] + } + } + if (defined(invoker.public_include_dirs)) { + include_dirs += invoker.public_include_dirs } } } @@ -387,7 +444,7 @@ if (generate_cc || generate_with_plugin) { # Not necessary if all protos are located in the same directory. - if (has_nested_dirs || defined(invoker.import_dirs)) { + if (defined(config_name)) { # It's not enough to set |include_dirs| for target since public imports # expose corresponding includes to header files as well. public_configs += [ ":$config_name" ]
diff --git a/tools/clang/scripts/build_clang_tools_extra.py b/tools/clang/scripts/build_clang_tools_extra.py new file mode 100755 index 0000000..12db0ad3 --- /dev/null +++ b/tools/clang/scripts/build_clang_tools_extra.py
@@ -0,0 +1,91 @@ +#!/usr/bin/env python +# 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. + +"""A script for fetching LLVM monorepo and building clang-tools-extra binaries. + +Example: build clangd and clangd-indexer + + tools/clang/scripts/build_clang_tools_extra.py --fetch out/Release clangd \ + clangd-indexer +""" + +import argparse +import errno +import os +import subprocess +import sys + + +def GetCheckoutDir(out_dir): + """Returns absolute path to the checked-out llvm repo.""" + return os.path.join(out_dir, 'tools', 'clang', 'third_party', 'llvm') + + +def GetBuildDir(out_dir): + return os.path.join(GetCheckoutDir(out_dir), 'build') + + +def CreateDirIfNotExists(dir): + if not os.path.exists(dir): + os.makedirs(dir) + + +def FetchLLVM(checkout_dir): + """Clone llvm repo into |out_dir| or update if it already exists.""" + CreateDirIfNotExists(os.path.dirname(checkout_dir)) + + try: + # First, try to clone the repo. + args = [ + 'git', + 'clone', + 'https://github.com/llvm/llvm-project.git', + checkout_dir, + ] + subprocess.check_call(args, shell=sys.platform == 'win32') + except subprocess.CalledProcessError: + # Otherwise, try to update it. + print('-- Attempting to update existing repo') + args = ['git', 'pull', '--rebase', 'origin', 'master'] + subprocess.check_call(args, cwd=checkout_dir) + + +def BuildTargets(build_dir, targets): + """Build targets from llvm repo at |build_dir|.""" + CreateDirIfNotExists(build_dir) + + # From that dir, run cmake + cmake_args = [ + 'cmake', + '-GNinja', + '-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra', + '-DCMAKE_BUILD_TYPE=Release', + '-DLLVM_ENABLE_ASSERTIONS=On', + '../llvm', + ] + subprocess.check_call(cmake_args, cwd=build_dir) + + ninja_commands = ['ninja'] + targets + subprocess.check_call(ninja_commands, cwd=build_dir) + + +def main(): + parser = argparse.ArgumentParser(description='Build clang_tools_extra.') + parser.add_argument( + '--fetch', action='store_true', help='fetch LLVM source') + parser.add_argument('OUT_DIR', help='where we put the LLVM source repository') + parser.add_argument('TARGETS', nargs='+', help='targets being built') + args = parser.parse_args() + + if args.fetch: + print 'Fetching LLVM source' + FetchLLVM(GetCheckoutDir(args.OUT_DIR)) + + print 'Building targets: %s' % ', '.join(args.TARGETS) + BuildTargets(GetBuildDir(args.OUT_DIR), args.TARGETS) + + +if __name__ == '__main__': + sys.exit(main())
diff --git a/tools/clang/scripts/clang_tidy_tool.py b/tools/clang/scripts/clang_tidy_tool.py index fae2f66..7bc16e2 100755 --- a/tools/clang/scripts/clang_tidy_tool.py +++ b/tools/clang/scripts/clang_tidy_tool.py
@@ -28,14 +28,7 @@ import subprocess import sys - -def GetCheckoutDir(out_dir): - """Returns absolute path to the checked-out llvm repo.""" - return os.path.join(out_dir, 'tools', 'clang', 'third_party', 'llvm') - - -def GetBuildDir(out_dir): - return os.path.join(GetCheckoutDir(out_dir), 'build') +import build_clang_tools_extra def GetBinaryPath(build_dir, binary): @@ -43,57 +36,6 @@ binary += '.exe' return os.path.join(build_dir, 'bin', binary) -def FetchClang(checkout_dir): - """Clone llvm repo into |out_dir| or update if it already exists.""" - try: - # Create parent directories of the checkout directory - os.makedirs(os.path.dirname(checkout_dir)) - except OSError: - pass - - try: - # First, try to clone the repo. - args = [ - 'git', - 'clone', - 'https://github.com/llvm/llvm-project.git', - checkout_dir, - ] - subprocess.check_call(args, shell=sys.platform == 'win32') - except subprocess.CalledProcessError: - # Otherwise, try to update it. - print('-- Attempting to update existing repo') - args = ['git', 'pull', '--rebase', 'origin', 'master'] - subprocess.check_call(args, cwd=checkout_dir) - - -def BuildClang(build_dir): - """Build clang from llvm repo at |build_dir|.""" - # Make <checkout>/build directory - try: - os.mkdir(build_dir) - except OSError as e: - # Ignore errno 17 'File Exists' - if e.errno != 17: - raise e - - # From that dir, run cmake - cmake_args = [ - 'cmake', - '-GNinja', - '-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra', - '-DCMAKE_BUILD_TYPE=Release', - '../llvm', - ] - subprocess.check_call(cmake_args, cwd=build_dir) - - ninja_args = [ - 'ninja', - 'clang-tidy', - 'clang-apply-replacements', - ] - subprocess.check_call(ninja_args, cwd=build_dir) - def BuildNinjaTarget(out_dir, ninja_target): args = ['autoninja', '-C', out_dir, ninja_target] @@ -228,9 +170,9 @@ # If the user hasn't provided a clang checkout and build dir, checkout and # build clang-tidy where update.py would. if not args.clang_src_dir: - args.clang_src_dir = GetCheckoutDir(args.OUT_DIR) + args.clang_src_dir = build_clang_tools_extra.GetCheckoutDir(args.OUT_DIR) if not args.clang_build_dir: - args.clang_build_dir = GetBuildDir(args.OUT_DIR) + args.clang_build_dir = build_clang_tools_extra.GetBuildDir(args.OUT_DIR) elif (args.clang_build_dir and not os.path.isfile(GetBinaryPath(args.clang_build_dir, 'clang-tidy'))): sys.exit('clang-tidy binary doesn\'t exist at ' + @@ -238,11 +180,14 @@ if args.fetch: - steps.append(('Fetching clang sources', lambda: - FetchClang(args.clang_src_dir))) + steps.append(('Fetching LLVM sources', lambda: + build_clang_tools_extra.FetchLLVM(args.clang_src_dir))) if args.build: - steps.append(('Building clang', lambda: BuildClang(args.clang_build_dir))) + steps.append(('Building clang-tidy', + lambda: build_clang_tools_extra.BuildTargets( + args.clang_build_dir, + ['clang-tidy', 'clang-apply-replacements']))) steps += [ ('Building ninja target: %s' % args.NINJA_TARGET,
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py index 10b061f..5e5f4bf 100755 --- a/tools/clang/scripts/update.py +++ b/tools/clang/scripts/update.py
@@ -35,7 +35,7 @@ # Do NOT CHANGE this if you don't know what you're doing -- see # https://chromium.googlesource.com/chromium/src/+/master/docs/updating_clang.md # Reverting problematic clang rolls is safe, though. -CLANG_REVISION = '356356' +CLANG_REVISION = '357692' use_head_revision = bool(os.environ.get('LLVM_FORCE_HEAD_REVISION', '0') in ('1', 'YES')) @@ -43,7 +43,7 @@ CLANG_REVISION = 'HEAD' # This is incremented when pushing a new build of Clang at the same revision. -CLANG_SUB_REVISION=3 +CLANG_SUB_REVISION=1 PACKAGE_VERSION = "%s-%s" % (CLANG_REVISION, CLANG_SUB_REVISION)
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 6de4664a..83e353f 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -33238,6 +33238,7 @@ <int value="-181279574" label="NativeFilesystemAPI:enabled"/> <int value="-181093956" label="ScrollAnchoring:enabled"/> <int value="-180481252" label="CompositorThreadedScrollbarScrolling:enabled"/> + <int value="-175666252" label="Portals:disabled"/> <int value="-174706795" label="WebPaymentsPerMethodCanMakePaymentQuota:enabled"/> <int value="-174564579" @@ -33368,6 +33369,7 @@ <int value="7533886" label="disable-offer-store-unmasked-wallet-cards"/> <int value="10458238" label="disable-print-preview-simplify"/> <int value="11698808" label="enable-dom-distiller-button-animation"/> + <int value="15614295" label="Portals:enabled"/> <int value="19629326" label="OmniboxExperimentalKeywordMode:enabled"/> <int value="19815558" label="EnableSettingsShortcutSearch:disabled"/> <int value="23556595" label="MarkHttpAs:enabled"/>
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index be720c7..55bea1c 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -112269,10 +112269,24 @@ </histogram> <histogram name="Signin.Reconciler.Duration"> + <obsolete> + Deprecated in favor of Signin.Reconciler.Duration.UpTo3mins. + </obsolete> <owner>rogerta@chromium.org</owner> + <owner>msarda@chromium.org</owner> <summary>Records the execution time of the account reconciler.</summary> </histogram> +<histogram base="true" name="Signin.Reconciler.Duration.UpTo3mins" units="ms" + expires_after="2021-04-30"> + <owner>droger@chromium.org</owner> + <owner>msarda@chromium.org</owner> + <summary> + Records the execution time of the account reconciler using 100 buckets, up + to 3 minutes. + </summary> +</histogram> + <histogram name="Signin.Reconciler.ExternalCcResultTime.Completed"> <owner>msarda@chromium.org</owner> <owner>droger@chromium.org</owner> @@ -150259,11 +150273,20 @@ </histogram_suffixes> <histogram_suffixes name="Signin.Reconciler.Duration" separator="."> + <obsolete> + Deprecated in favor of Signin.Reconciler.Duration.UpTo3mins. + </obsolete> <suffix name="Failure" label="Failed execution of reconciler"/> <suffix name="Success" label="Successful execution of reconciler"/> <affected-histogram name="Signin.Reconciler.Duration"/> </histogram_suffixes> +<histogram_suffixes name="Signin.Reconciler.Duration.UpTo3mins" separator="."> + <suffix name="Failure" label="Failed execution of reconciler"/> + <suffix name="Success" label="Successful execution of reconciler"/> + <affected-histogram name="Signin.Reconciler.Duration.UpTo3mins"/> +</histogram_suffixes> + <histogram_suffixes name="SigninAccountStatus" separator="."> <suffix name="NewAccount" label="Using a new account, in the sign-in promo."> <obsolete>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 998ccfb70..7bf87f405 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -2405,6 +2405,7 @@ <aggregation> <history> <index fields="profile.country"/> + <index fields="profile.country,profile.system_ram"/> <statistics> <quantiles type="std-percentiles"/> </statistics> @@ -2443,6 +2444,7 @@ <aggregation> <history> <index fields="profile.country"/> + <index fields="profile.country,profile.system_ram"/> <statistics> <quantiles type="std-percentiles"/> </statistics>
diff --git a/tools/traffic_annotation/auditor/BUILD.gn b/tools/traffic_annotation/auditor/BUILD.gn index 5f01c32..7931a890 100644 --- a/tools/traffic_annotation/auditor/BUILD.gn +++ b/tools/traffic_annotation/auditor/BUILD.gn
@@ -9,8 +9,6 @@ assert(is_win || is_linux) proto_library("chrome_settings_full_runtime") { - proto_out_dir = "/tools/traffic_annotation" - cc_include = "components/policy/proto/policy_proto_export.h" sources = [
diff --git a/ui/accessibility/BUILD.gn b/ui/accessibility/BUILD.gn index a8b692a..8ce6a2e 100644 --- a/ui/accessibility/BUILD.gn +++ b/ui/accessibility/BUILD.gn
@@ -132,15 +132,12 @@ defines = [ "ACCESSIBILITY_IMPLEMENTATION" ] - deps = [ - "//third_party/cld_3/src/src:cld_3", - ] - public_deps = [ ":ax_constants_mojo", ":ax_enums_mojo", "//base", "//base:i18n", + "//third_party/cld_3/src/src:cld_3", "//ui/base", "//ui/display", "//ui/gfx",
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.cc b/ui/accessibility/platform/ax_platform_node_auralinux.cc index 06cac04..82eec09 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.cc +++ b/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -3238,8 +3238,53 @@ } void AXPlatformNodeAuraLinux::UpdateHypertext() { + AXHypertext old_hypertext = hypertext_; + base::OffsetAdjuster::Adjustments old_adjustments = GetHypertextAdjustments(); + UpdateComputedHypertext(); text_unicode_adjustments_ = base::nullopt; + + if ((!GetData().HasState(ax::mojom::State::kEditable) || + GetData().GetRestriction() == ax::mojom::Restriction::kReadOnly) && + !IsInLiveRegion()) { + return; + } + + size_t shared_prefix, old_len, new_len; + ComputeHypertextRemovedAndInserted(old_hypertext, &shared_prefix, &old_len, + &new_len); + + DCHECK(atk_object_); + DCHECK(ATK_IS_TEXT(atk_object_)); + + if (old_len > 0) { + base::string16 removed_substring = + old_hypertext.hypertext.substr(shared_prefix, old_len); + + size_t shared_unicode_prefix = shared_prefix; + base::OffsetAdjuster::AdjustOffset(old_adjustments, &shared_unicode_prefix); + size_t shared_unicode_suffix = shared_prefix + old_len; + base::OffsetAdjuster::AdjustOffset(old_adjustments, &shared_unicode_suffix); + + g_signal_emit_by_name( + atk_object_, "text-remove", + shared_unicode_prefix, // position of removal + shared_unicode_suffix - shared_prefix, // length of removal + base::UTF16ToUTF8(removed_substring).c_str()); + } + + if (new_len > 0) { + base::string16 inserted_substring = + hypertext_.hypertext.substr(shared_prefix, new_len); + size_t shared_unicode_prefix = UTF16ToUnicodeOffsetInText(shared_prefix); + size_t shared_unicode_suffix = + UTF16ToUnicodeOffsetInText(shared_prefix + new_len); + g_signal_emit_by_name( + atk_object_, "text-insert", + shared_unicode_prefix, // position of insertion + shared_unicode_suffix - shared_unicode_prefix, // length of insertion + base::UTF16ToUTF8(inserted_substring).c_str()); + } } const AXHypertext& AXPlatformNodeAuraLinux::GetHypertext() { @@ -3558,4 +3603,9 @@ selection_end); } +bool AXPlatformNodeAuraLinux::IsInLiveRegion() { + return GetData().HasStringAttribute( + ax::mojom::StringAttribute::kContainerLiveStatus); +} + } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_auralinux.h b/ui/accessibility/platform/ax_platform_node_auralinux.h index c447b482..d1dd931 100644 --- a/ui/accessibility/platform/ax_platform_node_auralinux.h +++ b/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -160,6 +160,7 @@ void AddRelationToSet(AtkRelationSet*, AtkRelationType, AXPlatformNode* target); + bool IsInLiveRegion(); // The AtkStateType for a checkable node can vary depending on the role. AtkStateType GetAtkStateTypeForCheckableNode();
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc index 11bdd64..14a7849 100644 --- a/ui/accessibility/platform/ax_platform_node_base.cc +++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -1366,4 +1366,122 @@ } } +bool AXPlatformNodeBase::IsSameHypertextCharacter( + const AXHypertext& old_hypertext, + size_t old_char_index, + size_t new_char_index) { + if (old_char_index >= old_hypertext.hypertext.size() || + new_char_index >= hypertext_.hypertext.size()) { + return false; + } + + // For anything other than the "embedded character", we just compare the + // characters directly. + base::char16 old_ch = old_hypertext.hypertext[old_char_index]; + base::char16 new_ch = hypertext_.hypertext[new_char_index]; + if (old_ch != new_ch) + return false; + if (new_ch != kEmbeddedCharacter) + return true; + + // If it's an embedded character, they're only identical if the child id + // the hyperlink points to is the same. + const std::map<int32_t, int32_t>& old_offset_to_index = + old_hypertext.hyperlink_offset_to_index; + const std::vector<int32_t>& old_hyperlinks = old_hypertext.hyperlinks; + int32_t old_hyperlinkscount = static_cast<int32_t>(old_hyperlinks.size()); + auto iter = old_offset_to_index.find(static_cast<int32_t>(old_char_index)); + int old_index = (iter != old_offset_to_index.end()) ? iter->second : -1; + int old_child_id = (old_index >= 0 && old_index < old_hyperlinkscount) + ? old_hyperlinks[old_index] + : -1; + + const std::map<int32_t, int32_t>& new_offset_to_index = + hypertext_.hyperlink_offset_to_index; + const std::vector<int32_t>& new_hyperlinks = hypertext_.hyperlinks; + int32_t new_hyperlinkscount = static_cast<int32_t>(new_hyperlinks.size()); + iter = new_offset_to_index.find(static_cast<int32_t>(new_char_index)); + int new_index = (iter != new_offset_to_index.end()) ? iter->second : -1; + int new_child_id = (new_index >= 0 && new_index < new_hyperlinkscount) + ? new_hyperlinks[new_index] + : -1; + + return old_child_id == new_child_id; +} + +// Return true if the index represents a text character. +bool AXPlatformNodeBase::IsText(const base::string16& text, + size_t index, + bool is_indexed_from_end) { + size_t text_len = text.size(); + if (index == text_len) + return false; + auto ch = text[is_indexed_from_end ? text_len - index - 1 : index]; + return ch != kEmbeddedCharacter; +} + +void AXPlatformNodeBase::ComputeHypertextRemovedAndInserted( + const AXHypertext& old_hypertext, + size_t* start, + size_t* old_len, + size_t* new_len) { + *start = 0; + *old_len = 0; + *new_len = 0; + + // Do not compute for static text objects, otherwise redundant text change + // announcements will occur in live regions, as the parent hypertext also + // changes. + if (GetData().role == ax::mojom::Role::kStaticText) + return; + + const base::string16& old_text = old_hypertext.hypertext; + const base::string16& new_text = hypertext_.hypertext; + + // TODO(accessibility) Plumb through which part of text changed so we don't + // have to guess what changed based on character differences. This can be + // wrong in some cases as follows: + // -- EDITABLE -- + // If editable: when part of the text node changes, assume only that part + // changed, and not the entire thing. For example, if "car" changes to + // "cat", assume only 1 letter changed. This code compares common characters + // to guess what has changed. + // -- NOT EDITABLE -- + // When part of the text changes, assume the entire node's text changed. For + // example, if "car" changes to "cat" then assume all 3 letters changed. + // Note, it is possible (though rare) that CharacterData methods are used to + // remove, insert, replace or append a substring. + bool allow_partial_text_node_changes = + GetData().HasState(ax::mojom::State::kEditable); + size_t prefix_index = 0; + size_t common_prefix = 0; + while (prefix_index < old_text.size() && prefix_index < new_text.size() && + IsSameHypertextCharacter(old_hypertext, prefix_index, prefix_index)) { + ++prefix_index; + if (allow_partial_text_node_changes || + (!IsText(old_text, prefix_index) && !IsText(new_text, prefix_index))) { + common_prefix = prefix_index; + } + } + + size_t suffix_index = 0; + size_t common_suffix = 0; + while (common_prefix + suffix_index < old_text.size() && + common_prefix + suffix_index < new_text.size() && + IsSameHypertextCharacter(old_hypertext, + old_text.size() - suffix_index - 1, + new_text.size() - suffix_index - 1)) { + ++suffix_index; + if (allow_partial_text_node_changes || + (!IsText(old_text, suffix_index, true) && + !IsText(new_text, suffix_index, true))) { + common_suffix = suffix_index; + } + } + + *start = common_prefix; + *old_len = old_text.size() - common_prefix - common_suffix; + *new_len = new_text.size() - common_prefix - common_suffix; +} + } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h index 4e84509..5cd44c74 100644 --- a/ui/accessibility/platform/ax_platform_node_base.h +++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -340,12 +340,24 @@ int GetHypertextOffsetFromEndpoint(AXPlatformNodeBase* endpoint_object, int endpoint_offset); + bool IsSameHypertextCharacter(const AXHypertext& old_hypertext, + size_t old_char_index, + size_t new_char_index); + void ComputeHypertextRemovedAndInserted(const AXHypertext& old_hypertext, + size_t* start, + size_t* old_len, + size_t* new_len); int32_t GetPosInSet() const; int32_t GetSetSize() const; AXHypertext hypertext_; private: + // Return true if the index represents a text character. + bool IsText(const base::string16& text, + size_t index, + bool is_indexed_from_end = false); + DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeBase); };
diff --git a/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc index b9e358f1..49b93164 100644 --- a/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textprovider_win_unittest.cc
@@ -324,6 +324,7 @@ EXPECT_EQ(0, wcscmp(text_content, L"some")); text_content.Reset(); selections.Reset(); + text_range_provider.Release(); // Verify that start and end are appropriately swapped when sel_anchor_offset // is greater than sel_focus_offset @@ -348,6 +349,7 @@ EXPECT_EQ(0, wcscmp(text_content, L"some")); text_content.Reset(); selections.Reset(); + text_range_provider.Release(); // Verify that text ranges at an insertion point returns a degenerate (empty) // text range via textbox with sel_anchor_offset equal to sel_focus_offset @@ -384,6 +386,7 @@ EXPECT_EQ(0U, SysStringLen(text_content)); text_content.Reset(); selections.Reset(); + text_edit_range_provider.Release(); // Now delete the tree (which will delete the associated elements) and verify // that UIA_E_ELEMENTNOTAVAILABLE is returned when calling GetSelection on
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc index 0bbf5c3c..2008808 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win.cc
@@ -8,6 +8,7 @@ #include <vector> #include "base/win/scoped_variant.h" +#include "ui/accessibility/ax_action_data.h" #include "ui/accessibility/platform/ax_platform_node_delegate.h" #define UIA_VALIDATE_TEXTRANGEPROVIDER_CALL() \ @@ -320,7 +321,17 @@ STDMETHODIMP AXPlatformNodeTextRangeProviderWin::Select() { WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_TEXTRANGE_SELECT); - return E_NOTIMPL; + UIA_VALIDATE_TEXTRANGEPROVIDER_CALL(); + + AXNodeRange range(start_->Clone(), end_->Clone()); + AXActionData action_data; + action_data.anchor_node_id = range.anchor()->anchor_id(); + action_data.anchor_offset = range.anchor()->text_offset(); + action_data.focus_node_id = range.focus()->anchor_id(); + action_data.focus_offset = range.focus()->text_offset(); + action_data.action = ax::mojom::Action::kSetSelection; + owner()->GetDelegate()->AccessibilityPerformAction(action_data); + return S_OK; } STDMETHODIMP AXPlatformNodeTextRangeProviderWin::AddToSelection() {
diff --git a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc index fe9bfaf..9592c8a3 100644 --- a/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc +++ b/ui/accessibility/platform/ax_platform_node_textrangeprovider_win_unittest.cc
@@ -442,6 +442,8 @@ EXPECT_UIA_ELEMENTNOTAVAILABLE(text_range_provider->MoveEndpointByRange( TextPatternRangeEndpoint_Start, text_range_provider.Get(), TextPatternRangeEndpoint_Start)); + + EXPECT_UIA_ELEMENTNOTAVAILABLE(text_range_provider->Select()); } // Test for when this provider is valid, but the other provider is not an @@ -1287,4 +1289,190 @@ expected_mixed_variant); } +TEST_F(AXPlatformNodeTextRangeProviderTest, TestITextRangeProviderSelect) { + ui::AXNodeData text_data; + text_data.id = 2; + text_data.role = ax::mojom::Role::kStaticText; + text_data.SetName("some text"); + + ui::AXNodeData more_text_data; + more_text_data.id = 3; + more_text_data.role = ax::mojom::Role::kStaticText; + more_text_data.SetName("more text2"); + + ui::AXNodeData root_data; + root_data.id = 1; + root_data.role = ax::mojom::Role::kRootWebArea; + root_data.child_ids = {2, 3}; + + ui::AXTreeUpdate update; + ui::AXTreeData tree_data; + tree_data.tree_id = ui::AXTreeID::CreateNewAXTreeID(); + update.tree_data = tree_data; + update.has_tree_data = true; + update.root_id = root_data.id; + update.nodes = {root_data, text_data, more_text_data}; + + Init(update); + + AXNode* root_node = GetRootNode(); + AXNodePosition::SetTreeForTesting(tree_.get()); + AXNode* text_node = root_node->children()[0]; + AXNode* more_text_node = root_node->children()[1]; + + // Text range for the document, which contains text "some textmore text2". + ComPtr<IRawElementProviderSimple> root_node_raw = + QueryInterfaceFromNode<IRawElementProviderSimple>(root_node); + ComPtr<ITextProvider> document_provider; + ComPtr<ITextRangeProvider> document_text_range_provider; + ComPtr<AXPlatformNodeTextRangeProviderWin> document_text_range; + EXPECT_HRESULT_SUCCEEDED( + root_node_raw->GetPatternProvider(UIA_TextPatternId, &document_provider)); + EXPECT_HRESULT_SUCCEEDED( + document_provider->get_DocumentRange(&document_text_range_provider)); + document_text_range_provider->QueryInterface( + IID_PPV_ARGS(&document_text_range)); + + // Text range related to "some text". + ComPtr<IRawElementProviderSimple> text_node_raw = + QueryInterfaceFromNode<IRawElementProviderSimple>(text_node); + ComPtr<ITextProvider> text_provider; + ComPtr<ITextRangeProvider> text_range_provider; + ComPtr<AXPlatformNodeTextRangeProviderWin> text_range; + EXPECT_HRESULT_SUCCEEDED( + text_node_raw->GetPatternProvider(UIA_TextPatternId, &text_provider)); + EXPECT_HRESULT_SUCCEEDED( + text_provider->get_DocumentRange(&text_range_provider)); + text_range_provider->QueryInterface(IID_PPV_ARGS(&text_range)); + + // Text range related to "more text2". + ComPtr<IRawElementProviderSimple> more_text_node_raw = + QueryInterfaceFromNode<IRawElementProviderSimple>(more_text_node); + ComPtr<ITextProvider> more_text_provider; + ComPtr<ITextRangeProvider> more_text_range_provider; + ComPtr<AXPlatformNodeTextRangeProviderWin> more_text_range; + EXPECT_HRESULT_SUCCEEDED(more_text_node_raw->GetPatternProvider( + UIA_TextPatternId, &more_text_provider)); + EXPECT_HRESULT_SUCCEEDED( + more_text_provider->get_DocumentRange(&more_text_range_provider)); + more_text_range_provider->QueryInterface(IID_PPV_ARGS(&more_text_range)); + + AXPlatformNodeDelegate* delegate = + GetOwner(document_text_range.Get())->GetDelegate(); + + CComPtr<ITextRangeProvider> selected_text_range_provider; + base::win::ScopedSafearray selection; + base::win::ScopedBstr selected_text_content; + long index = 0; + long ubound; + long lbound; + + // Text range "some text" performs select. + { + text_range_provider->Select(); + + // Verify selection. + EXPECT_EQ(2, delegate->GetTreeData().sel_anchor_object_id); + EXPECT_EQ(2, delegate->GetTreeData().sel_focus_object_id); + EXPECT_EQ(0, delegate->GetTreeData().sel_anchor_offset); + EXPECT_EQ(9, delegate->GetTreeData().sel_focus_offset); + + // Verify the content of the selection. + document_provider->GetSelection(selection.Receive()); + ASSERT_NE(nullptr, selection.Get()); + + EXPECT_HRESULT_SUCCEEDED(SafeArrayGetUBound(selection.Get(), 1, &ubound)); + EXPECT_EQ(0, ubound); + EXPECT_HRESULT_SUCCEEDED(SafeArrayGetLBound(selection.Get(), 1, &lbound)); + EXPECT_EQ(0, lbound); + EXPECT_HRESULT_SUCCEEDED(SafeArrayGetElement( + selection.Get(), &index, &selected_text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED(selected_text_range_provider->GetText( + -1, selected_text_content.Receive())); + EXPECT_EQ(0, wcscmp(selected_text_content, L"some text")); + selection.Reset(); + selected_text_content.Reset(); + selected_text_range_provider.Release(); + } + + // Text range "more text2" performs select. + { + more_text_range_provider->Select(); + + // Verify selection + EXPECT_EQ(3, delegate->GetTreeData().sel_anchor_object_id); + EXPECT_EQ(3, delegate->GetTreeData().sel_focus_object_id); + EXPECT_EQ(0, delegate->GetTreeData().sel_anchor_offset); + EXPECT_EQ(10, delegate->GetTreeData().sel_focus_offset); + + // Verify the content of the selection. + document_provider->GetSelection(selection.Receive()); + ASSERT_NE(nullptr, selection.Get()); + + EXPECT_HRESULT_SUCCEEDED(SafeArrayGetUBound(selection.Get(), 1, &ubound)); + EXPECT_EQ(0, ubound); + EXPECT_HRESULT_SUCCEEDED(SafeArrayGetLBound(selection.Get(), 1, &lbound)); + EXPECT_EQ(0, lbound); + EXPECT_HRESULT_SUCCEEDED(SafeArrayGetElement( + selection.Get(), &index, &selected_text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED(selected_text_range_provider->GetText( + -1, selected_text_content.Receive())); + EXPECT_EQ(0, wcscmp(selected_text_content, L"more text2")); + selection.Reset(); + selected_text_content.Reset(); + selected_text_range_provider.Release(); + } + + // Document text range "some textmore text2" performs select. + { + document_text_range_provider->Select(); + + // Verify selection. + EXPECT_EQ(2, delegate->GetTreeData().sel_anchor_object_id); + EXPECT_EQ(3, delegate->GetTreeData().sel_focus_object_id); + EXPECT_EQ(0, delegate->GetTreeData().sel_anchor_offset); + EXPECT_EQ(10, delegate->GetTreeData().sel_focus_offset); + + // When selection spans multiple nodes ITextProvider::GetSelection is not + // supported. But the text range is still selected. + document_provider->GetSelection(selection.Receive()); + ASSERT_EQ(nullptr, selection.Get()); + } + + // A degenerate text range performs select. + { + // Move the endpoint of text range so it becomes degenerate, then select. + text_range_provider->MoveEndpointByRange(TextPatternRangeEndpoint_Start, + text_range_provider.Get(), + TextPatternRangeEndpoint_End); + text_range_provider->Select(); + + // Verify selection. + EXPECT_EQ(2, delegate->GetTreeData().sel_anchor_object_id); + EXPECT_EQ(2, delegate->GetTreeData().sel_focus_object_id); + EXPECT_EQ(9, delegate->GetTreeData().sel_anchor_offset); + EXPECT_EQ(9, delegate->GetTreeData().sel_focus_offset); + + // Verify the content of the selection. + document_provider->GetSelection(selection.Receive()); + ASSERT_NE(nullptr, selection.Get()); + + EXPECT_HRESULT_SUCCEEDED(SafeArrayGetUBound(selection.Get(), 1, &ubound)); + EXPECT_EQ(0, ubound); + EXPECT_HRESULT_SUCCEEDED(SafeArrayGetLBound(selection.Get(), 1, &lbound)); + EXPECT_EQ(0, lbound); + EXPECT_HRESULT_SUCCEEDED(SafeArrayGetElement( + selection.Get(), &index, &selected_text_range_provider)); + + EXPECT_HRESULT_SUCCEEDED(selected_text_range_provider->GetText( + -1, selected_text_content.Receive())); + EXPECT_EQ(0, wcscmp(selected_text_content, L"")); + selection.Reset(); + selected_text_content.Reset(); + selected_text_range_provider.Release(); + } +} + } // namespace ui
diff --git a/ui/accessibility/platform/ax_platform_node_win.cc b/ui/accessibility/platform/ax_platform_node_win.cc index fb94111..cb10e1f 100644 --- a/ui/accessibility/platform/ax_platform_node_win.cc +++ b/ui/accessibility/platform/ax_platform_node_win.cc
@@ -6471,118 +6471,11 @@ return false; } -bool AXPlatformNodeWin::IsSameHypertextCharacter(size_t old_char_index, - size_t new_char_index) { - if (old_char_index >= old_hypertext_.hypertext.size() || - new_char_index >= hypertext_.hypertext.size()) { - return false; - } - - // For anything other than the "embedded character", we just compare the - // characters directly. - base::char16 old_ch = old_hypertext_.hypertext[old_char_index]; - base::char16 new_ch = hypertext_.hypertext[new_char_index]; - if (old_ch != new_ch) - return false; - if (new_ch != kEmbeddedCharacter) - return true; - - // If it's an embedded character, they're only identical if the child id - // the hyperlink points to is the same. - std::map<int32_t, int32_t>& old_offset_to_index = - old_hypertext_.hyperlink_offset_to_index; - std::vector<int32_t>& old_hyperlinks = old_hypertext_.hyperlinks; - int32_t old_hyperlinkscount = static_cast<int32_t>(old_hyperlinks.size()); - std::map<int32_t, int32_t>::iterator iter; - iter = old_offset_to_index.find((int32_t)old_char_index); - int old_index = (iter != old_offset_to_index.end()) ? iter->second : -1; - int old_child_id = (old_index >= 0 && old_index < old_hyperlinkscount) - ? old_hyperlinks[old_index] - : -1; - - std::map<int32_t, int32_t>& new_offset_to_index = - hypertext_.hyperlink_offset_to_index; - std::vector<int32_t>& new_hyperlinks = hypertext_.hyperlinks; - int32_t new_hyperlinkscount = static_cast<int32_t>(new_hyperlinks.size()); - iter = new_offset_to_index.find((int32_t)new_char_index); - int new_index = (iter != new_offset_to_index.end()) ? iter->second : -1; - int new_child_id = (new_index >= 0 && new_index < new_hyperlinkscount) - ? new_hyperlinks[new_index] - : -1; - - return old_child_id == new_child_id; -} - -// Return true if the index represents a text character. -bool AXPlatformNodeWin::IsText(const base::string16& text, - size_t index, - bool is_indexed_from_end) { - size_t text_len = text.size(); - if (index == text_len) - return false; - auto ch = text[is_indexed_from_end ? text_len - index - 1 : index]; - return ch != kEmbeddedCharacter; -} - void AXPlatformNodeWin::ComputeHypertextRemovedAndInserted(size_t* start, size_t* old_len, size_t* new_len) { - *start = 0; - *old_len = 0; - *new_len = 0; - - // Do not compute for static text objects, otherwise redundant text change - // announcements will occur in live regions, as the parent hypertext also - // changes. - if (GetData().role == ax::mojom::Role::kStaticText) - return; - - const base::string16& old_text = old_hypertext_.hypertext; - const base::string16& new_text = hypertext_.hypertext; - - // TODO(accessibility) Plumb through which part of text changed so we don't - // have to guess what changed based on character differences. This can be - // wrong in some cases as follows: - // -- EDITABLE -- - // If editable: when part of the text node changes, assume only that part - // changed, and not the entire thing. For example, if "car" changes to - // "cat", assume only 1 letter changed. This code compares common characters - // to guess what has changed. - // -- NOT EDITABLE -- - // When part of the text changes, assume the entire node's text changed. For - // example, if "car" changes to "cat" then assume all 3 letters changed. - // Note, it is possible (though rare) that CharacterData methods are used to - // remove, insert, replace or append a substring. - bool allow_partial_text_node_changes = - GetData().HasState(ax::mojom::State::kEditable); - size_t prefix_index = 0; - size_t common_prefix = 0; - while (prefix_index < old_text.size() && prefix_index < new_text.size() && - IsSameHypertextCharacter(prefix_index, prefix_index)) { - ++prefix_index; - if (allow_partial_text_node_changes || - (!IsText(old_text, prefix_index) && !IsText(new_text, prefix_index))) { - common_prefix = prefix_index; - } - } - - size_t suffix_index = 0; - size_t common_suffix = 0; - while (common_prefix + suffix_index < old_text.size() && - common_prefix + suffix_index < new_text.size() && - IsSameHypertextCharacter(old_text.size() - suffix_index - 1, - new_text.size() - suffix_index - 1)) { - ++suffix_index; - if (allow_partial_text_node_changes || - (!IsText(old_text, suffix_index, true) && - !IsText(new_text, suffix_index, true))) { - common_suffix = suffix_index; - } - } - - *start = common_prefix; - *old_len = old_text.size() - common_prefix - common_suffix; - *new_len = new_text.size() - common_prefix - common_suffix; + AXPlatformNodeBase::ComputeHypertextRemovedAndInserted(old_hypertext_, start, + old_len, new_len); } double AXPlatformNodeWin::GetHorizontalScrollPercent() {
diff --git a/ui/accessibility/platform/ax_platform_node_win.h b/ui/accessibility/platform/ax_platform_node_win.h index 190f838..2eb9a14 100644 --- a/ui/accessibility/platform/ax_platform_node_win.h +++ b/ui/accessibility/platform/ax_platform_node_win.h
@@ -1048,8 +1048,6 @@ // Also, in IA2, text that includes embedded objects is called hypertext. // Returns true if the current object is an IA2 hyperlink. bool IsHyperlink(); - - bool IsSameHypertextCharacter(size_t old_char_index, size_t new_char_index); void ComputeHypertextRemovedAndInserted(size_t* start, size_t* old_len, size_t* new_len); @@ -1165,11 +1163,6 @@ LONG start_offset, TextBoundaryDirection direction); - // Return true if the index represents a text character. - bool IsText(const base::string16& text, - size_t index, - bool is_indexed_from_end = false); - // Many MSAA methods take a var_id parameter indicating that the operation // should be performed on a particular child ID, rather than this object. // This method tries to figure out the target object from |var_id| and
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.cc b/ui/accessibility/platform/test_ax_node_wrapper.cc index b29eb27..3e10fef 100644 --- a/ui/accessibility/platform/test_ax_node_wrapper.cc +++ b/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -278,6 +278,22 @@ node_->SetData(new_data); } +void TestAXNodeWrapper::ReplaceTreeDataTextSelection(int32_t anchor_node_id, + int32_t anchor_offset, + int32_t focus_node_id, + int32_t focus_offset) { + if (!tree_) + return; + + AXTreeData new_tree_data = GetTreeData(); + new_tree_data.sel_anchor_object_id = anchor_node_id; + new_tree_data.sel_anchor_offset = anchor_offset; + new_tree_data.sel_focus_object_id = focus_node_id; + new_tree_data.sel_focus_offset = focus_offset; + + tree_->UpdateData(new_tree_data); +} + bool TestAXNodeWrapper::IsTable() const { return node_->IsTable(); } @@ -434,14 +450,17 @@ } return true; - case ax::mojom::Action::kSetSelection: + case ax::mojom::Action::kSetSelection: { ReplaceIntAttribute(data.anchor_node_id, ax::mojom::IntAttribute::kTextSelStart, data.anchor_offset); - ReplaceIntAttribute(data.anchor_node_id, + ReplaceIntAttribute(data.focus_node_id, ax::mojom::IntAttribute::kTextSelEnd, data.focus_offset); + ReplaceTreeDataTextSelection(data.anchor_node_id, data.anchor_offset, + data.focus_node_id, data.focus_offset); return true; + } case ax::mojom::Action::kFocus: g_focused_node_in_tree[tree_] = node_;
diff --git a/ui/accessibility/platform/test_ax_node_wrapper.h b/ui/accessibility/platform/test_ax_node_wrapper.h index 1ce4add8..7c2ccfc 100644 --- a/ui/accessibility/platform/test_ax_node_wrapper.h +++ b/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -119,6 +119,10 @@ void ReplaceBoolAttribute(ax::mojom::BoolAttribute attribute, bool value); void ReplaceStringAttribute(ax::mojom::StringAttribute attribute, std::string value); + void ReplaceTreeDataTextSelection(int32_t anchor_node_id, + int32_t anchor_offset, + int32_t focus_node_id, + int32_t focus_offset); TestAXNodeWrapper* HitTestSyncInternal(int x, int y);
diff --git a/ui/aura/mus/window_tree_client.cc b/ui/aura/mus/window_tree_client.cc index fdd132b..b9a4f57 100644 --- a/ui/aura/mus/window_tree_client.cc +++ b/ui/aura/mus/window_tree_client.cc
@@ -1822,6 +1822,12 @@ drag_drop_controller_.get()); } +void WindowTreeClient::ConnectToImeEngine( + ime::mojom::ImeEngineRequest engine_request, + ime::mojom::ImeEngineClientPtr client) { + tree_->ConnectToImeEngine(std::move(engine_request), std::move(client)); +} + void WindowTreeClient::OnTransientChildWindowAdded(Window* parent, Window* transient_child) { // TransientWindowClient is a singleton and we allow multiple
diff --git a/ui/aura/mus/window_tree_client.h b/ui/aura/mus/window_tree_client.h index c9b3d24..04a0a3d 100644 --- a/ui/aura/mus/window_tree_client.h +++ b/ui/aura/mus/window_tree_client.h
@@ -515,6 +515,8 @@ std::unique_ptr<WindowPortMus> CreateWindowPortForTopLevel( const std::map<std::string, std::vector<uint8_t>>* properties) override; void OnWindowTreeHostCreated(WindowTreeHostMus* window_tree_host) override; + void ConnectToImeEngine(ime::mojom::ImeEngineRequest engine_request, + ime::mojom::ImeEngineClientPtr client) override; // client::TransientWindowClientObserver: void OnTransientChildWindowAdded(Window* parent,
diff --git a/ui/aura/mus/window_tree_host_mus.cc b/ui/aura/mus/window_tree_host_mus.cc index a06c87c..1c694ec 100644 --- a/ui/aura/mus/window_tree_host_mus.cc +++ b/ui/aura/mus/window_tree_host_mus.cc
@@ -350,6 +350,13 @@ WindowPortMus::Get(window())->SetImeVisibility(visible, std::move(state)); } +bool WindowTreeHostMus::ConnectToImeEngine( + ime::mojom::ImeEngineRequest engine_request, + ime::mojom::ImeEngineClientPtr client) { + delegate_->ConnectToImeEngine(std::move(engine_request), std::move(client)); + return true; +} + void WindowTreeHostMus::SetBoundsInPixels( const gfx::Rect& bounds, const viz::LocalSurfaceIdAllocation& local_surface_id_allocation) {
diff --git a/ui/aura/mus/window_tree_host_mus.h b/ui/aura/mus/window_tree_host_mus.h index 45cdbf0..a8afe3b 100644 --- a/ui/aura/mus/window_tree_host_mus.h +++ b/ui/aura/mus/window_tree_host_mus.h
@@ -16,6 +16,7 @@ #include "ui/aura/aura_export.h" #include "ui/aura/mus/input_method_mus_delegate.h" #include "ui/aura/window_tree_host_platform.h" +#include "ui/base/ime/mojo/ime.mojom.h" #include "ui/base/mojo/ui_base_types.mojom.h" namespace display { @@ -118,6 +119,8 @@ void SetTextInputState(ui::mojom::TextInputStatePtr state) override; void SetImeVisibility(bool visible, ui::mojom::TextInputStatePtr state) override; + bool ConnectToImeEngine(ime::mojom::ImeEngineRequest engine_request, + ime::mojom::ImeEngineClientPtr client) override; protected: // This is in the protected section as SetBounds() is preferred.
diff --git a/ui/aura/mus/window_tree_host_mus_delegate.h b/ui/aura/mus/window_tree_host_mus_delegate.h index 76f759a5..d45ed48 100644 --- a/ui/aura/mus/window_tree_host_mus_delegate.h +++ b/ui/aura/mus/window_tree_host_mus_delegate.h
@@ -12,6 +12,7 @@ #include <vector> #include "ui/aura/aura_export.h" +#include "ui/base/ime/mojo/ime.mojom.h" namespace gfx { class Rect; @@ -75,6 +76,11 @@ // created. virtual void OnWindowTreeHostCreated(WindowTreeHostMus* window_tree_host) = 0; + // Called when a client requests to connect to the active + // ime::mojom::ImeEngine. + virtual void ConnectToImeEngine(ime::mojom::ImeEngineRequest engine_request, + ime::mojom::ImeEngineClientPtr client) = 0; + protected: virtual ~WindowTreeHostMusDelegate() {} };
diff --git a/ui/base/ime/BUILD.gn b/ui/base/ime/BUILD.gn index 5323a67..8826b212 100644 --- a/ui/base/ime/BUILD.gn +++ b/ui/base/ime/BUILD.gn
@@ -13,15 +13,47 @@ ] } -jumbo_component("ime") { - output_name = "ui_base_ime" +jumbo_component("ime_types") { + output_name = "ui_base_ime_types" sources = [ "candidate_window.cc", "candidate_window.h", - "character_composer.cc", - "character_composer.h", "composition_text.cc", "composition_text.h", + "ime_text_span.cc", + "ime_text_span.h", + "infolist_entry.cc", + "infolist_entry.h", + ] + + defines = [ "IS_UI_BASE_IME_TYPES_IMPL" ] + + deps = [ + "//base", + "//ui/gfx/range", + ] + + public_deps = [ + ":text_input_types", + "//skia", + ] + + if (is_chromeos || use_ozone) { + sources += [ + "character_composer.cc", + "character_composer.h", + ] + deps += [ + "//ui/events:dom_keycode_converter", + "//ui/events:events", + "//ui/events:events_base", + ] + } +} + +jumbo_component("ime") { + output_name = "ui_base_ime" + sources = [ "constants.cc", "constants.h", "ime_bridge.cc", @@ -29,10 +61,6 @@ "ime_candidate_window_handler_interface.h", "ime_engine_handler_interface.h", "ime_input_context_handler_interface.h", - "ime_text_span.cc", - "ime_text_span.h", - "infolist_entry.cc", - "infolist_entry.h", "input_method.h", "input_method_base.cc", "input_method_base.h", @@ -57,11 +85,13 @@ defines = [ "IS_UI_BASE_IME_IMPL" ] public_deps = [ + ":ime_types", ":text_input_types", "//base", "//base:i18n", "//skia", "//third_party/icu", + "//ui/base/ime/mojo", "//ui/events", "//ui/events:dom_keycode_converter", "//ui/events:events",
diff --git a/ui/base/ime/candidate_window.h b/ui/base/ime/candidate_window.h index 57e40d04..82c3fac 100644 --- a/ui/base/ime/candidate_window.h +++ b/ui/base/ime/candidate_window.h
@@ -18,14 +18,14 @@ namespace ui { // CandidateWindow represents the structure of candidates generated from IME. -class COMPONENT_EXPORT(UI_BASE_IME) CandidateWindow { +class COMPONENT_EXPORT(UI_BASE_IME_TYPES) CandidateWindow { public: enum Orientation { HORIZONTAL = 0, VERTICAL = 1, }; - struct COMPONENT_EXPORT(UI_BASE_IME) CandidateWindowProperty { + struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) CandidateWindowProperty { CandidateWindowProperty(); virtual ~CandidateWindowProperty(); int page_size; @@ -41,7 +41,7 @@ }; // Represents a candidate entry. - struct COMPONENT_EXPORT(UI_BASE_IME) Entry { + struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) Entry { Entry(); Entry(const Entry& other); virtual ~Entry();
diff --git a/ui/base/ime/character_composer.h b/ui/base/ime/character_composer.h index 42baf12..57642c4 100644 --- a/ui/base/ime/character_composer.h +++ b/ui/base/ime/character_composer.h
@@ -20,7 +20,7 @@ // A class to recognize compose and dead key sequence. // Outputs composed character. -class COMPONENT_EXPORT(UI_BASE_IME) CharacterComposer { +class COMPONENT_EXPORT(UI_BASE_IME_TYPES) CharacterComposer { public: using ComposeBuffer = std::vector<DomKey>;
diff --git a/ui/base/ime/chromeos/BUILD.gn b/ui/base/ime/chromeos/BUILD.gn index aee4bc0..0c31364 100644 --- a/ui/base/ime/chromeos/BUILD.gn +++ b/ui/base/ime/chromeos/BUILD.gn
@@ -57,6 +57,7 @@ "//services/ws/public/cpp/input_devices", "//third_party/icu", "//ui/base", + "//ui/base/ime/mojo", "//ui/chromeos/strings", ] }
diff --git a/ui/base/ime/chromeos/input_method_chromeos.cc b/ui/base/ime/chromeos/input_method_chromeos.cc index bc94b4eb..587b0890 100644 --- a/ui/base/ime/chromeos/input_method_chromeos.cc +++ b/ui/base/ime/chromeos/input_method_chromeos.cc
@@ -19,12 +19,15 @@ #include "base/strings/utf_string_conversions.h" #include "base/third_party/icu/icu_utf.h" #include "chromeos/system/devicemode.h" +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/interface_request.h" #include "ui/base/ime/chromeos/ime_keyboard.h" #include "ui/base/ime/chromeos/input_method_manager.h" #include "ui/base/ime/composition_text.h" #include "ui/base/ime/ime_bridge.h" #include "ui/base/ime/ime_engine_handler_interface.h" #include "ui/base/ime/input_method_delegate.h" +#include "ui/base/ime/mojo/ime.mojom.h" #include "ui/base/ime/text_input_client.h" #include "ui/events/event.h" #include "ui/gfx/geometry/rect.h" @@ -57,6 +60,68 @@ } // namespace +// The helper to make the InputMethodChromeOS as a ime::mojom::ImeEngineClient. +// It forwards the ime::mojom::ImeEngineClient method calls toi methods of +// ui::IMEInputContextHandlerInterface methods. +// Due to the method naming conflict, InputMethodChromeOS cannot directly +// inherit from ime::mojom::ImeEngineClient. +class InputMethodChromeOS::MojoHelper : public ime::mojom::ImeEngineClient { + public: + explicit MojoHelper(InputMethodChromeOS* im) : im_(im), binding_(this) {} + ~MojoHelper() override = default; + + ime::mojom::ImeEngineProxy* ime_engine() { return ime_engine_.get(); } + + bool connected() const { return connected_; } + + void Connect() { + ime::mojom::ImeEngineClientPtr client_ptr; + binding_.Bind(mojo::MakeRequest(&client_ptr)); + connected_ = im_->delegate()->ConnectToImeEngine( + mojo::MakeRequest(&ime_engine_), std::move(client_ptr)); + } + + void Reset() { + binding_.Close(); + ime_engine_.reset(); + connected_ = false; + } + + private: + // ime::mojom::ImeEngineClient: + void CommitText(const std::string& text) override { im_->CommitText(text); } + void UpdateCompositionText(const ui::CompositionText& composition_text, + uint32_t cursor_pos, + bool visible) override { + im_->UpdateCompositionText(composition_text, cursor_pos, visible); + } + void DeleteSurroundingText(int32_t offset, uint32_t length) override { + im_->DeleteSurroundingText(offset, length); + } + void SendKeyEvent(std::unique_ptr<ui::Event> key_event) override { + im_->SendKeyEvent(key_event->AsKeyEvent()); + } + void Reconnect() override { + // Don't reconnect when the |ime_engine_| has been reset, which means the + // InputMethodChromeOS is not focused. + if (ime_engine_) { + Reset(); + Connect(); + } + } + + InputMethodChromeOS* im_; + // Whether the mojo connection is enabled. + // If true, |InputMethodChromeOS| works with ime::mojom::ImeEngine. + // If false, |InputMethodChromeOS| works with ui::IMEEngineHandlerInterface. + bool connected_ = false; + + mojo::Binding<ime::mojom::ImeEngineClient> binding_; + ime::mojom::ImeEnginePtr ime_engine_; + + DISALLOW_COPY_AND_ASSIGN(MojoHelper); +}; + // InputMethodChromeOS implementation ----------------------------------------- InputMethodChromeOS::InputMethodChromeOS( internal::InputMethodDelegate* delegate) @@ -64,6 +129,7 @@ composing_text_(false), composition_changed_(false), handling_key_event_(false), + mojo_helper_(std::make_unique<MojoHelper>(this)), weak_ptr_factory_(this) { ui::IMEBridge::Get()->SetInputContextHandler(this); @@ -150,7 +216,8 @@ // normal input field (not a password field). // Note: We need to send the key event to ibus even if the |context_| is not // enabled, so that ibus can have a chance to enable the |context_|. - if (!IsNonPasswordInputFieldFocused() || !GetEngine()) { + const bool has_engine = GetEngine() || mojo_helper_->connected(); + if (!IsNonPasswordInputFieldFocused() || !has_engine) { if (event->type() == ET_KEY_PRESSED) { if (ExecuteCharacterComposer(*event)) { // Treating as PostIME event if character composer handles key event and @@ -165,13 +232,17 @@ } handling_key_event_ = true; + ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback = base::BindOnce( + &InputMethodChromeOS::KeyEventDoneCallback, + weak_ptr_factory_.GetWeakPtr(), + // Pass the ownership of the new copied event. + base::Owned(new ui::KeyEvent(*event)), std::move(result_callback)); + if (mojo_helper_->connected()) { + mojo_helper_->ime_engine()->ProcessKeyEvent(ui::Event::Clone(*event), + std::move(callback)); + return ui::EventDispatchDetails(); + } if (GetEngine()->IsInterestedInKeyEvent()) { - ui::IMEEngineHandlerInterface::KeyEventDoneCallback callback = - base::BindOnce(&InputMethodChromeOS::KeyEventDoneCallback, - weak_ptr_factory_.GetWeakPtr(), - // Pass the ownership of the new copied event. - base::Owned(new ui::KeyEvent(*event)), - std::move(result_callback)); GetEngine()->ProcessKeyEvent(*event, std::move(callback)); return ui::EventDispatchDetails(); } @@ -227,16 +298,23 @@ UpdateContextFocusState(); - ui::IMEEngineHandlerInterface* engine = GetEngine(); - if (engine) { - // When focused input client is not changed, a text input type change should - // cause blur/focus events to engine. - // The focus in to or out from password field should also notify engine. - engine->FocusOut(); - ui::IMEEngineHandlerInterface::InputContext context( + if (mojo_helper_->connected()) { + mojo_helper_->ime_engine()->FinishInput(); + mojo_helper_->ime_engine()->StartInput(ime::mojom::EditorInfo::New( GetTextInputType(), GetTextInputMode(), GetTextInputFlags(), - GetClientFocusReason(), GetClientShouldDoLearning()); - engine->FocusIn(context); + GetClientFocusReason(), GetClientShouldDoLearning())); + } else { + ui::IMEEngineHandlerInterface* engine = GetEngine(); + if (engine) { + ui::IMEEngineHandlerInterface::InputContext context( + GetTextInputType(), GetTextInputMode(), GetTextInputFlags(), + GetClientFocusReason(), GetClientShouldDoLearning()); + // When focused input client is not changed, a text input type change + // should cause blur/focus events to engine. The focus in to or out from + // password field should also notify engine. + engine->FocusOut(); + engine->FocusIn(context); + } } OnCaretBoundsChanged(client); @@ -257,8 +335,12 @@ DCHECK(client == GetTextInputClient()); DCHECK(!IsTextInputTypeNone()); - if (GetEngine()) + if (mojo_helper_->connected()) { + mojo_helper_->ime_engine()->UpdateCompositionBounds( + GetCompositionBounds(client)); + } else if (GetEngine()) { GetEngine()->SetCompositionBounds(GetCompositionBounds(client)); + } chromeos::IMECandidateWindowHandlerInterface* candidate_window = ui::IMEBridge::Get()->GetCandidateWindowHandler(); @@ -305,12 +387,17 @@ // Here SetSurroundingText accepts relative position of |surrounding_text|, so // we have to convert |selection_range| from node coordinates to // |surrounding_text| coordinates. - if (!GetEngine()) - return; - GetEngine()->SetSurroundingText(base::UTF16ToUTF8(surrounding_text), - selection_range.start() - text_range.start(), - selection_range.end() - text_range.start(), - text_range.start()); + if (mojo_helper_->connected()) { + mojo_helper_->ime_engine()->UpdateSurroundingInfo( + base::UTF16ToUTF8(surrounding_text), + selection_range.start() - text_range.start(), + selection_range.end() - text_range.start(), text_range.start()); + } else if (GetEngine()) { + GetEngine()->SetSurroundingText( + base::UTF16ToUTF8(surrounding_text), + selection_range.start() - text_range.start(), + selection_range.end() - text_range.start(), text_range.start()); + } } void InputMethodChromeOS::CancelComposition(const TextInputClient* client) { @@ -334,13 +421,26 @@ return InputMethodBase::GetInputMethodKeyboardController(); } +void InputMethodChromeOS::OnFocus() { + InputMethodBase::OnFocus(); + mojo_helper_->Connect(); +} + +void InputMethodChromeOS::OnBlur() { + InputMethodBase::OnBlur(); + mojo_helper_->Reset(); +} + void InputMethodChromeOS::OnWillChangeFocusedClient( TextInputClient* focused_before, TextInputClient* focused) { ConfirmCompositionText(); - if (GetEngine()) + if (mojo_helper_->connected()) { + mojo_helper_->ime_engine()->FinishInput(); + } else if (GetEngine()) { GetEngine()->FocusOut(); + } } void InputMethodChromeOS::OnDidChangeFocusedClient( @@ -351,7 +451,11 @@ // focus and after it acquires focus again are the same. UpdateContextFocusState(); - if (GetEngine()) { + if (mojo_helper_->connected()) { + mojo_helper_->ime_engine()->StartInput(ime::mojom::EditorInfo::New( + GetTextInputType(), GetTextInputMode(), GetTextInputFlags(), + GetClientFocusReason(), GetClientShouldDoLearning())); + } else if (GetEngine()) { ui::IMEEngineHandlerInterface::InputContext context( GetTextInputType(), GetTextInputMode(), GetTextInputFlags(), GetClientFocusReason(), GetClientShouldDoLearning()); @@ -382,7 +486,9 @@ // Note: some input method engines may not support reset method, such as // ibus-anthy. But as we control all input method engines by ourselves, we can // make sure that all of the engines we are using support it correctly. - if (GetEngine()) + if (mojo_helper_->connected()) + mojo_helper_->ime_engine()->CancelInput(); + else if (GetEngine()) GetEngine()->Reset(); character_composer_.Reset();
diff --git a/ui/base/ime/chromeos/input_method_chromeos.h b/ui/base/ime/chromeos/input_method_chromeos.h index e7d968ca..41d809e 100644 --- a/ui/base/ime/chromeos/input_method_chromeos.h +++ b/ui/base/ime/chromeos/input_method_chromeos.h
@@ -24,6 +24,8 @@ namespace ui { +class TestableInputMethodChromeOS; + // A ui::InputMethod implementation for ChromeOS. class COMPONENT_EXPORT(UI_BASE_IME_CHROMEOS) InputMethodChromeOS : public InputMethodBase, @@ -48,6 +50,8 @@ InputMethodKeyboardController* GetInputMethodKeyboardController() override; // Overridden from InputMethodBase: + void OnFocus() override; + void OnBlur() override; void OnWillChangeFocusedClient(TextInputClient* focused_before, TextInputClient* focused) override; void OnDidChangeFocusedClient(TextInputClient* focused_before, @@ -71,7 +75,9 @@ void ResetContext(); private: + class MojoHelper; class PendingKeyEvent; + friend TestableInputMethodChromeOS; ui::EventDispatchDetails DispatchKeyEventInternal(ui::KeyEvent* event, AckCallback ack_callback); @@ -180,6 +186,8 @@ // This is used in CommitText/UpdateCompositionText/etc. bool handling_key_event_; + std::unique_ptr<MojoHelper> mojo_helper_; + // Used for making callbacks. base::WeakPtrFactory<InputMethodChromeOS> weak_ptr_factory_;
diff --git a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc index 07ad8b0..f456a48 100644 --- a/ui/base/ime/chromeos/input_method_chromeos_unittest.cc +++ b/ui/base/ime/chromeos/input_method_chromeos_unittest.cc
@@ -15,6 +15,8 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind_test_util.h" +#include "base/test/scoped_task_environment.h" +#include "mojo/public/cpp/bindings/binding.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/ime/chromeos/mock_ime_candidate_window_handler.h" @@ -25,6 +27,7 @@ #include "ui/base/ime/ime_bridge.h" #include "ui/base/ime/ime_engine_handler_interface.h" #include "ui/base/ime/input_method_delegate.h" +#include "ui/base/ime/mojo/ime.mojom.h" #include "ui/base/ime/text_input_client.h" #include "ui/events/event.h" #include "ui/events/event_utils.h" @@ -88,6 +91,10 @@ } return details; } + void CommitText(const std::string& text) override { + InputMethodChromeOS::CommitText(text); + text_committed_ = text; + } void ResetCallCount() { process_key_event_post_ime_call_count_ = 0; @@ -101,6 +108,8 @@ return process_key_event_post_ime_call_count_; } + const std::string& text_committed() const { return text_committed_; } + // Change access rights for testing. using InputMethodChromeOS::ExtractCompositionText; using InputMethodChromeOS::ResetContext; @@ -108,6 +117,7 @@ private: ProcessKeyEventPostIMEArgs process_key_event_post_ime_args_; int process_key_event_post_ime_call_count_; + std::string text_committed_; }; class SetSurroundingTextVerifier { @@ -224,6 +234,53 @@ DISALLOW_COPY_AND_ASSIGN(CachingInputMethodDelegate); }; +class MojoInputMethodDelegate : public ui::internal::InputMethodDelegate, + public ime::mojom::ImeEngine { + public: + MojoInputMethodDelegate() : engine_binding_(this) {} + ~MojoInputMethodDelegate() override = default; + + ime::mojom::ImeEngineClientProxy* engine_client() const { + return engine_client_.get(); + } + + void FlushForTesting() { engine_client_.FlushForTesting(); } + + private: + // Overridden from ui::internal::InputMethodDelegate: + ui::EventDispatchDetails DispatchKeyEventPostIME( + ui::KeyEvent* event, + DispatchKeyEventPostIMECallback callback) override { + event->StopPropagation(); + RunDispatchKeyEventPostIMECallback(event, std::move(callback)); + return ui::EventDispatchDetails(); + } + bool ConnectToImeEngine(ime::mojom::ImeEngineRequest engine_request, + ime::mojom::ImeEngineClientPtr client) override { + engine_binding_.Bind(std::move(engine_request)); + engine_client_ = std::move(client); + return true; + } + + // ime::mojom::ImeEngine: + void StartInput(ime::mojom::EditorInfoPtr info) override {} + void FinishInput() override {} + void CancelInput() override {} + void ProcessKeyEvent(std::unique_ptr<ui::Event> key_event, + ProcessKeyEventCallback callback) override {} + void UpdateSurroundingInfo(const std::string& text, + int32_t cursor, + int32_t anchor, + int32_t offset) override {} + void UpdateCompositionBounds(const std::vector<gfx::Rect>& bounds) override {} + + mojo::Binding<ime::mojom::ImeEngine> engine_binding_; + + ime::mojom::ImeEngineClientPtr engine_client_; + + DISALLOW_COPY_AND_ASSIGN(MojoInputMethodDelegate); +}; + class InputMethodChromeOSTest : public internal::InputMethodDelegate, public testing::Test, public DummyTextInputClient { @@ -388,6 +445,8 @@ TestInputMethodManager* input_method_manager_; + base::test::ScopedTaskEnvironment scoped_task_environment_; + DISALLOW_COPY_AND_ASSIGN(InputMethodChromeOSTest); }; @@ -911,6 +970,15 @@ IMEBridge::Get()->SetCurrentEngineHandler(nullptr); } +TEST_F(InputMethodChromeOSTest, MojoInteractions) { + MojoInputMethodDelegate delegate; + TestableInputMethodChromeOS im(&delegate); + im.OnFocus(); + delegate.engine_client()->CommitText("test"); + delegate.FlushForTesting(); + EXPECT_EQ("test", im.text_committed()); +} + class InputMethodChromeOSKeyEventTest : public InputMethodChromeOSTest { public: InputMethodChromeOSKeyEventTest() {}
diff --git a/ui/base/ime/composition_text.h b/ui/base/ime/composition_text.h index ba7b76f..cddf445e 100644 --- a/ui/base/ime/composition_text.h +++ b/ui/base/ime/composition_text.h
@@ -15,7 +15,7 @@ namespace ui { // A struct represents the status of an ongoing composition text. -struct COMPONENT_EXPORT(UI_BASE_IME) CompositionText { +struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) CompositionText { CompositionText(); CompositionText(const CompositionText& other); ~CompositionText();
diff --git a/ui/base/ime/ime_text_span.h b/ui/base/ime/ime_text_span.h index 4125a3b..4e449567 100644 --- a/ui/base/ime/ime_text_span.h +++ b/ui/base/ime/ime_text_span.h
@@ -18,7 +18,7 @@ // Intentionally keep sync with blink::WebImeTextSpan defined in: // third_party/WebKit/public/web/WebImeTextSpan.h -struct COMPONENT_EXPORT(UI_BASE_IME) ImeTextSpan { +struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) ImeTextSpan { enum class Type { // Creates a composition marker. kComposition,
diff --git a/ui/base/ime/infolist_entry.h b/ui/base/ime/infolist_entry.h index 107db39..54d6320 100644 --- a/ui/base/ime/infolist_entry.h +++ b/ui/base/ime/infolist_entry.h
@@ -11,7 +11,7 @@ namespace ui { // The data model of infolist window. -struct COMPONENT_EXPORT(UI_BASE_IME) InfolistEntry { +struct COMPONENT_EXPORT(UI_BASE_IME_TYPES) InfolistEntry { base::string16 title; base::string16 body; bool highlighted;
diff --git a/ui/base/ime/input_method_delegate.cc b/ui/base/ime/input_method_delegate.cc index dc950847..92c25586 100644 --- a/ui/base/ime/input_method_delegate.cc +++ b/ui/base/ime/input_method_delegate.cc
@@ -5,11 +5,18 @@ #include "ui/base/ime/input_method_delegate.h" #include "base/callback.h" +#include "ui/base/ime/mojo/ime.mojom.h" #include "ui/events/event.h" namespace ui { namespace internal { +bool InputMethodDelegate::ConnectToImeEngine( + ::ime::mojom::ImeEngineRequest engine_request, + ::ime::mojom::ImeEngineClientPtr client) { + return false; +} + // static void InputMethodDelegate::RunDispatchKeyEventPostIMECallback( KeyEvent* key_event,
diff --git a/ui/base/ime/input_method_delegate.h b/ui/base/ime/input_method_delegate.h index a0bcccd2..324982e 100644 --- a/ui/base/ime/input_method_delegate.h +++ b/ui/base/ime/input_method_delegate.h
@@ -7,6 +7,17 @@ #include "base/callback_forward.h" #include "base/component_export.h" +#include "mojo/public/cpp/bindings/interface_ptr.h" +#include "mojo/public/cpp/bindings/interface_request.h" + +namespace ime { +namespace mojom { + +class ImeEngine; +class ImeEngineClient; + +} // namespace mojom +} // namespace ime namespace ui { @@ -34,6 +45,10 @@ KeyEvent* key_event, DispatchKeyEventPostIMECallback callback) = 0; + virtual bool ConnectToImeEngine( + mojo::InterfaceRequest<::ime::mojom::ImeEngine> engine_request, + mojo::InterfacePtr<::ime::mojom::ImeEngineClient> client); + protected: static void RunDispatchKeyEventPostIMECallback( KeyEvent* key_event,
diff --git a/ui/base/ime/mojo/ime.mojom b/ui/base/ime/mojo/ime.mojom index 993922c4..d28cbf8d 100644 --- a/ui/base/ime/mojo/ime.mojom +++ b/ui/base/ime/mojo/ime.mojom
@@ -60,6 +60,25 @@ // (e.g. by IME's on-screen keyboard) // - later after the IME responds the |ProcessKeyEvent| with the result; interface ImeEngineClient { + // Called when the IME wants to insert the |text| to the input field. + CommitText(string text); + + // Called when the IME wants to generate/update the composition text to the + // input field. + UpdateCompositionText(ui.mojom.CompositionText composition_text, + uint32 cursor_pos, + bool visible); + + // Called when the IME wants to remove a piece of text in the input field. + DeleteSurroundingText(int32 offset, uint32 length); + + // Called when the IME wants to silumate a physical key event to the app. + // Usually this is for on-screen keyboard support (e.g. simulate Enter key). + SendKeyEvent(ui.mojom.Event key_event); + + // Called when the ImeEngine is deactivated and this client should reconnect + // for the new active ImeEngine. + Reconnect(); }; // Implemented by the IME.
diff --git a/ui/base/ime/mojo/ime_types.typemap b/ui/base/ime/mojo/ime_types.typemap index 4e800fc6..acdc8fff 100644 --- a/ui/base/ime/mojo/ime_types.typemap +++ b/ui/base/ime/mojo/ime_types.typemap
@@ -15,7 +15,7 @@ "//ui/base/ime/mojo/ime_types_struct_traits.cc", ] public_deps = [ - "//ui/base/ime", + "//ui/base/ime:ime_types", ] deps = [ "//ui/gfx/range",
diff --git a/ui/keyboard/BUILD.gn b/ui/keyboard/BUILD.gn index 107da45..1cbb657 100644 --- a/ui/keyboard/BUILD.gn +++ b/ui/keyboard/BUILD.gn
@@ -171,6 +171,7 @@ "//base", "//base/test:test_support", "//components/ukm:test_support", + "//mojo/core/embedder", "//services/service_manager/public/cpp", "//testing/gmock", "//testing/gtest",
diff --git a/ui/keyboard/test/run_all_unittests.cc b/ui/keyboard/test/run_all_unittests.cc index 9d0da8c..2b3a1706 100644 --- a/ui/keyboard/test/run_all_unittests.cc +++ b/ui/keyboard/test/run_all_unittests.cc
@@ -8,6 +8,7 @@ #include "base/path_service.h" #include "base/test/launcher/unit_test_launcher.h" #include "base/test/test_suite.h" +#include "mojo/core/embedder/embedder.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/aura/env.h" #include "ui/base/resource/resource_bundle.h" @@ -49,6 +50,7 @@ int main(int argc, char** argv) { KeyboardTestSuite test_suite(argc, argv); + mojo::core::Init(); return base::LaunchUnitTests( argc, argv, base::BindOnce(&KeyboardTestSuite::Run, base::Unretained(&test_suite)));
diff --git a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc index 7385a97..761a10c 100644 --- a/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc +++ b/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
@@ -286,7 +286,7 @@ const int hit; } kTestCases[] = { #if defined(OS_WIN) - {0, is_aero_glass_enabled ? HTTRANSPARENT : HTCAPTION}, + {0, is_aero_glass_enabled ? HTTRANSPARENT : HTNOWHERE}, #else {0, HTTRANSPARENT}, #endif
diff --git a/ui/views/bubble/bubble_frame_view.cc b/ui/views/bubble/bubble_frame_view.cc index a6a60190..3828c024 100644 --- a/ui/views/bubble/bubble_frame_view.cc +++ b/ui/views/bubble/bubble_frame_view.cc
@@ -181,6 +181,19 @@ if (close_->visible() && close_->GetMirroredBounds().Contains(point)) return HTCLOSE; + // Allow dialogs to show the system menu and be dragged. + if (GetWidget()->widget_delegate()->AsDialogDelegate() && + !GetWidget()->widget_delegate()->AsBubbleDialogDelegate()) { + gfx::Rect bounds(GetContentsBounds()); + bounds.Inset(title_margins_); + gfx::Rect sys_rect(0, 0, bounds.x(), bounds.y()); + sys_rect.set_origin(gfx::Point(GetMirroredXForRect(sys_rect), 0)); + if (sys_rect.Contains(point)) + return HTSYSMENU; + if (point.y() < title()->bounds().bottom()) + return HTCAPTION; + } + // Convert to RRectF to accurately represent the rounded corners of the // dialog and allow events to pass through the shadows. gfx::RRectF round_contents_bounds(gfx::RectF(GetContentsBounds()), @@ -191,16 +204,6 @@ if (!round_contents_bounds.Contains(rectf_point)) return HTTRANSPARENT; - if (HasTitle() && point.y() < title()->bounds().bottom()) { - auto* dialog_delegate = GetWidget()->widget_delegate()->AsDialogDelegate(); - // Allow the dialog to be dragged if it is not modal. This can happen if the - // dialog has no parent browser window. - if (dialog_delegate && - dialog_delegate->GetModalType() == ui::MODAL_TYPE_NONE) { - return HTCAPTION; - } - } - return GetWidget()->client_view()->NonClientHitTest(point); }
diff --git a/ui/views/controls/link.cc b/ui/views/controls/link.cc index befcf5d..25e54af5 100644 --- a/ui/views/controls/link.cc +++ b/ui/views/controls/link.cc
@@ -166,11 +166,6 @@ node_data->role = ax::mojom::Role::kLink; } -void Link::OnEnabledChanged() { - RecalculateFont(); - View::OnEnabledChanged(); // Jump over Label. -} - void Link::OnFocus() { Label::OnFocus(); RecalculateFont(); @@ -223,6 +218,9 @@ underline_ = GetDefaultFocusStyle() != FocusStyle::UNDERLINE; RecalculateFont(); + enabled_changed_subscription_ = AddEnabledChangedCallback( + base::BindRepeating(&Link::RecalculateFont, base::Unretained(this))); + // Label::Init() calls SetText(), but if that's being called from Label(), our // SetText() override will not be reached (because the constructed class is // only a Label at the moment, not yet a Link). So explicitly configure focus
diff --git a/ui/views/controls/link.h b/ui/views/controls/link.h index 27c73ed..0764dfa 100644 --- a/ui/views/controls/link.h +++ b/ui/views/controls/link.h
@@ -67,7 +67,6 @@ void OnGestureEvent(ui::GestureEvent* event) override; bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override; void GetAccessibleNodeData(ui::AXNodeData* node_data) override; - void OnEnabledChanged() override; void OnFocus() override; void OnBlur() override; void SetFontList(const gfx::FontList& font_list) override; @@ -105,6 +104,8 @@ SkColor requested_enabled_color_; bool requested_enabled_color_set_; + PropertyChangedSubscription enabled_changed_subscription_; + DISALLOW_COPY_AND_ASSIGN(Link); };
diff --git a/ui/views/view.cc b/ui/views/view.cc index eebe9cf..1b2f567 100644 --- a/ui/views/view.cc +++ b/ui/views/view.cc
@@ -457,20 +457,25 @@ return visible_ && parent_ ? parent_->IsDrawn() : false; } -void View::SetEnabled(bool enabled) { - if (enabled != enabled_) { - enabled_ = enabled; - AdvanceFocusIfNecessary(); +void View::SetEnabled(bool is_enabled) { + if (enabled_ == is_enabled) + return; - OnEnabledChanged(); + enabled_ = is_enabled; + AdvanceFocusIfNecessary(); + OnPropertyChanged(&enabled_, kPropertyEffectsPaint); - for (ViewObserver& observer : observers_) - observer.OnViewEnabledChanged(this); - } + // TODO(kylixrd): Remove this once all overridden instances are refactored + // to use property change callback. + OnEnabledChanged(); +} + +PropertyChangedSubscription View::AddEnabledChangedCallback( + PropertyChangedCallback callback) { + return AddPropertyChangedCallback(&enabled_, std::move(callback)); } void View::OnEnabledChanged() { - SchedulePaint(); } View::Views View::GetChildrenInZOrder() { @@ -1224,7 +1229,7 @@ bool View::CanHandleAccelerators() const { const Widget* widget = GetWidget(); - if (!enabled() || !IsDrawn() || !widget || !widget->IsVisible()) + if (!GetEnabled() || !IsDrawn() || !widget || !widget->IsVisible()) return false; #if defined(USE_AURA) && !defined(OS_CHROMEOS) // Non-ChromeOS aura windows have an associated FocusManagerEventHandler which @@ -1278,11 +1283,11 @@ } bool View::IsFocusable() const { - return focus_behavior_ == FocusBehavior::ALWAYS && enabled_ && IsDrawn(); + return focus_behavior_ == FocusBehavior::ALWAYS && GetEnabled() && IsDrawn(); } bool View::IsAccessibilityFocusable() const { - return focus_behavior_ != FocusBehavior::NEVER && enabled_ && IsDrawn(); + return focus_behavior_ != FocusBehavior::NEVER && GetEnabled() && IsDrawn(); } FocusManager* View::GetFocusManager() { @@ -1849,6 +1854,40 @@ return PaintInfo::ScaleType::kScaleWithEdgeSnapping; } +void View::HandlePropertyChangeEffects(PropertyEffects effects) { + if (effects & kPropertyEffectsLayout) + InvalidateLayout(); + if (effects & kPropertyEffectsPaint) + SchedulePaint(); +} + +PropertyChangedSubscription View::AddPropertyChangedCallback( + PropertyKey property, + PropertyChangedCallback callback) { + auto entry = property_changed_vectors_.find(property); + if (entry == property_changed_vectors_.end()) { + entry = property_changed_vectors_ + .emplace(property, std::make_unique<PropertyChangedCallbacks>()) + .first; + } + PropertyChangedCallbacks* property_changed_callbacks = entry->second.get(); + + return property_changed_callbacks->Add(std::move(callback)); +} + +void View::OnPropertyChanged(PropertyKey property, + PropertyEffects property_effects) { + if (property_effects != kPropertyEffectsNone) + HandlePropertyChangeEffects(property_effects); + + auto entry = property_changed_vectors_.find(property); + if (entry == property_changed_vectors_.end()) + return; + + PropertyChangedCallbacks* property_changed_callbacks = entry->second.get(); + property_changed_callbacks->Notify(); +} + //////////////////////////////////////////////////////////////////////////////// // View, private: @@ -2433,10 +2472,10 @@ event.IsRightMouseButton() ? context_menu_controller_ : nullptr; View::DragInfo* drag_info = GetDragInfo(); - const bool enabled = enabled_; + const bool was_enabled = GetEnabled(); const bool result = OnMousePressed(event); - if (!enabled) + if (!was_enabled) return result; if (event.IsOnlyRightMouseButton() && context_menu_controller &&
diff --git a/ui/views/view.h b/ui/views/view.h index 125ac49..eccdf5a6 100644 --- a/ui/views/view.h +++ b/ui/views/view.h
@@ -15,6 +15,9 @@ #include <utility> #include <vector> +#include "base/bind.h" +#include "base/callback.h" +#include "base/callback_list.h" #include "base/compiler_specific.h" #include "base/i18n/rtl.h" #include "base/logging.h" @@ -118,6 +121,27 @@ View* move_view; }; +// Used to identify the CallbackList<> within the PropertyChangedVectors map. +using PropertyKey = const void*; + +using PropertyChangedCallbacks = base::CallbackList<void()>; +using PropertyChangedCallback = PropertyChangedCallbacks::CallbackType; +using PropertyChangedSubscription = + std::unique_ptr<PropertyChangedCallbacks::Subscription>; + +// The elements in PropertyEffects represent bits which define what effect(s) a +// changed Property has on the containing class. Additional elements should +// use the next most significant bit. +enum PropertyEffects { + kPropertyEffectsNone = 0, + // Any changes to the property should cause the container to invalidate the + // current layout state. + kPropertyEffectsLayout = 0x00000001, + // Changes to the property should cause the container to schedule a painting + // update. + kPropertyEffectsPaint = 0x00000002, +}; + ///////////////////////////////////////////////////////////////////////////// // // View class @@ -142,6 +166,69 @@ // Unless otherwise documented, views is not thread safe and should only be // accessed from the main thread. // +// Properties ------------------ +// +// Properties which are intended to be dynamically visible through metadata to +// other subsystems, such as dev-tools must adhere to a naming convention, +// usage and implementation patterns. +// +// Properties start with their base name, such as "Frobble" (note the +// capitalization). The method to set the property must be called SetXXXX and +// the method to retrieve the value is called GetXXXX. For the aforementioned +// Frobble property, this would be SetFrobble and GetFrobble. +// +// void SetFrobble(bool is_frobble); +// bool GetFrobble() const; +// +// In the SetXXXX method, after the value storage location has been updated, +// OnPropertyChanged() must be called using the address of the storage +// location as a key. Additionally, any combination of PropertyEffects are +// also passed in. This will ensure that any desired side effects are properly +// invoked. +// +// void View::SetFrobble(bool is_frobble) { +// if (is_frobble == frobble_) +// return; +// frobble_ = is_frobble; +// OnPropertyChanged(&frobble_, kPropertyEffectsPaint); +// } +// +// Each property should also have a way to "listen" to changes by registering +// a callback. +// +// PropertyChangedSubscription AddFrobbleChangedCallback( +// PropertyChangedCallback callback) WARN_UNUSED_RETURN; +// +// Each callback uses the the existing base::Bind mechanisms which allow for +// various kinds of callbacks; object methods, normal functions and lambdas. +// +// Example: +// +// class FrobbleView : public View { +// ... +// private: +// void OnFrobbleChanged(); +// PropertyChangeSubscription frobble_changed_subscription_; +// } +// +// ... +// frobble_changed_subscription_ = AddFrobbleChangedCallback( +// base::BindRepeating(&FrobbleView::OnFrobbleChanged, +// base::Unretained(this))); +// +// Example: +// +// void MyView::ValidateFrobbleChanged() { +// bool frobble_changed = false; +// PropertyChangedSubscription subscription = +// frobble_view_->AddFrobbleChangedCallback( +// base::BindRepeating([](bool* frobble_changed_ptr) { +// *frobble_changed_ptr = true; +// }, &frobble_changed)); +// frobble_view_->SetFrobble(!frobble_view_->GetFrobble()); +// LOG() << frobble_changed ? "Frobble changed" : "Frobble NOT changed!"; +// } +// ///////////////////////////////////////////////////////////////////////////// class VIEWS_EXPORT View : public ui::LayerDelegate, public ui::LayerOwner, @@ -440,12 +527,23 @@ // Returns true if this view is drawn on screen. virtual bool IsDrawn() const; + // The |Enabled| property. See comment above for instructions on declaring and + // implementing a property. + // // Set whether this view is enabled. A disabled view does not receive keyboard // or mouse inputs. If |enabled| differs from the current value, SchedulePaint // is invoked. Also, clears focus if the focused view is disabled. - void SetEnabled(bool enabled); - + void SetEnabled(bool is_enabled); // Returns whether the view is enabled. + bool GetEnabled() const { return enabled_; } + + // Adds a callback subscription associated with the above |Enabled| property. + // The callback will be invoked whenever the property changes. + PropertyChangedSubscription AddEnabledChangedCallback( + PropertyChangedCallback callback) WARN_UNUSED_RESULT; + + // NOTE: Deprecated. Please use GetEnabled() which is the getter for the + // |Enabled| property. bool enabled() const { return enabled_; } // Returns the child views ordered in reverse z-order. That is, views later in @@ -1424,6 +1522,14 @@ // hierarchy). virtual void OnNativeThemeChanged(const ui::NativeTheme* theme) {} + // Property Support ---------------------------------------------------------- + + PropertyChangedSubscription AddPropertyChangedCallback( + PropertyKey property, + PropertyChangedCallback callback); + void OnPropertyChanged(PropertyKey property, + PropertyEffects property_effects); + private: friend class internal::PreEventDispatchHandler; friend class internal::PostEventDispatchHandler; @@ -1438,6 +1544,9 @@ FRIEND_TEST_ALL_PREFIXES(ViewTest, PaintWithMovedViewUsesCacheInRTL); FRIEND_TEST_ALL_PREFIXES(ViewTest, PaintWithUnknownInvalidation); + using PropertyChangedVectors = + std::map<PropertyKey, std::unique_ptr<PropertyChangedCallbacks>>; + // Painting ----------------------------------------------------------------- // Invoked before and after the bounds change to schedule painting the old and @@ -1692,6 +1801,12 @@ const gfx::Point& press_pt, ui::DragDropTypes::DragEventSource source); + // Property support ---------------------------------------------------------- + + // Called from OnPropertyChanged with the given set of property effects. This + // function is NOT called if effects == kPropertyEffectsNone. + void HandlePropertyChangeEffects(PropertyEffects effects); + ////////////////////////////////////////////////////////////////////////////// // Creation and lifetime ----------------------------------------------------- @@ -1852,10 +1967,13 @@ // Manages the accessibility interface for this View. std::unique_ptr<ViewAccessibility> view_accessibility_; - // Observers ------------------------------------------------------------- + // Observers ----------------------------------------------------------------- base::ObserverList<ViewObserver>::Unchecked observers_; + // Property Changed Callbacks ------------------------------------------------ + PropertyChangedVectors property_changed_vectors_; + DISALLOW_COPY_AND_ASSIGN(View); };
diff --git a/ui/views/view_observer.h b/ui/views/view_observer.h index bcd0a61..39695be 100644 --- a/ui/views/view_observer.h +++ b/ui/views/view_observer.h
@@ -26,9 +26,6 @@ // View::IsDrawn() for details on how visibility and drawn differ. virtual void OnViewVisibilityChanged(View* observed_view) {} - // Called when View::SetEnabled() is called with a new value. - virtual void OnViewEnabledChanged(View* observed_view) {} - // Called from View::PreferredSizeChanged(). virtual void OnViewPreferredSizeChanged(View* observed_view) {}
diff --git a/ui/views/view_unittest.cc b/ui/views/view_unittest.cc index 46e3f804..174b0ac 100644 --- a/ui/views/view_unittest.cc +++ b/ui/views/view_unittest.cc
@@ -9,6 +9,7 @@ #include <map> #include <memory> +#include "base/bind.h" #include "base/command_line.h" #include "base/i18n/rtl.h" #include "base/macros.h" @@ -4979,6 +4980,17 @@ EXPECT_EQ(layers_after_attached[1], child_view1->layer()); } +TEST_F(ViewTest, TestEnabledChangedCallback) { + View test_view; + bool enabled_changed = false; + auto subscription = test_view.AddEnabledChangedCallback(base::BindRepeating( + [](bool* enabled_changed) { *enabled_changed = true; }, + &enabled_changed)); + test_view.SetEnabled(false); + EXPECT_TRUE(enabled_changed); + EXPECT_FALSE(test_view.enabled()); +} + //////////////////////////////////////////////////////////////////////////////// // Observer tests. //////////////////////////////////////////////////////////////////////////////// @@ -5005,10 +5017,6 @@ view_visibility_changed_ = view; } - void OnViewEnabledChanged(View* view) override { - view_enabled_changed_ = view; - } - void OnViewBoundsChanged(View* view) override { view_bounds_changed_ = view; } void OnChildViewReordered(View* parent, View* view) override { @@ -5023,7 +5031,6 @@ child_view_removed_ = nullptr; child_view_removed_parent_ = nullptr; view_visibility_changed_ = nullptr; - view_enabled_changed_ = nullptr; view_bounds_changed_ = nullptr; view_reordered_ = nullptr; } @@ -5047,7 +5054,6 @@ const View* view_visibility_changed() const { return view_visibility_changed_; } - const View* view_enabled_changed() const { return view_enabled_changed_; } const View* view_bounds_changed() const { return view_bounds_changed_; } const View* view_reordered() const { return view_reordered_; } @@ -5060,7 +5066,6 @@ View* child_view_removed_ = nullptr; View* child_view_removed_parent_ = nullptr; View* view_visibility_changed_ = nullptr; - View* view_enabled_changed_ = nullptr; View* view_bounds_changed_ = nullptr; View* view_reordered_ = nullptr; @@ -5105,13 +5110,6 @@ EXPECT_FALSE(view->visible()); } -TEST_F(ViewObserverTest, ViewEnabledChanged) { - std::unique_ptr<View> view = NewView(); - view->SetEnabled(false); - EXPECT_EQ(view.get(), view_enabled_changed()); - EXPECT_FALSE(view->enabled()); -} - TEST_F(ViewObserverTest, ViewBoundsChanged) { std::unique_ptr<View> view = NewView(); gfx::Rect bounds(2, 2, 2, 2);
diff --git a/ui/views/window/dialog_delegate_unittest.cc b/ui/views/window/dialog_delegate_unittest.cc index 8aa6955..b8e92a1 100644 --- a/ui/views/window/dialog_delegate_unittest.cc +++ b/ui/views/window/dialog_delegate_unittest.cc
@@ -98,13 +98,6 @@ views::Textfield* input() { return input_; } - ui::ModalType GetModalType() const override { - return modal_type_none_ ? ui::MODAL_TYPE_NONE : ui::MODAL_TYPE_WINDOW; - } - void set_modal_type_none(bool modal_type_none) { - modal_type_none_ = modal_type_none; - } - private: views::Textfield* input_; bool canceled_ = false; @@ -116,7 +109,6 @@ bool show_close_button_ = true; bool should_handle_escape_ = false; int dialog_buttons_ = ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL; - bool modal_type_none_ = false; DISALLOW_COPY_AND_ASSIGN(TestDialog); }; @@ -224,22 +216,22 @@ const NonClientView* view = dialog()->GetWidget()->non_client_view(); BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view()); - constexpr struct { + struct { const int point; const int hit; - } kCases[] = { - {0, HTTRANSPARENT}, - {10, HTNOWHERE}, + } cases[] = { + {0, HTSYSMENU}, + {10, HTSYSMENU}, {20, HTNOWHERE}, {50, HTCLIENT /* Space is reserved for the close button. */}, {60, HTCLIENT}, {1000, HTNOWHERE}, }; - for (const auto test_case : kCases) { - gfx::Point point(test_case.point, test_case.point); - EXPECT_EQ(test_case.hit, frame->NonClientHitTest(point)) - << " at point " << test_case.point; + for (size_t i = 0; i < base::size(cases); ++i) { + gfx::Point point(cases[i].point, cases[i].point); + EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point)) + << " case " << i << " at point " << cases[i].point; } } @@ -251,18 +243,18 @@ const NonClientView* view = dialog()->GetWidget()->non_client_view(); BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view()); - constexpr struct { + struct { const int point; const int hit; - } kCases[] = { - {0, HTTRANSPARENT}, {10, HTCLIENT}, {20, HTCLIENT}, - {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, + } cases[] = { + {0, HTSYSMENU}, {10, HTSYSMENU}, {20, HTCLIENT}, + {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, }; - for (const auto test_case : kCases) { - gfx::Point point(test_case.point, test_case.point); - EXPECT_EQ(test_case.hit, frame->NonClientHitTest(point)) - << " at point " << test_case.point; + for (size_t i = 0; i < base::size(cases); ++i) { + gfx::Point point(cases[i].point, cases[i].point); + EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point)) + << " case " << i << " at point " << cases[i].point; } } @@ -274,43 +266,18 @@ dialog()->GetWidget()->LayoutRootViewIfNecessary(); BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view()); - constexpr struct { + struct { const int point; const int hit; - } kCases[] = { - {0, HTTRANSPARENT}, {10, HTNOWHERE}, {20, HTNOWHERE}, - {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, + } cases[] = { + {0, HTSYSMENU}, {10, HTSYSMENU}, {20, HTCAPTION}, + {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, }; - for (const auto test_case : kCases) { - gfx::Point point(test_case.point, test_case.point); - EXPECT_EQ(test_case.hit, frame->NonClientHitTest(point)) - << " at point " << test_case.point; - } -} - -TEST_F(DialogTest, HitTest_ModalTypeNone_WithTitle) { - // Ensure that BubbleFrameView hit-tests as expected when the title is shown - // and the modal type is none. - const NonClientView* view = dialog()->GetWidget()->non_client_view(); - dialog()->set_title(base::ASCIIToUTF16("Title")); - dialog()->GetWidget()->UpdateWindowTitle(); - dialog()->set_modal_type_none(true); - dialog()->GetWidget()->LayoutRootViewIfNecessary(); - BubbleFrameView* frame = static_cast<BubbleFrameView*>(view->frame_view()); - - constexpr struct { - const int point; - const int hit; - } kCases[] = { - {0, HTTRANSPARENT}, {10, HTCAPTION}, {20, HTCAPTION}, - {50, HTCLIENT}, {60, HTCLIENT}, {1000, HTNOWHERE}, - }; - - for (const auto test_case : kCases) { - gfx::Point point(test_case.point, test_case.point); - EXPECT_EQ(test_case.hit, frame->NonClientHitTest(point)) - << " at point " << test_case.point; + for (size_t i = 0; i < base::size(cases); ++i) { + gfx::Point point(cases[i].point, cases[i].point); + EXPECT_EQ(cases[i].hit, frame->NonClientHitTest(point)) + << " at point " << cases[i].point; } }
diff --git a/url/url_canon_pathurl.cc b/url/url_canon_pathurl.cc index 494fbdaf..36fbce8e 100644 --- a/url/url_canon_pathurl.cc +++ b/url/url_canon_pathurl.cc
@@ -16,13 +16,12 @@ // Canonicalize the given |component| from |source| into |output| and // |new_component|. If |separator| is non-zero, it is pre-pended to |output| // prior to the canonicalized component; i.e. for the '?' or '#' characters. -template<typename CHAR, typename UCHAR> -bool DoCanonicalizePathComponent(const CHAR* source, +template <typename CHAR, typename UCHAR> +void DoCanonicalizePathComponent(const CHAR* source, const Component& component, char separator, CanonOutput* output, Component* new_component) { - bool success = true; if (component.is_valid()) { if (separator) output->push_back(separator); @@ -34,7 +33,7 @@ for (int i = component.begin; i < end; i++) { UCHAR uch = static_cast<UCHAR>(source[i]); if (uch < 0x20 || uch >= 0x80) - success &= AppendUTF8EscapedChar(source, &i, end, output); + AppendUTF8EscapedChar(source, &i, end, output); else output->push_back(static_cast<char>(uch)); } @@ -43,7 +42,6 @@ // Empty part. new_component->reset(); } - return success; } template <typename CHAR, typename UCHAR> @@ -63,12 +61,15 @@ new_parsed->port.reset(); // We allow path URLs to have the path, query and fragment components, but we // will canonicalize each of the via the weaker path URL rules. - success &= DoCanonicalizePathComponent<CHAR, UCHAR>( - source.path, parsed.path, '\0', output, &new_parsed->path); - success &= DoCanonicalizePathComponent<CHAR, UCHAR>( - source.query, parsed.query, '?', output, &new_parsed->query); - success &= DoCanonicalizePathComponent<CHAR, UCHAR>( - source.ref, parsed.ref, '#', output, &new_parsed->ref); + // + // Note: parsing the path part should never cause a failure, see + // https://url.spec.whatwg.org/#cannot-be-a-base-url-path-state + DoCanonicalizePathComponent<CHAR, UCHAR>(source.path, parsed.path, '\0', + output, &new_parsed->path); + DoCanonicalizePathComponent<CHAR, UCHAR>(source.query, parsed.query, '?', + output, &new_parsed->query); + DoCanonicalizePathComponent<CHAR, UCHAR>(source.ref, parsed.ref, '#', output, + &new_parsed->ref); return success; }
diff --git a/url/url_canon_unittest.cc b/url/url_canon_unittest.cc index 3f80036..5a487ca 100644 --- a/url/url_canon_unittest.cc +++ b/url/url_canon_unittest.cc
@@ -1873,9 +1873,13 @@ const char* input; const char* expected; } path_cases[] = { - {"javascript:", "javascript:"}, - {"JavaScript:Foo", "javascript:Foo"}, - {"Foo:\":This /is interesting;?#", "foo:\":This /is interesting;?#"}, + {"javascript:", "javascript:"}, + {"JavaScript:Foo", "javascript:Foo"}, + {"Foo:\":This /is interesting;?#", "foo:\":This /is interesting;?#"}, + + // Validation errors should not cause failure. See + // https://crbug.com/925614. + {"javascript:\uFFFF", "javascript:%EF%BF%BD"}, }; for (size_t i = 0; i < base::size(path_cases); i++) {