diff --git a/DEPS b/DEPS index 452cfd8..16a4acf9 100644 --- a/DEPS +++ b/DEPS
@@ -248,7 +248,7 @@ # luci-go CIPD package version. # Make sure the revision is uploaded by infra-packagers builder. # https://ci.chromium.org/p/infra-internal/g/infra-packagers/console - 'luci_go': 'git_revision:74734688ffc9d2807cda0d1dc7752197480de29e', + 'luci_go': 'git_revision:a9a10995e2889126ace91faf4052949e38c69d33', # This can be overridden, e.g. with custom_vars, to build clang from HEAD # instead of downloading the prebuilt pinned revision. @@ -299,7 +299,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'src_internal_revision': '4c4da7a117aa9100f7a27e9f37a7e92b4bfcde60', + 'src_internal_revision': 'f968a67f8ed26827ecdbf84d5cb239dc600692f8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. @@ -311,7 +311,7 @@ # 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': '432d1d1efdbd0e8d5788529fe193e0eb1e8456bf', + 'angle_revision': '3b77a177ba09c418046d232e7f16dd402f10ef1c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -335,7 +335,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling googletest # and whatever else without interference from each other. - 'googletest_revision': '59c924bc471cefea25a7cf7eb40b6c101b170b12', + 'googletest_revision': '04ee1b4f2aefdffb0135d7cf2a2c519fe50dabe4', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lighttpd # and whatever else without interference from each other. @@ -375,7 +375,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': '0f4bac59a38c6aa5ad9874778f822d76ea737d35', + 'catapult_revision': '1591e813b66e04a5b9d9e8fc5d94e74ef4effaa1', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. @@ -395,7 +395,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '6c841fc0da4e1eeec9f198fd14167572e1f6656a', + 'devtools_frontend_revision': '503afe09a5c33d317399ceb4278bcd59b2f3de0b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -527,7 +527,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling llvm-libc # and whatever else without interference from each other. - 'compiler_rt_revision': 'cf8cac9f64ff4ac6fd2041a699dd86f717c63586', + 'compiler_rt_revision': '6558e6a3eacafd269527cf2595e0e722f117c1e6', # If you change this, also update the libc++ revision in # //buildtools/deps_revisions.gni. @@ -1152,7 +1152,7 @@ }, 'src/chrome/release_scripts': { - 'url': Var('chrome_git') + '/chrome/tools/release/scripts' + '@' + '6ad235a921b16b76e60316629f799e4fef593769', + 'url': Var('chrome_git') + '/chrome/tools/release/scripts' + '@' + '38a00a22c91fb29e2b8f6e88fae3d151a52e8f21', 'condition': 'checkout_chrome_release_scripts', }, @@ -1495,7 +1495,7 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - 'cfb3b184379b5491aafc36c95a2d8effd010eea2', + 'b8e94f74cdf17fd4bad068bed25f841a4b566dce', 'condition': 'checkout_android and checkout_src_internal', }, @@ -1987,7 +1987,7 @@ 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'e6596746dc95fe658b3a5f0924c10e322c7d8e22', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '354f6026f14f87466040e3e1878c599138a23bce', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -2949,7 +2949,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/linux-amd64', - 'version': 'NtaId8DHFYM0HEPBE-dRD6zfLa9-6IjHXfsuAdzJzLEC', + 'version': 'srGbc-O6bVQmBoT6VLvP66h6Be4A-nffx4UhixUJ9w0C', }, ], 'dep_type': 'cipd', @@ -2959,7 +2959,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/windows-amd64', - 'version': 'tRO9OhKyiYkium4C_kayNwnY6PIgcWtDksS3QxJwOXMC', + 'version': 'zasiUhQIHGZ2e60_M6g41oz8mYgPta5JmOWV5LwFjGMC', }, ], 'dep_type': 'cipd', @@ -2970,7 +2970,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-amd64', - 'version': 'EpMC1Y5vZrdaOqYJF8868kIiqwwGIGE6ysHYLu7_6CkC', + 'version': 'tZvHxy8AcDJhO9A-5UuZKL_-5vfE_wC-RBkElqWZpM4C', }, ], 'dep_type': 'cipd', @@ -2981,7 +2981,7 @@ 'packages': [ { 'package': 'skia/tools/goldctl/mac-arm64', - 'version': 'iFehV3QPYIc0N4dnQVxK8HAHV_drYY-V7czzW0ipQdsC', + 'version': '2br8hIWKHDAaOt77siYyRUclHBYUZX6dj8jtogL90nwC', }, ], 'dep_type': 'cipd', @@ -4623,7 +4623,7 @@ 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - '28300a0a975163d53866dc59929e600f3a9917bc', + '976b8f41d35f356dd01e2dc99e317dbafb032477', 'condition': 'checkout_src_internal', },
diff --git a/android_webview/nonembedded/component_updater/aw_component_update_service_test.cc b/android_webview/nonembedded/component_updater/aw_component_update_service_test.cc index e9fe3ef3..8626a167 100644 --- a/android_webview/nonembedded/component_updater/aw_component_update_service_test.cc +++ b/android_webview/nonembedded/component_updater/aw_component_update_service_test.cc
@@ -103,6 +103,7 @@ /* network_error= */ -2, /* header_etag= */ "", /* header_x_cup_server_proof= */ "", + /* header_cookie= */ "", /* x_header_retry_after_sec= */ 0ll); } @@ -144,6 +145,7 @@ /* network_error= */ -2, /* header_etag= */ "", /* header_x_cup_server_proof= */ "", + /* header_cookie= */ "", /* x_header_retry_after_sec= */ 0ll); } @@ -200,6 +202,7 @@ /* network_error= */ network_error, /* header_etag= */ "", /* header_x_cup_server_proof= */ "", + /* header_cookie= */ "", /* x_header_retry_after_sec= */ 0ll); }
diff --git a/android_webview/nonembedded/net/network_fetcher_task.cc b/android_webview/nonembedded/net/network_fetcher_task.cc index 9e48d47..5d1f991 100644 --- a/android_webview/nonembedded/net/network_fetcher_task.cc +++ b/android_webview/nonembedded/net/network_fetcher_task.cc
@@ -245,7 +245,8 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); std::move(post_request_complete_callback_) .Run(std::move(response_body), network_error, header_etag, - header_x_cup_server_proof, x_header_retry_after_sec); + header_x_cup_server_proof, /*header_cookie=*/"", + x_header_retry_after_sec); } } // namespace android_webview
diff --git a/base/features.cc b/base/features.cc index 79791ac..72db06b1 100644 --- a/base/features.cc +++ b/base/features.cc
@@ -50,6 +50,19 @@ "FastFilePathIsParent", FEATURE_ENABLED_BY_DEFAULT); +// Use the Rust JSON parser. Enabled everywhere. +BASE_FEATURE(kUseRustJsonParser, + "UseRustJsonParser", + FEATURE_ENABLED_BY_DEFAULT); + +// If true, use the Rust JSON parser in-thread; otherwise, it runs in a thread +// pool. +BASE_FEATURE_PARAM(bool, + kUseRustJsonParserInCurrentSequence, + &kUseRustJsonParser, + "UseRustJsonParserInCurrentSequence", + true); + // Use non default low memory device threshold. // Value should be given via |LowMemoryDeviceThresholdMB|. #if BUILDFLAG(IS_ANDROID)
diff --git a/base/features.h b/base/features.h index 0e4c48d..8b0dfea4 100644 --- a/base/features.h +++ b/base/features.h
@@ -19,6 +19,8 @@ BASE_EXPORT BASE_DECLARE_FEATURE(kFastFilePathIsParent); +BASE_EXPORT BASE_DECLARE_FEATURE(kUseRustJsonParser); + BASE_EXPORT BASE_DECLARE_FEATURE_PARAM(bool, kUseRustJsonParserInCurrentSequence);
diff --git a/base/json/json_reader.cc b/base/json/json_reader.cc index 3fcccc9..f32622d 100644 --- a/base/json/json_reader.cc +++ b/base/json/json_reader.cc
@@ -7,13 +7,13 @@ #include <string_view> #include <utility> +#include "base/features.h" +#include "base/json/json_parser.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "build/build_config.h" -#if BUILDFLAG(IS_NACL) -#include "base/json/json_parser.h" -#else +#if !BUILDFLAG(IS_NACL) #include "base/strings/string_view_rust.h" #include "third_party/rust/serde_json_lenient/v0_2/wrapper/functions.h" #include "third_party/rust/serde_json_lenient/v0_2/wrapper/lib.rs.h" @@ -142,13 +142,17 @@ return parser.Parse(json); #else // BUILDFLAG(IS_NACL) SCOPED_UMA_HISTOGRAM_TIMER_MICROS(kSecurityJsonParsingTime); - - JSONReader::Result result = - serde_json_lenient::DecodeJSONInRust(json, options, max_depth); - if (!result.has_value()) { - return std::nullopt; + if (UsingRust()) { + JSONReader::Result result = + serde_json_lenient::DecodeJSONInRust(json, options, max_depth); + if (!result.has_value()) { + return std::nullopt; + } + return std::move(*result); + } else { + internal::JSONParser parser(options, max_depth); + return parser.Parse(json); } - return std::move(*result); #endif // BUILDFLAG(IS_NACL) } @@ -192,9 +196,38 @@ return std::move(*value); #else // BUILDFLAG(IS_NACL) SCOPED_UMA_HISTOGRAM_TIMER_MICROS(kSecurityJsonParsingTime); - return serde_json_lenient::DecodeJSONInRust(json, options, - internal::kAbsoluteMaxDepth); + if (UsingRust()) { + return serde_json_lenient::DecodeJSONInRust(json, options, + internal::kAbsoluteMaxDepth); + } else { + internal::JSONParser parser(options); + auto value = parser.Parse(json); + if (!value) { + Error error; + error.message = parser.GetErrorMessage(); + error.line = parser.error_line(); + error.column = parser.error_column(); + return base::unexpected(std::move(error)); + } + + return std::move(*value); + } #endif // BUILDFLAG(IS_NACL) } +// static +bool JSONReader::UsingRust() { + // If features have not yet been enabled, we cannot check the feature, so fall + // back to the C++ parser. In practice, this seems to apply to + // `ReadPrefsFromDisk()`, which is parsing trusted JSON. + if (!base::FeatureList::GetInstance()) { + return false; + } +#if BUILDFLAG(IS_NACL) + return false; +#else + return base::FeatureList::IsEnabled(base::features::kUseRustJsonParser); +#endif +} + } // namespace base
diff --git a/base/json/json_reader.h b/base/json/json_reader.h index 1b1c536..5349d3c 100644 --- a/base/json/json_reader.h +++ b/base/json/json_reader.h
@@ -133,6 +133,9 @@ static Result ReadAndReturnValueWithError( std::string_view json, int options = JSON_PARSE_CHROMIUM_EXTENSIONS); + + // Determine whether the Rust parser is in use. + static bool UsingRust(); }; } // namespace base
diff --git a/base/json/json_reader_unittest.cc b/base/json/json_reader_unittest.cc index 79de5e0..ae2dca9 100644 --- a/base/json/json_reader_unittest.cc +++ b/base/json/json_reader_unittest.cc
@@ -19,6 +19,7 @@ #include "base/base_paths.h" #include "base/containers/heap_array.h" #include "base/containers/span.h" +#include "base/features.h" #include "base/files/file_util.h" #include "base/logging.h" #include "base/path_service.h" @@ -26,6 +27,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/gmock_expected_support.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/values.h" #include "build/build_config.h" #include "testing/gmock/include/gmock/gmock.h" @@ -51,20 +53,32 @@ namespace base { -TEST(JSONReaderTest, Whitespace) { +class JSONReaderTest : public testing::TestWithParam<bool> { + public: + void SetUp() override { + feature_list_.InitWithFeatureState(base::features::kUseRustJsonParser, + using_rust_); + } + + protected: + bool using_rust_ = GetParam(); + base::test::ScopedFeatureList feature_list_; +}; + +TEST_P(JSONReaderTest, Whitespace) { std::optional<Value> root = JSONReader::Read(" null "); ASSERT_TRUE(root); EXPECT_TRUE(root->is_none()); } -TEST(JSONReaderTest, InvalidString) { +TEST_P(JSONReaderTest, InvalidString) { // These are invalid because they do not represent a JSON value, // see https://tools.ietf.org/rfc/rfc8259.txt EXPECT_FALSE(JSONReader::Read("")); EXPECT_FALSE(JSONReader::Read("nu")); } -TEST(JSONReaderTest, SimpleBool) { +TEST_P(JSONReaderTest, SimpleBool) { base::HistogramTester histograms; std::optional<Value> root = JSONReader::Read("true "); ASSERT_TRUE(root); @@ -72,7 +86,7 @@ histograms.ExpectTotalCount("Security.JSONParser.ParsingTime", 1); } -TEST(JSONReaderTest, EmbeddedComments) { +TEST_P(JSONReaderTest, EmbeddedComments) { std::optional<Value> root = JSONReader::Read("/* comment */null"); ASSERT_TRUE(root); EXPECT_TRUE(root->is_none()); @@ -128,21 +142,21 @@ EXPECT_FALSE(JSONReader::Read("/33")); } -TEST(JSONReaderTest, Ints) { +TEST_P(JSONReaderTest, Ints) { std::optional<Value> root = JSONReader::Read("43"); ASSERT_TRUE(root); ASSERT_TRUE(root->is_int()); EXPECT_EQ(43, root->GetInt()); } -TEST(JSONReaderTest, NonDecimalNumbers) { +TEST_P(JSONReaderTest, NonDecimalNumbers) { // According to RFC 8259, oct, hex, and leading zeros are invalid JSON. EXPECT_FALSE(JSONReader::Read("043")); EXPECT_FALSE(JSONReader::Read("0x43")); EXPECT_FALSE(JSONReader::Read("00")); } -TEST(JSONReaderTest, NumberZero) { +TEST_P(JSONReaderTest, NumberZero) { // Test 0 (which needs to be special cased because of the leading zero // clause). std::optional<Value> root = JSONReader::Read("0"); @@ -151,7 +165,7 @@ EXPECT_EQ(0, root->GetInt()); } -TEST(JSONReaderTest, LargeIntPromotion) { +TEST_P(JSONReaderTest, LargeIntPromotion) { // Numbers that overflow ints should succeed, being internally promoted to // storage as doubles std::optional<Value> root = JSONReader::Read("2147483648"); @@ -164,7 +178,7 @@ EXPECT_DOUBLE_EQ(-2147483649.0, root->GetDouble()); } -TEST(JSONReaderTest, LargerIntIsLossy) { +TEST_P(JSONReaderTest, LargerIntIsLossy) { // Parse LONG_MAX as a JSON number (not a JSON string). The result of the // parse is a base::Value, either a (32-bit) int or a (64-bit) double. // LONG_MAX would overflow an int and can only be approximated by a double. @@ -181,7 +195,7 @@ EXPECT_EQ(std::string(etc808), StringPrintf("%f", root->GetDouble())); } -TEST(JSONReaderTest, Doubles) { +TEST_P(JSONReaderTest, Doubles) { std::optional<Value> root = JSONReader::Read("43.1"); ASSERT_TRUE(root); EXPECT_TRUE(root->is_double()); @@ -225,14 +239,14 @@ ASSERT_FALSE(value.has_value()); } -TEST(JSONReaderTest, FractionalNumbers) { +TEST_P(JSONReaderTest, FractionalNumbers) { // Fractional parts must have a digit before and after the decimal point. EXPECT_FALSE(JSONReader::Read("1.")); EXPECT_FALSE(JSONReader::Read(".1")); EXPECT_FALSE(JSONReader::Read("1.e10")); } -TEST(JSONReaderTest, ExponentialNumbers) { +TEST_P(JSONReaderTest, ExponentialNumbers) { // Exponent must have a digit following the 'e'. EXPECT_FALSE(JSONReader::Read("1e")); EXPECT_FALSE(JSONReader::Read("1E")); @@ -240,7 +254,7 @@ EXPECT_FALSE(JSONReader::Read("1e1.0")); } -TEST(JSONReaderTest, InvalidInfNAN) { +TEST_P(JSONReaderTest, InvalidInfNAN) { // The largest finite double is roughly 1.8e308. EXPECT_FALSE(JSONReader::Read("1e1000")); EXPECT_FALSE(JSONReader::Read("-1e1000")); @@ -249,7 +263,7 @@ EXPECT_FALSE(JSONReader::Read("inf")); } -TEST(JSONReaderTest, InvalidNumbers) { +TEST_P(JSONReaderTest, InvalidNumbers) { EXPECT_TRUE(JSONReader::Read("4.3")); EXPECT_FALSE(JSONReader::Read("4.")); EXPECT_FALSE(JSONReader::Read("4.3.1")); @@ -258,7 +272,7 @@ EXPECT_FALSE(JSONReader::Read("42a")); } -TEST(JSONReaderTest, Zeroes) { +TEST_P(JSONReaderTest, Zeroes) { std::optional<Value> root = JSONReader::Read("0"); ASSERT_TRUE(root); EXPECT_TRUE(root->is_int()); @@ -283,21 +297,21 @@ EXPECT_TRUE(std::signbit(root->GetDouble())); } -TEST(JSONReaderTest, SimpleString) { +TEST_P(JSONReaderTest, SimpleString) { std::optional<Value> root = JSONReader::Read("\"hello world\""); ASSERT_TRUE(root); ASSERT_TRUE(root->is_string()); EXPECT_EQ("hello world", root->GetString()); } -TEST(JSONReaderTest, EmptyString) { +TEST_P(JSONReaderTest, EmptyString) { std::optional<Value> root = JSONReader::Read("\"\""); ASSERT_TRUE(root); ASSERT_TRUE(root->is_string()); EXPECT_EQ("", root->GetString()); } -TEST(JSONReaderTest, BasicStringEscapes) { +TEST_P(JSONReaderTest, BasicStringEscapes) { std::optional<Value> root = JSONReader::Read("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\""); ASSERT_TRUE(root); @@ -305,7 +319,7 @@ EXPECT_EQ(" \"\\/\b\f\n\r\t", root->GetString()); } -TEST(JSONReaderTest, UnicodeEscapes) { +TEST_P(JSONReaderTest, UnicodeEscapes) { // Test hex and unicode escapes including the null character. std::optional<Value> root = JSONReader::Read("\"\\x41\\xFF\\x00\\u1234\\u0000\""); @@ -322,7 +336,7 @@ EXPECT_TRUE(JSONReader::Read("\"\\uD834\\uDD1E\"")); // U+1D11E } -TEST(JSONReaderTest, InvalidStrings) { +TEST_P(JSONReaderTest, InvalidStrings) { EXPECT_FALSE(JSONReader::Read("\"no closing quote")); EXPECT_FALSE(JSONReader::Read("\"\\z invalid escape char\"")); EXPECT_FALSE(JSONReader::Read("\"\\xAQ invalid hex code\"")); @@ -331,7 +345,7 @@ EXPECT_FALSE(JSONReader::Read("\"extra backslash at end of input\\\"")); } -TEST(JSONReaderTest, BasicArray) { +TEST_P(JSONReaderTest, BasicArray) { std::optional<Value> root = JSONReader::Read("[true, false, null]"); ASSERT_TRUE(root); Value::List* list = root->GetIfList(); @@ -345,7 +359,7 @@ EXPECT_EQ(*list, *root2); } -TEST(JSONReaderTest, EmptyArray) { +TEST_P(JSONReaderTest, EmptyArray) { std::optional<Value> value = JSONReader::Read("[]"); ASSERT_TRUE(value); Value::List* list = value->GetIfList(); @@ -353,7 +367,7 @@ EXPECT_TRUE(list->empty()); } -TEST(JSONReaderTest, CompleteArray) { +TEST_P(JSONReaderTest, CompleteArray) { std::optional<Value> value = JSONReader::Read("[\"a\", 3, 4.56, null]"); ASSERT_TRUE(value); Value::List* list = value->GetIfList(); @@ -361,7 +375,7 @@ EXPECT_EQ(4U, list->size()); } -TEST(JSONReaderTest, NestedArrays) { +TEST_P(JSONReaderTest, NestedArrays) { std::optional<Value> value = JSONReader::Read( "[[true], [], {\"smell\": \"nice\",\"taste\": \"yummy\" }, [false, [], " "[null]], null]"); @@ -379,7 +393,7 @@ EXPECT_EQ(*list, *root2); } -TEST(JSONReaderTest, InvalidArrays) { +TEST_P(JSONReaderTest, InvalidArrays) { // Missing close brace. EXPECT_FALSE(JSONReader::Read("[[true], [], [false, [], [null]], null")); @@ -394,7 +408,7 @@ EXPECT_FALSE(JSONReader::Read("[true,]")); } -TEST(JSONReaderTest, ArrayTrailingComma) { +TEST_P(JSONReaderTest, ArrayTrailingComma) { // Valid if we set |allow_trailing_comma| to true. std::optional<Value> value = JSONReader::Read("[true,]", JSON_ALLOW_TRAILING_COMMAS); @@ -407,7 +421,7 @@ EXPECT_TRUE(value1.GetBool()); } -TEST(JSONReaderTest, ArrayTrailingCommaNoEmptyElements) { +TEST_P(JSONReaderTest, ArrayTrailingCommaNoEmptyElements) { // Don't allow empty elements, even if |allow_trailing_comma| is // true. EXPECT_FALSE(JSONReader::Read("[,]", JSON_ALLOW_TRAILING_COMMAS)); @@ -416,13 +430,13 @@ EXPECT_FALSE(JSONReader::Read("[true,,false]", JSON_ALLOW_TRAILING_COMMAS)); } -TEST(JSONReaderTest, EmptyDictionary) { +TEST_P(JSONReaderTest, EmptyDictionary) { std::optional<Value> dict_val = JSONReader::Read("{}"); ASSERT_TRUE(dict_val); ASSERT_TRUE(dict_val->is_dict()); } -TEST(JSONReaderTest, CompleteDictionary) { +TEST_P(JSONReaderTest, CompleteDictionary) { std::optional<Value> root1 = JSONReader::Read( "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", \"bool\": " "false, \"more\": {} }"); @@ -481,7 +495,7 @@ EXPECT_EQ(*root1_dict, *root2_dict); } -TEST(JSONReaderTest, NestedDictionaries) { +TEST_P(JSONReaderTest, NestedDictionaries) { std::optional<Value> root1 = JSONReader::Read( "{\"inner\":{\"array\":[true, 3, 4.56, null]},\"false\":false,\"d\":{}}"); ASSERT_TRUE(root1); @@ -506,7 +520,7 @@ EXPECT_EQ(*root1_dict, *root2); } -TEST(JSONReaderTest, DictionaryKeysWithPeriods) { +TEST_P(JSONReaderTest, DictionaryKeysWithPeriods) { std::optional<Value> root = JSONReader::Read("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}"); ASSERT_TRUE(root); @@ -538,7 +552,7 @@ EXPECT_EQ(1, *integer_value); } -TEST(JSONReaderTest, DuplicateKeys) { +TEST_P(JSONReaderTest, DuplicateKeys) { std::optional<Value> root = JSONReader::Read("{\"x\":1,\"x\":2,\"y\":3}"); ASSERT_TRUE(root); const Value::Dict* root_dict = root->GetIfDict(); @@ -549,7 +563,7 @@ EXPECT_EQ(2, *integer_value); } -TEST(JSONReaderTest, InvalidDictionaries) { +TEST_P(JSONReaderTest, InvalidDictionaries) { // No closing brace. EXPECT_FALSE(JSONReader::Read("{\"a\": true")); @@ -579,7 +593,7 @@ JSON_ALLOW_TRAILING_COMMAS)); } -TEST(JSONReaderTest, StackOverflow) { +TEST_P(JSONReaderTest, StackOverflow) { std::string evil(1000000, '['); evil.append(std::string(1000000, ']')); EXPECT_FALSE(JSONReader::Read(evil)); @@ -598,7 +612,7 @@ EXPECT_EQ(5001U, list->size()); } -TEST(JSONReaderTest, UTF8Input) { +TEST_P(JSONReaderTest, UTF8Input) { std::optional<Value> root = JSONReader::Read("\"\xe7\xbd\x91\xe9\xa1\xb5\""); ASSERT_TRUE(root); ASSERT_TRUE(root->is_string()); @@ -662,13 +676,13 @@ } } -TEST(JSONReaderTest, InvalidUTF8Input) { +TEST_P(JSONReaderTest, InvalidUTF8Input) { EXPECT_FALSE(JSONReader::Read("\"345\xb0\xa1\xb0\xa2\"")); EXPECT_FALSE(JSONReader::Read("\"123\xc0\x81\"")); EXPECT_FALSE(JSONReader::Read("\"abc\xc0\xae\"")); } -TEST(JSONReaderTest, UTF16Escapes) { +TEST_P(JSONReaderTest, UTF16Escapes) { std::optional<Value> root = JSONReader::Read("\"\\u20ac3,14\""); ASSERT_TRUE(root); ASSERT_TRUE(root->is_string()); @@ -683,7 +697,7 @@ EXPECT_EQ("\xf0\x9f\x92\xa9\xf0\x9f\x91\xac", root->GetString()); } -TEST(JSONReaderTest, InvalidUTF16Escapes) { +TEST_P(JSONReaderTest, InvalidUTF16Escapes) { const char* const cases[] = { "\"\\u123\"", // Invalid scalar. "\"\\ud83d\"", // Invalid scalar. @@ -705,7 +719,7 @@ } } -TEST(JSONReaderTest, LiteralRoots) { +TEST_P(JSONReaderTest, LiteralRoots) { std::optional<Value> root = JSONReader::Read("null"); ASSERT_TRUE(root); EXPECT_TRUE(root->is_none()); @@ -726,7 +740,7 @@ EXPECT_EQ("root", root->GetString()); } -TEST(JSONReaderTest, ReadFromFile) { +TEST_P(JSONReaderTest, ReadFromFile) { FilePath path; ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &path)); path = path.AppendASCII("json"); @@ -742,7 +756,7 @@ // Tests that the root of a JSON object can be deleted safely while its // children outlive it. -TEST(JSONReaderTest, StringOptimizations) { +TEST_P(JSONReaderTest, StringOptimizations) { Value dict_literal_0; Value dict_literal_1; Value dict_string_0; @@ -818,7 +832,7 @@ // A smattering of invalid JSON designed to test specific portions of the // parser implementation against buffer overflow. Best run with DCHECKs so // that the one in NextChar fires. -TEST(JSONReaderTest, InvalidSanity) { +TEST_P(JSONReaderTest, InvalidSanity) { const auto kInvalidJson = std::to_array<const char*>({ "/* test *", "{\"foo\"", @@ -836,7 +850,7 @@ } } -TEST(JSONReaderTest, IllegalTrailingNull) { +TEST_P(JSONReaderTest, IllegalTrailingNull) { const auto json = std::to_array<char>({'"', 'n', 'u', 'l', 'l', '"', '\0'}); std::string json_string(json.data(), sizeof(json)); auto root = JSONReader::ReadAndReturnValueWithError(json_string); @@ -844,7 +858,7 @@ EXPECT_NE("", root.error().message); } -TEST(JSONReaderTest, ASCIIControlCodes) { +TEST_P(JSONReaderTest, ASCIIControlCodes) { // A literal NUL byte or a literal new line, in a JSON string, should be // rejected. RFC 8259 section 7 says "the characters that MUST be escaped // [include]... the control characters (U+0000 through U+001F)". @@ -869,13 +883,13 @@ } } -TEST(JSONReaderTest, MaxNesting) { +TEST_P(JSONReaderTest, MaxNesting) { std::string json(R"({"outer": { "inner": {"foo": true}}})"); EXPECT_FALSE(JSONReader::Read(json, JSON_PARSE_RFC, 3)); EXPECT_TRUE(JSONReader::Read(json, JSON_PARSE_RFC, 4)); } -TEST(JSONReaderTest, Decode4ByteUtf8Char) { +TEST_P(JSONReaderTest, Decode4ByteUtf8Char) { // kUtf8Data contains a 4 byte unicode character (a smiley!) that JSONReader // should be able to handle. The UTF-8 encoding of U+1F607 SMILING FACE WITH // HALO is "\xF0\x9F\x98\x87". @@ -889,7 +903,7 @@ EXPECT_EQ("\xF0\x9F\x98\x87", (*list)[0].GetString()); } -TEST(JSONReaderTest, DecodeUnicodeNonCharacter) { +TEST_P(JSONReaderTest, DecodeUnicodeNonCharacter) { // Tests Unicode code points (encoded as escaped UTF-16) that are not valid // characters. EXPECT_TRUE(JSONReader::Read("[\"\\uFDD0\"]")); // U+FDD0 @@ -931,13 +945,13 @@ EXPECT_TRUE(JSONReader::Read("[\"\\uDBFF\\uDFFF\"]")); // U+10FFFF } -TEST(JSONReaderTest, DecodeNegativeEscapeSequence) { +TEST_P(JSONReaderTest, DecodeNegativeEscapeSequence) { EXPECT_FALSE(JSONReader::Read("[\"\\x-A\"]")); EXPECT_FALSE(JSONReader::Read("[\"\\u-00A\"]")); } // Verifies invalid code points are replaced. -TEST(JSONReaderTest, ReplaceInvalidCharacters) { +TEST_P(JSONReaderTest, ReplaceInvalidCharacters) { // U+D800 is a lone high surrogate. const std::string invalid_high = "\"\xED\xA0\x80\""; std::optional<Value> value = @@ -956,7 +970,7 @@ EXPECT_EQ(U_FFFD U_FFFD U_FFFD, value->GetString()); } -TEST(JSONReaderTest, ReplaceInvalidUTF16EscapeSequence) { +TEST_P(JSONReaderTest, ReplaceInvalidUTF16EscapeSequence) { // U+D800 is a lone high surrogate. const std::string invalid_high = "\"_\\uD800_\""; std::optional<Value> value = @@ -973,7 +987,7 @@ EXPECT_EQ("_" U_FFFD "_", value->GetString()); } -TEST(JSONReaderTest, InvalidUTF16HighSurrogates) { +TEST_P(JSONReaderTest, InvalidUTF16HighSurrogates) { // U+dbaa is a high surrogate and expects a low surrogate, which U+001e is // not, so the entire surrogate pair should be replaced by // REPLACEMENT_CHARACTER. @@ -990,7 +1004,7 @@ ASSERT_FALSE(value); } -TEST(JSONReaderTest, InvalidUTF16HighSurrogatesAndEscapes) { +TEST_P(JSONReaderTest, InvalidUTF16HighSurrogatesAndEscapes) { // U+dbaa is a lone high surrogate, and should be replaced with // REPLACEMENT_CHARACTER and not affect interpretation of the following `\` // character as a part of the escape sequence `\"`. @@ -1007,7 +1021,7 @@ ASSERT_FALSE(value); } -TEST(JSONReaderTest, ParseNumberErrors) { +TEST_P(JSONReaderTest, ParseNumberErrors) { struct Cases { const char* input; bool parse_success; @@ -1045,7 +1059,7 @@ } } -TEST(JSONReaderTest, UnterminatedInputs) { +TEST_P(JSONReaderTest, UnterminatedInputs) { const auto kCases = std::to_array<const char*>({ // clang-format off "/", @@ -1077,7 +1091,7 @@ } } -TEST(JSONReaderTest, LineColumnCounting) { +TEST_P(JSONReaderTest, LineColumnCounting) { struct Cases { const char* input; int error_line; @@ -1151,7 +1165,7 @@ } } -TEST(JSONReaderTest, ChromiumExtensions) { +TEST_P(JSONReaderTest, ChromiumExtensions) { // All of these cases should parse with JSON_PARSE_CHROMIUM_EXTENSIONS but // fail with JSON_PARSE_RFC. struct Cases { @@ -1193,7 +1207,7 @@ // For every control character, place it unescaped in a string and ensure that: // a) It doesn't parse with JSON_PARSE_RFC // b) It doesn't parse with JSON_PARSE_CHROMIUM_EXTENSIONS -TEST(JSONReaderTest, UnescapedControls) { +TEST_P(JSONReaderTest, UnescapedControls) { std::string input = "\"foo\""; // ECMA-404 (JSON standard) section 9: characters from 0x00 to 0x1f must be // escaped. @@ -1209,7 +1223,11 @@ } } -TEST(JSONReaderTest, ReadingJsonIntoDictAndList) { +TEST_P(JSONReaderTest, UsingRust) { + ASSERT_EQ(JSONReader::UsingRust(), using_rust_); +} + +TEST_P(JSONReaderTest, ReadingJsonIntoDictAndList) { { std::optional<base::Value::List> list = JSONReader::ReadList("[1, 2, 3]"); ASSERT_TRUE(list); @@ -1238,4 +1256,11 @@ FUZZ_TEST(JSONReaderTest, CanParseAnythingWithoutCrashing); +INSTANTIATE_TEST_SUITE_P(All, + JSONReaderTest, + testing::Bool(), + [](const testing::TestParamInfo<bool>& info) { + return info.param ? "Rust" : "Cpp"; + }); + } // namespace base
diff --git a/build/config/rust.gni b/build/config/rust.gni index 80ff972..8c074fc 100644 --- a/build/config/rust.gni +++ b/build/config/rust.gni
@@ -33,13 +33,6 @@ # (including `//base`, `//net`, etc.) enable_rust = build_with_chromium - # The CXX tool is in //third_party/rust which is not shared with downstream - # projects yet. So they need to copy the required dependencies and GN files - # into their project to enable CXX there. - # - # We do not support disabling this flag in Chromium code. - enable_rust_cxx = build_with_chromium - # The chromium prelude crate provides the `chromium::import!` macro which # is needed to depend on first-party rust libraries. Third-party libraries # are specified with cargo_crate and do not get imported through this macro. @@ -104,6 +97,16 @@ force_rustc_color_output = false } +declare_args() { + # The CXX tool is in //third_party/rust which is not shared with downstream + # projects yet. So they need to copy the required dependencies and GN files + # into their project to enable CXX there. + # + # Currently, cxx is needed to use Rust with an allocator since the Chromium + # allocator shim uses cxx + enable_rust_cxx = enable_rust +} + # Use the Rust toolchain built in-tree. When false, we use the prebuilt Rust # stdlibs that come with the specified custom toolchain. use_chromium_rust_toolchain = rust_sysroot_absolute == ""
diff --git a/chrome/VERSION b/chrome/VERSION index 857b97cd..190627b 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=138 MINOR=0 -BUILD=7154 +BUILD=7155 PATCH=0
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index 20e03027..a437c1e 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -1192,6 +1192,7 @@ chrome_java_sources += [ "java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialog.java", "java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialogBridge.java", + "java/src/org/chromium/chrome/browser/media/MediaCapturePickerHeadlessFragment.java", "java/src/org/chromium/chrome/browser/media/MediaCapturePickerItemProperties.java", "java/src/org/chromium/chrome/browser/media/MediaCapturePickerItemViewBinder.java", ]
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java index 5375fa9..362e7e9 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -3471,10 +3471,16 @@ new MinimizeAppAndCloseTabBackPressHandler( getActivityTabProvider(), this::backShouldCloseTab, + TabAssociatedApp::isOpenedFromExternalApp, + this::closeTabUponMinimization, this::sendToBackground); mBackPressManager.addHandler( mMinimizeAppAndCloseTabBackPressHandler, BackPressHandler.Type.MINIMIZE_APP_AND_CLOSE_TAB); + if (MinimizeAppAndCloseTabBackPressHandler.supportCloseTabUponMinimization()) { + mBackPressManager.addOnSystemNavigationObserver( + mMinimizeAppAndCloseTabBackPressHandler); + } } } @@ -3522,54 +3528,56 @@ private void sendToBackground(@Nullable final Tab tabToClose) { Log.i(TAG, "sendToBackground(): " + tabToClose); moveTaskToBack(true); - if (tabToClose != null) { - // In the case of closing a tab upon minimization, don't allow the close action to - // happen until after our app is minimized to make sure we don't get a brief glimpse of - // the newly active tab before we exit Chrome. - // - // If the runnable doesn't run before the Activity dies, Chrome won't crash but the tab - // won't be closed (crbug.com/587565). - mHandler.postDelayed( - () -> { - if (mTabModelSelector == null - || tabToClose.isClosing() - || tabToClose.isDestroyed()) { - return; - } + if (tabToClose != null) closeTabUponMinimization(tabToClose); + } - final TabModel currentModel = mTabModelSelector.getCurrentModel(); - final TabModel tabToCloseModel = - mTabModelSelector.getModel(tabToClose.isIncognito()); - if (currentModel != tabToCloseModel) { - // This seems improbable; however, crbug/1463397 suggests otherwise. If - // this happens, remain on the current tab and close the tab in the - // other model. - tabToCloseModel - .getTabRemover() - .closeTabs( - TabClosureParams.closeTab(tabToClose) - .uponExit(true) - .allowUndo(false) - .build(), - /* allowDialog= */ false); - return; - } + private void closeTabUponMinimization(@NonNull Tab tabToClose) { + // In the case of closing a tab upon minimization, don't allow the close action to + // happen until after our app is minimized to make sure we don't get a brief glimpse of + // the newly active tab before we exit Chrome. + // + // If the runnable doesn't run before the Activity dies, Chrome won't crash but the tab + // won't be closed (crbug.com/587565). + mHandler.postDelayed( + () -> { + if (mTabModelSelector == null + || tabToClose.isClosing() + || tabToClose.isDestroyed()) { + return; + } - Tab nextTab = - currentModel.getNextTabIfClosed( - tabToClose.getId(), /* uponExit= */ true); + final TabModel currentModel = mTabModelSelector.getCurrentModel(); + final TabModel tabToCloseModel = + mTabModelSelector.getModel(tabToClose.isIncognito()); + if (currentModel != tabToCloseModel) { + // This seems improbable; however, crbug/1463397 suggests otherwise. If + // this happens, remain on the current tab and close the tab in the + // other model. tabToCloseModel .getTabRemover() .closeTabs( TabClosureParams.closeTab(tabToClose) - .recommendedNextTab(nextTab) .uponExit(true) .allowUndo(false) .build(), /* allowDialog= */ false); - }, - CLOSE_TAB_ON_MINIMIZE_DELAY_MS); - } + return; + } + + Tab nextTab = + currentModel.getNextTabIfClosed( + tabToClose.getId(), /* uponExit= */ true); + tabToCloseModel + .getTabRemover() + .closeTabs( + TabClosureParams.closeTab(tabToClose) + .recommendedNextTab(nextTab) + .uponExit(true) + .allowUndo(false) + .build(), + /* allowDialog= */ false); + }, + CLOSE_TAB_ON_MINIMIZE_DELAY_MS); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java index 5f18cda..db1a655 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/SwipeRefreshHandler.java
@@ -37,6 +37,7 @@ import org.chromium.ui.OverscrollAction; import org.chromium.ui.OverscrollRefreshHandler; import org.chromium.ui.base.BackGestureEventSwipeEdge; +import org.chromium.ui.base.DeviceInput; import org.chromium.ui.base.WindowAndroid; import java.lang.annotation.Retention; @@ -281,23 +282,26 @@ public boolean start( @OverscrollAction int type, @BackGestureEventSwipeEdge int initiatingEdge) { mSwipeType = type; - if (type == OverscrollAction.PULL_TO_REFRESH) { - if (mSwipeRefreshLayout == null) initSwipeRefreshLayout(mTab.getContext()); - attachSwipeRefreshLayoutIfNecessary(); - return mSwipeRefreshLayout.start(); - } else if (type == OverscrollAction.HISTORY_NAVIGATION) { - if (mNavigationCoordinator != null) { - mNavigationCoordinator.startGesture(); - // Note: triggerUi returns true as long as the handler is in a valid state, i.e. - // even if the navigation direction doesn't have further history entries. - boolean navigable = mNavigationCoordinator.triggerUi(initiatingEdge); - return navigable; - } - } else if (type == OverscrollAction.PULL_FROM_BOTTOM_EDGE) { - if (mBrowserControls != null) { - recordEdgeToEdgeOverscrollFromBottom(mBrowserControls); + if (isRefreshOnOverscrollSupported()) { + if (type == OverscrollAction.PULL_TO_REFRESH) { + if (mSwipeRefreshLayout == null) initSwipeRefreshLayout(mTab.getContext()); + attachSwipeRefreshLayoutIfNecessary(); + return mSwipeRefreshLayout.start(); + } else if (type == OverscrollAction.HISTORY_NAVIGATION) { + if (mNavigationCoordinator != null) { + mNavigationCoordinator.startGesture(); + // Note: triggerUi returns true as long as the handler is in a valid state, i.e. + // even if the navigation direction doesn't have further history entries. + boolean navigable = mNavigationCoordinator.triggerUi(initiatingEdge); + return navigable; + } + } else if (type == OverscrollAction.PULL_FROM_BOTTOM_EDGE) { + if (mBrowserControls != null) { + recordEdgeToEdgeOverscrollFromBottom(mBrowserControls); + } } } + mSwipeType = OverscrollAction.NONE; return false; } @@ -419,4 +423,22 @@ sample, BottomControlsStatus.NUM_TOTAL); } + + /** + * Checks to see if page refresh on overscroll is supported Wrapped so we can stub behavior in + * tests. + * + * <p>Currently, overscroll to refresh is disabled if a precision pointer device is attached. + * For example, this will disable it for touch screen when a mouse is attaached. However + * long-term, the plan is to selectively enable for things such as touchscreen only. + * + * <p>TODO(crbug.com/412465463): enable overscroll refresh for touch even when precision pointer + * is attached + * + * @return true if page refresh on overscroll is supported. + */ + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + boolean isRefreshOnOverscrollSupported() { + return !DeviceInput.supportsPrecisionPointer(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java index 304b3fa..3057cd7 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -29,6 +29,7 @@ import android.view.ViewGroup; import android.view.ViewStub; import android.widget.FrameLayout; +import android.window.OnBackInvokedDispatcher; import androidx.annotation.CallSuper; import androidx.annotation.NonNull; @@ -1563,6 +1564,12 @@ } if (mBackPressManager != null) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA + && mBackPressManager.getOnSystemNavigationCallback() != null) { + getOnBackInvokedDispatcher() + .unregisterOnBackInvokedCallback( + mBackPressManager.getOnSystemNavigationCallback()); + } mBackPressManager.destroy(); } @@ -2277,6 +2284,13 @@ } private void initializeBackPressHandling() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA + && mBackPressManager.getOnSystemNavigationCallback() != null) { + getOnBackInvokedDispatcher() + .registerOnBackInvokedCallback( + OnBackInvokedDispatcher.PRIORITY_SYSTEM_NAVIGATION_OBSERVER, + mBackPressManager.getOnSystemNavigationCallback()); + } mBackPressManager.setIsGestureNavEnabledSupplier( () -> UiUtils.isGestureNavigationMode(getWindow())); final Runnable callbackForLegacyTabStartupMetricsTracker =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java index 7b8c72f4..29c86a5 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/HiddenTabHolder.java
@@ -44,6 +44,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Objects; /** * Holds a hidden tab which may be used to preload pages before a CustomTabActivity is launched. @@ -267,18 +268,11 @@ try (TraceEvent e = TraceEvent.scoped("CustomTabsConnection.takeHiddenTab")) { if (intent.getBooleanExtra(IntentHandler.EXTRA_CCT_EARLY_NAV, false)) { recordEarlyNavDebugMetric(session, ignoreFragments, url, intent); - - // Work around Early Nav failures by always continuing with the early nav if it - // hasn't been cleaned up. - if (mSpeculation != null && mSpeculation.isEarlyNav) { - HiddenTab hiddenTab = mSpeculation.hiddenTab; - mSpeculation = null; - return hiddenTab; - } } - if (mSpeculation == null || session == null) return null; - if (!session.equals(mSpeculation.session)) return null; + if (mSpeculation == null) return null; + // ~10% of CCT startups have no session, allow them to use Early Nav. + if (!Objects.equals(session, mSpeculation.session)) return null; HiddenTab hiddenTab = mSpeculation.hiddenTab; String speculatedUrl = hiddenTab.url; @@ -313,7 +307,9 @@ @EarlyNavFailureReason int failureReason = EarlyNavFailureReason.SUCCESS; if (mSpeculation == null) { failureReason = EarlyNavFailureReason.NO_SPECULATION; - } else if (session == null) { + } else if (!Objects.equals(session, mSpeculation.session)) { + // NO_SESSION redefined to be wrong session. This is just for short term debugging so + // it's fine. failureReason = EarlyNavFailureReason.NO_SESSION; } else { boolean isSessionValid = CustomTabsConnection.getInstance().isSessionValid(session);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialog.java b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialog.java index 5e0320b7..e9d5be3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialog.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialog.java
@@ -12,12 +12,14 @@ import android.widget.ListView; import androidx.annotation.IntDef; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.google.android.material.materialswitch.MaterialSwitch; import org.chromium.chrome.R; import org.chromium.chrome.browser.app.tabmodel.AllTabObserver; +import org.chromium.chrome.browser.media.MediaCapturePickerHeadlessFragment.CaptureAction; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabLoadIfNeededCaller; import org.chromium.content_public.browser.WebContents; @@ -41,21 +43,32 @@ private final View mDialogView; private final LinearLayout mButtonsView; private final View mPositiveButton; + private final View mScreenButton; private final MaterialSwitch mAudioSwitch; private final ModelList mModelList = new ModelList(); private final Map<Tab, TabItemState> mTabItemStateMap = new HashMap<>(); @Nullable private TabItemState mLastSelectedTabItemState; + @Nullable private PropertyModel mPropertyModel; @Nullable private Delegate mDelegate; /** A delegate for handling returning the picker result. */ interface Delegate { /** - * Called when the user has selected a tab to share, or when the dialog is cancelled. + * Called when the user has selected a tab to share. * * @param webContents The contents to share. * @param audioShare True if tab audio should be shared. */ - void onFinishPicking(@Nullable WebContents webContents, boolean audioShare); + void onPickTab(@NonNull WebContents webContents, boolean audioShare); + + /** Called when the user has selected a window to share. */ + void onPickWindow(); + + /** Called when the user has selected a screen to share. */ + void onPickScreen(); + + /** Called when the user has elected to not share anything. */ + void onCancel(); } private class TabItemState { @@ -149,6 +162,7 @@ .inflate(R.layout.media_capture_picker_button_row, null); mPositiveButton = mButtonsView.findViewById(R.id.positive_button); + mScreenButton = mButtonsView.findViewById(R.id.screen_button); // Share audio should be on by default. mAudioSwitch = mButtonsView.findViewById(R.id.media_capture_picker_audio_share_switch); @@ -178,6 +192,30 @@ removed.destroy(); } + private void startAndroidCapturePrompt() { + var fragment = MediaCapturePickerHeadlessFragment.getInstanceForCurrentActivity(); + fragment.startAndroidCapturePrompt( + result -> { + switch (result) { + case CaptureAction.CAPTURE_CANCELLED: + mDelegate.onCancel(); + break; + case CaptureAction.CAPTURE_WINDOW: + mDelegate.onPickWindow(); + break; + case CaptureAction.CAPTURE_SCREEN: + mDelegate.onPickScreen(); + break; + default: + assert false; + } + + mDelegate = null; + mModalDialogManager.dismissDialog( + mPropertyModel, DialogDismissalCause.ACTION_ON_DIALOG_COMPLETED); + }); + } + private void show() { var allTabObserver = new AllTabObserver(this); @@ -192,10 +230,9 @@ var webContents = tab.getWebContents(); assert webContents != null; - mDelegate.onFinishPicking(webContents, mAudioSwitch.isChecked()); + mDelegate.onPickTab(webContents, mAudioSwitch.isChecked()); } else { - mDelegate.onFinishPicking( - /* webContents= */ null, /* audioShare= */ false); + mDelegate.onCancel(); } mDelegate = null; mModalDialogManager.dismissDialog( @@ -208,8 +245,7 @@ @Override public void onDismiss(PropertyModel model, int dismissalCause) { if (mDelegate != null) { - mDelegate.onFinishPicking( - /* webContents= */ null, /* audioShare= */ false); + mDelegate.onCancel(); mDelegate = null; } allTabObserver.destroy(); @@ -219,7 +255,8 @@ Resources resources = mDialogView.getResources(); var title = resources.getString(R.string.media_capture_picker_dialog_title, mAppName); - var propertyModel = + assert mPropertyModel == null; + mPropertyModel = new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS) .with(ModalDialogProperties.CONTROLLER, controller) .with(ModalDialogProperties.CUSTOM_VIEW, mDialogView) @@ -229,11 +266,14 @@ mButtonsView .findViewById(R.id.negative_button) - .setOnClickListener(view -> controller.onClick(propertyModel, ButtonType.NEGATIVE)); + .setOnClickListener( + view -> controller.onClick(mPropertyModel, ButtonType.NEGATIVE)); mPositiveButton.setOnClickListener( - view -> controller.onClick(propertyModel, ButtonType.POSITIVE)); + view -> controller.onClick(mPropertyModel, ButtonType.POSITIVE)); - mModalDialogManager.showDialog(propertyModel, ModalDialogManager.ModalDialogType.TAB); + mScreenButton.setOnClickListener(view -> startAndroidCapturePrompt()); + + mModalDialogManager.showDialog(mPropertyModel, ModalDialogManager.ModalDialogType.TAB); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialogBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialogBridge.java index b329d3c..a78499b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialogBridge.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerDialogBridge.java
@@ -6,6 +6,8 @@ import android.app.Activity; +import androidx.annotation.NonNull; + import org.jni_zero.CalledByNative; import org.jni_zero.JniType; import org.jni_zero.NativeMethods; @@ -15,7 +17,7 @@ import org.chromium.ui.modaldialog.ModalDialogManagerHolder; /** Glue for the media capture picker dialog UI code and communication with the native backend. */ -public class MediaCapturePickerDialogBridge { +public class MediaCapturePickerDialogBridge implements MediaCapturePickerDialog.Delegate { private long mNativeMediaCapturePickerDialogBridge; /** @@ -55,14 +57,7 @@ ((ModalDialogManagerHolder) activity).getModalDialogManager(), appName, requestAudio, - (webContents, audioShare) -> { - // We know `mNativeMediaCapturePickerDialogBridge` is non-zero because - // `destroy` will only be called after the dialog is dismissed. - assert mNativeMediaCapturePickerDialogBridge != 0; - MediaCapturePickerDialogBridgeJni.get() - .onResult( - mNativeMediaCapturePickerDialogBridge, webContents, audioShare); - }); + this); } @CalledByNative @@ -70,11 +65,50 @@ mNativeMediaCapturePickerDialogBridge = 0; } + @Override + public void onPickTab(@NonNull WebContents webContents, boolean audioShare) { + // We know `mNativeMediaCapturePickerDialogBridge` is non-zero because + // `destroy` will only be called after the dialog is dismissed. + assert mNativeMediaCapturePickerDialogBridge != 0; + MediaCapturePickerDialogBridgeJni.get() + .onPickTab(mNativeMediaCapturePickerDialogBridge, webContents, audioShare); + } + + @Override + public void onPickWindow() { + // We know `mNativeMediaCapturePickerDialogBridge` is non-zero because + // `destroy` will only be called after the dialog is dismissed. + assert mNativeMediaCapturePickerDialogBridge != 0; + MediaCapturePickerDialogBridgeJni.get().onPickWindow(mNativeMediaCapturePickerDialogBridge); + } + + @Override + public void onPickScreen() { + // We know `mNativeMediaCapturePickerDialogBridge` is non-zero because + // `destroy` will only be called after the dialog is dismissed. + assert mNativeMediaCapturePickerDialogBridge != 0; + MediaCapturePickerDialogBridgeJni.get().onPickScreen(mNativeMediaCapturePickerDialogBridge); + } + + @Override + public void onCancel() { + // We know `mNativeMediaCapturePickerDialogBridge` is non-zero because + // `destroy` will only be called after the dialog is dismissed. + assert mNativeMediaCapturePickerDialogBridge != 0; + MediaCapturePickerDialogBridgeJni.get().onCancel(mNativeMediaCapturePickerDialogBridge); + } + @NativeMethods interface Natives { - void onResult( + void onPickTab( long nativeMediaCapturePickerDialogBridge, WebContents webContents, boolean audioShare); + + void onPickWindow(long nativeMediaCapturePickerDialogBridge); + + void onPickScreen(long nativeMediaCapturePickerDialogBridge); + + void onCancel(long nativeMediaCapturePickerDialogBridge); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerHeadlessFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerHeadlessFragment.java new file mode 100644 index 0000000..8b72a251 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/media/MediaCapturePickerHeadlessFragment.java
@@ -0,0 +1,107 @@ +// Copyright 2025 The Chromium Authors +// 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.media; + +import android.app.Activity; +import android.content.Context; +import android.content.Intent; +import android.media.projection.MediaProjectionManager; +import android.os.Bundle; + +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.annotation.IntDef; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import org.chromium.base.ApplicationStatus; +import org.chromium.base.Callback; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Headless fragment used to invoke the MediaProjection API. + * + * <p>This is created on a per-Activity basis. + */ +public class MediaCapturePickerHeadlessFragment extends Fragment { + private static final String TAG = "MediaCapturePickerHeadlessFragment"; + + @Retention(RetentionPolicy.SOURCE) + @Target(ElementType.TYPE_USE) + @IntDef({ + CaptureAction.CAPTURE_CANCELLED, + CaptureAction.CAPTURE_WINDOW, + CaptureAction.CAPTURE_SCREEN + }) + @interface CaptureAction { + int CAPTURE_CANCELLED = 0; + int CAPTURE_WINDOW = 1; + int CAPTURE_SCREEN = 2; + } + + private MediaProjectionManager mMediaProjectionManager; + private ActivityResultLauncher<Intent> mLauncher; + private Callback<@CaptureAction Integer> mNextCallback; + + public static MediaCapturePickerHeadlessFragment getInstanceForCurrentActivity() { + var activity = (FragmentActivity) ApplicationStatus.getLastTrackedFocusedActivity(); + if (activity == null) { + return null; + } + FragmentManager fragmentManager = activity.getSupportFragmentManager(); + var fragment = + (MediaCapturePickerHeadlessFragment) + fragmentManager.findFragmentByTag(MediaCapturePickerHeadlessFragment.TAG); + + if (fragment == null) { + fragment = new MediaCapturePickerHeadlessFragment(); + fragmentManager + .beginTransaction() + .add(fragment, MediaCapturePickerHeadlessFragment.TAG) + .commitNowAllowingStateLoss(); + } + return fragment; + } + + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + mMediaProjectionManager = + (MediaProjectionManager) + requireActivity().getSystemService(Context.MEDIA_PROJECTION_SERVICE); + + mLauncher = + registerForActivityResult( + new ActivityResultContracts.StartActivityForResult(), + result -> { + assert mNextCallback != null; + if (result.getResultCode() == Activity.RESULT_OK + && result.getData() != null) { + // There is currently no way to differentiate between window and + // screen sharing. + mNextCallback.onResult(CaptureAction.CAPTURE_WINDOW); + } else { + mNextCallback.onResult(CaptureAction.CAPTURE_CANCELLED); + } + mNextCallback = null; + }); + + // This fragment has no UI so we can retain it. + setRetainInstance(true); + } + + public void startAndroidCapturePrompt(Callback<@CaptureAction Integer> callback) { + assert mNextCallback == null; + mNextCallback = callback; + mLauncher.launch(mMediaProjectionManager.createScreenCaptureIntent()); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java index 2d3c59e..a0a3aa3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -137,6 +137,7 @@ import org.chromium.chrome.browser.toolbar.bottom.BottomControlsContentDelegate; import org.chromium.chrome.browser.toolbar.bottom.BottomControlsCoordinator; import org.chromium.chrome.browser.toolbar.bottom.ScrollingBottomViewResourceFrameLayout; +import org.chromium.chrome.browser.toolbar.extensions.ExtensionToolbarManager; import org.chromium.chrome.browser.toolbar.home_button.HomeButtonCoordinator; import org.chromium.chrome.browser.toolbar.load_progress.LoadProgressCoordinator; import org.chromium.chrome.browser.toolbar.menu_button.MenuButtonCoordinator; @@ -302,6 +303,8 @@ private HomeButtonCoordinator mHomeButtonCoordinator; private ToggleTabStackButtonCoordinator mTabSwitcherButtonCoordinator; private @Nullable BackButtonCoordinator mBackButtonCoordinator; + private @Nullable ExtensionToolbarManager mExtensionToolbarManager; + private BrowserStateBrowserControlsVisibilityDelegate mControlsVisibilityDelegate; private int mFullscreenFocusToken = TokenHolder.INVALID_TOKEN; private int mFullscreenFindInPageToken = TokenHolder.INVALID_TOKEN; @@ -1592,6 +1595,14 @@ mWindowAndroid.setProgressBarConfigProvider(mProgressBarConfigProvider); initializeToolbarPositionController(); + ViewStub extensionToolbarStub = + controlContainer.findViewById(R.id.extension_toolbar_container_stub); + if (extensionToolbarStub != null) { + mExtensionToolbarManager = + ExtensionToolbarManager.maybeCreate( + mActivity, extensionToolbarStub, profileSupplier, tabProvider); + } + TraceEvent.end("ToolbarManager.ToolbarManager"); } @@ -2308,6 +2319,11 @@ mTabSwitcherButtonCoordinator = null; } + if (mExtensionToolbarManager != null) { + mExtensionToolbarManager.destroy(); + mExtensionToolbarManager = null; + } + if (mCallbackController != null) { mCallbackController.destroy(); mCallbackController = null;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/SwipeRefreshHandlerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/SwipeRefreshHandlerTest.java index 8076639..5bc3bfa 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/SwipeRefreshHandlerTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/SwipeRefreshHandlerTest.java
@@ -5,10 +5,13 @@ package org.chromium.chrome.browser; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; @@ -63,6 +66,9 @@ private OnRefreshListener mOnRefreshListener; private OnResetListener mOnResetListener; private SwipeRefreshLayout mSwipeRefreshLayout; + + private SwipeRefreshHandler mHandler; + private final SwipeRefreshHandler.SwipeRefreshLayoutCreator mSwipeRefreshLayoutCreator = context -> { mSwipeRefreshLayout = mock(); @@ -87,14 +93,18 @@ when(mTab.getContext()).thenReturn(activityTestRule.getActivity()); when(mTab.getUserDataHost()).thenReturn(new UserDataHost()); when(mTab.getContentView()).thenReturn(mock()); + + // Limited use of spy() so we can test actual object, while changing some behaviors + // dynamically (such as whether mouse is attached or not) + mHandler = spy(SwipeRefreshHandler.from(mTab, mSwipeRefreshLayoutCreator)); + mHandler.initWebContents(mock()); // Needed to enable the overscroll refresh handler. + doReturn(true).when(mHandler).isRefreshOnOverscrollSupported(); // Default no mouse/touchpad } @Test @SmallTest public void testAccessibilityAnnouncement() { - var handler = SwipeRefreshHandler.from(mTab, mSwipeRefreshLayoutCreator); - handler.initWebContents(mock()); // Needed to enable the overscroll refresh handler. - triggerRefresh(handler); + triggerRefresh(mHandler); InOrder orderVerifier = inOrder(mSwipeRefreshLayout); orderVerifier @@ -104,17 +114,25 @@ .verify(mSwipeRefreshLayout, times(1)) .setContentDescription(sAccessibilitySwipeRefreshString); - reset(handler); + reset(mHandler); orderVerifier.verify(mSwipeRefreshLayout, times(1)).setContentDescription(null); } + /** Ensures that we do not trigger refresh if precision pointing device is attached */ + @Test + @SmallTest + public void testOverscrollButNoRefresh() { + doReturn(false).when(mHandler).isRefreshOnOverscrollSupported(); // pointer device attached + triggerRefresh(mHandler); + // When refresh is NOT triggered, then refresh layout is NOT created + assertNull(mSwipeRefreshLayout); + } + @Test @SmallTest public void testAccessibilityAnnouncement_swipingASecondTime() { - var handler = SwipeRefreshHandler.from(mTab, mSwipeRefreshLayoutCreator); - handler.initWebContents(mock()); // Needed to enable the overscroll refresh handler. - triggerRefresh(handler); + triggerRefresh(mHandler); var firstSwipeRefreshLayout = mSwipeRefreshLayout; @@ -126,11 +144,11 @@ .verify(firstSwipeRefreshLayout, times(1)) .setContentDescription(sAccessibilitySwipeRefreshString); - reset(handler); + reset(mHandler); orderVerifier.verify(mSwipeRefreshLayout, times(1)).setContentDescription(null); - triggerRefresh(handler); + triggerRefresh(mHandler); var secondSwipeRefreshLayout = mSwipeRefreshLayout;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java index 9f4b2a2..0e52e01 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/contextmenu/ContextMenuTest.java
@@ -95,6 +95,9 @@ import org.chromium.content_public.browser.test.util.TestTouchUtils; import org.chromium.content_public.common.ContentFeatures; import org.chromium.net.test.EmbeddedTestServer; +import org.chromium.printing.Printable; +import org.chromium.printing.PrintingController; +import org.chromium.printing.PrintingControllerImpl; import org.chromium.ui.base.Clipboard; import org.chromium.ui.base.DeviceFormFactor; import org.chromium.ui.mojom.MenuSourceType; @@ -118,6 +121,7 @@ @Mock private TabContextMenuItemDelegate mItemDelegate; @Mock private ShareDelegate mShareDelegate; + @Mock private PrintingController mPrintingController; @Mock private DataProtectionBridge.Natives mDataProtectionBridgeMock; @ClassRule @@ -1192,6 +1196,31 @@ chromeExtrasCaptor.getValue().saveLastUsed()); } + @Test + @MediumTest + @Restriction(DeviceFormFactor.DESKTOP) + @EnableFeatures({ChromeFeatureList.CONTEXT_MENU_EMPTY_SPACE}) + public void testPrintPage() throws Exception { + Tab tab = sDownloadTestRule.getActivity().getActivityTab(); + ThreadUtils.runOnUiThreadBlocking( + // Set printing controller to use the mock instance. + () -> { + PrintingControllerImpl.setInstanceForTesting(mPrintingController); + }); + + ContextMenuUtils.selectContextMenuItemFromRightClick( + InstrumentationRegistry.getInstrumentation(), + sDownloadTestRule.getActivity(), + tab, + "testEmptySpace", + R.id.contextmenu_print_page); + + // Check that the started print job has the same title as the current tab. + ArgumentCaptor<Printable> printableCaptor = ArgumentCaptor.forClass(Printable.class); + verify(mPrintingController).startPrint(printableCaptor.capture(), any()); + Assert.assertEquals(tab.getTitle(), printableCaptor.getValue().getTitle()); + } + // TODO(benwgold): Add more test coverage for histogram recording of other context menu types. /**
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java index cac57b705..89aec25 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/settings/SettingsActivityTest.java
@@ -116,5 +116,10 @@ SettingsActivity.class, Stage.CREATED, () -> activity.startActivity(intent3)); } - public static class TestFragment extends Fragment implements SettingsFragment {} + public static class TestFragment extends Fragment implements SettingsFragment { + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } + } }
diff --git a/chrome/app/app-Info.plist b/chrome/app/app-Info.plist index d834534c..9190c5e 100644 --- a/chrome/app/app-Info.plist +++ b/chrome/app/app-Info.plist
@@ -246,8 +246,6 @@ <dict> <key>MallocNanoZone</key> <string>0</string> - <key>MallocProbGuard</key> - <string>0</string> </dict> <key>LSFileQuarantineEnabled</key> <true/>
diff --git a/chrome/app/helper-Info.plist b/chrome/app/helper-Info.plist index 764c3d9..7e1bbe0 100644 --- a/chrome/app/helper-Info.plist +++ b/chrome/app/helper-Info.plist
@@ -22,8 +22,6 @@ <dict> <key>MallocNanoZone</key> <string>0</string> - <key>MallocProbGuard</key> - <string>0</string> </dict> <key>LSFileQuarantineEnabled</key> <true/>
diff --git a/chrome/app_shim/app_mode-Info.plist b/chrome/app_shim/app_mode-Info.plist index 5e502f74..9ac68981 100644 --- a/chrome/app_shim/app_mode-Info.plist +++ b/chrome/app_shim/app_mode-Info.plist
@@ -30,8 +30,6 @@ <dict> <key>MallocNanoZone</key> <string>0</string> - <key>MallocProbGuard</key> - <string>0</string> </dict> <key>LSMinimumSystemVersion</key> <string>${CHROMIUM_MIN_SYSTEM_VERSION}</string>
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 6ac1a70b..f002e3a 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -5867,6 +5867,12 @@ flag_descriptions::kGridTabSwitcherUpdateDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kGridTabSwitcherUpdate)}, + // Predictive back gesture + {"allow-tab-closing-upon-minimization", + flag_descriptions::kAllowTabClosingUponMinimizationName, + flag_descriptions::kAllowTabClosingUponMinimizationDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kAllowTabClosingUponMinimization)}, + #endif // BUILDFLAG(IS_ANDROID) {"disallow-doc-written-script-loads", flag_descriptions::kDisallowDocWrittenScriptsUiName, @@ -12257,6 +12263,11 @@ flag_descriptions::kGridTabSwitcherSurfaceColorUpdateDescription, kOsAndroid, FEATURE_VALUE_TYPE(chrome::android::kGridTabSwitcherSurfaceColorUpdate)}, + + // Contextual Page Action button. + {"cpa-spec-update", flag_descriptions::kCpaSpecUpdateName, + flag_descriptions::kCpaSpecUpdateDescription, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kCpaSpecUpdate)}, #endif // BUILDFLAG(IS_ANDROID) #if !BUILDFLAG(IS_ANDROID)
diff --git a/chrome/browser/android/omnibox/autocomplete_controller_android.cc b/chrome/browser/android/omnibox/autocomplete_controller_android.cc index d1e5811..8f4cd7a3 100644 --- a/chrome/browser/android/omnibox/autocomplete_controller_android.cc +++ b/chrome/browser/android/omnibox/autocomplete_controller_android.cc
@@ -45,6 +45,7 @@ #include "components/omnibox/browser/actions/omnibox_answer_action.h" #include "components/omnibox/browser/autocomplete_classifier.h" #include "components/omnibox/browser/autocomplete_controller_emitter.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_grouper_sections.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" @@ -284,7 +285,9 @@ } void AutocompleteControllerAndroid::Stop(JNIEnv* env, bool clear_results) { - autocomplete_controller_->Stop(clear_results); + autocomplete_controller_->Stop(clear_results + ? AutocompleteStopReason::kClobbered + : AutocompleteStopReason::kInteraction); } void AutocompleteControllerAndroid::ResetSession(JNIEnv* env) {
diff --git a/chrome/browser/ash/app_list/search/omnibox/omnibox_provider.cc b/chrome/browser/ash/app_list/search/omnibox/omnibox_provider.cc index 8242e98..67cff74 100644 --- a/chrome/browser/ash/app_list/search/omnibox/omnibox_provider.cc +++ b/chrome/browser/ash/app_list/search/omnibox/omnibox_provider.cc
@@ -26,6 +26,7 @@ #include "chrome/browser/profiles/profile.h" #include "components/favicon/core/favicon_service.h" #include "components/omnibox/browser/autocomplete_classifier.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/prefs/pref_service.h" #include "third_party/metrics_proto/omnibox_event.pb.h" @@ -73,7 +74,7 @@ last_query_ = query; last_tokenized_query_.emplace(query, TokenizedString::Mode::kCamelCase); - controller_->Stop(false); + controller_->Stop(AutocompleteStopReason::kInteraction); query_finished_ = false; // The new page classification value(CHROMEOS_APP_LIST) is introduced // to differentiate the suggest requests initiated by ChromeOS app_list from @@ -91,7 +92,7 @@ last_tokenized_query_.reset(); query_finished_ = false; - controller_->Stop(true); + controller_->Stop(AutocompleteStopReason::kClobbered); } ash::AppListSearchResultType OmniboxProvider::ResultType() const {
diff --git a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc index c992fe3c..376c3cf 100644 --- a/chrome/browser/ash/input_method/native_input_method_engine_observer.cc +++ b/chrome/browser/ash/input_method/native_input_method_engine_observer.cc
@@ -475,6 +475,8 @@ return mojom::NamedDomKey::kAudioVolumeDown; case ui::DomKey::AUDIO_VOLUME_UP: return mojom::NamedDomKey::kAudioVolumeUp; + case ui::DomKey::NUM_LOCK: + return mojom::NamedDomKey::kNumLock; default: return std::nullopt; }
diff --git a/chrome/browser/autocomplete/keyword_extensions_delegate_impl.cc b/chrome/browser/autocomplete/keyword_extensions_delegate_impl.cc index 07edcb8..044a2da 100644 --- a/chrome/browser/autocomplete/keyword_extensions_delegate_impl.cc +++ b/chrome/browser/autocomplete/keyword_extensions_delegate_impl.cc
@@ -54,18 +54,19 @@ base::UTF16ToUTF8(suggestion_text)); } -void KeywordExtensionsDelegateImpl::IncrementInputId() { +void KeywordExtensionsDelegateImpl::IncrementInputId() { current_input_id_ = ++global_input_uid_; } bool KeywordExtensionsDelegateImpl::IsEnabledExtension( const std::string& extension_id) { const extensions::Extension* extension = - extensions::ExtensionRegistry::Get( - profile_)->enabled_extensions().GetByID(extension_id); + extensions::ExtensionRegistry::Get(profile_) + ->enabled_extensions() + .GetByID(extension_id); return extension && - (!profile_->IsOffTheRecord() || - extensions::util::IsIncognitoEnabled(extension_id, profile_)); + (!profile_->IsOffTheRecord() || + extensions::util::IsIncognitoEnabled(extension_id, profile_)); } bool KeywordExtensionsDelegateImpl::Start(
diff --git a/chrome/browser/back_press/android/BUILD.gn b/chrome/browser/back_press/android/BUILD.gn index 669fcd85..95e1c625 100644 --- a/chrome/browser/back_press/android/BUILD.gn +++ b/chrome/browser/back_press/android/BUILD.gn
@@ -67,6 +67,7 @@ "//components/browser_ui/widget/android:java", "//content/public/test/android:content_java_test_support", "//third_party/androidx:androidx_activity_activity_java", + "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_test_runner_java", "//third_party/hamcrest:hamcrest_java", "//third_party/junit",
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java index d6b74f3..5f208cb 100644 --- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java +++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManager.java
@@ -7,14 +7,18 @@ import static org.chromium.build.NullUtil.assumeNonNull; import android.annotation.SuppressLint; +import android.os.Build; import android.util.SparseIntArray; +import android.window.OnBackInvokedCallback; import androidx.activity.BackEventCompat; import androidx.activity.OnBackPressedCallback; +import androidx.annotation.RequiresApi; import androidx.annotation.VisibleForTesting; import org.chromium.base.Callback; import org.chromium.base.CallbackUtils; +import org.chromium.base.ObserverList; import org.chromium.base.lifetime.Destroyable; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.supplier.Supplier; @@ -24,6 +28,7 @@ import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; import org.chromium.components.browser_ui.widget.gesture.BackPressHandler.BackPressResult; import org.chromium.components.browser_ui.widget.gesture.BackPressHandler.Type; +import org.chromium.components.browser_ui.widget.gesture.OnSystemNavigationObserver; /** * A central manager class to handle the back gesture. Every component/feature which is going to @@ -166,10 +171,13 @@ private boolean mHasSystemBackArm; private final @Nullable Callback<Boolean>[] mObserverCallbacks = new Callback[Type.NUM_TYPES]; + private @Nullable OnBackInvokedCallback mOnSystemNavigationCallback; private Runnable mFallbackOnBackPressed; private int mLastCalledHandlerType = -1; private @Nullable Runnable mOnBackPressed; private Supplier<Boolean> mIsGestureNavEnabledSupplier = () -> false; + private final ObserverList<OnSystemNavigationObserver> mOnSystemNavigationObservers = + new ObserverList<>(); /** * Record when the back press is consumed by a certain feature. @@ -210,6 +218,11 @@ public BackPressManager() { mFallbackOnBackPressed = CallbackUtils.emptyRunnable(); mUseSystemBack = MinimizeAppAndCloseTabBackPressHandler.shouldUseSystemBack(); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BAKLAVA) { + createOnSystemNavigationCallback(); + } + backPressStateChanged(); } @@ -274,6 +287,18 @@ return mCallback; } + /** + * Callback when the back press is not consumed by any feature {@link BackPressHandler} and this + * back press will be consumed by the Android OS. In this case, Clank is minimized by the OS. + * + * @return The callback registered by OS to observe system navigation events; return null if the + * current OS does not support this feature. + */ + @Nullable + public OnBackInvokedCallback getOnSystemNavigationCallback() { + return mOnSystemNavigationCallback; + } + /* * @param fallbackOnBackPressed Callback executed when a handler claims to intercept back press * but no handler succeeds. @@ -305,6 +330,27 @@ mIsGestureNavEnabledSupplier = supplier; } + /** + * Add a new observer to observe the system navigation event. See details at {@link + * OnSystemNavigationObserver}. All registered observers will be called and any two observers + * should be mutually exclusive. + * + * @param observer The observer of system navigation to add. + */ + public void addOnSystemNavigationObserver(OnSystemNavigationObserver observer) { + mOnSystemNavigationObservers.addObserver(observer); + } + + /** + * Remove a new observer to observe the system navigation event. See details at {@link + * OnSystemNavigationObserver}. + * + * @param observer The observer of system navigation to remove. + */ + public void removeOnSystemNavigationObserver(OnSystemNavigationObserver observer) { + mOnSystemNavigationObservers.removeObserver(observer); + } + private void backPressStateChanged() { boolean intercept = shouldInterceptBackPress(); if (mHasSystemBackArm) { @@ -365,6 +411,22 @@ assert !failed : "Callback is enabled but no handler consumed back gesture."; } + private void onSystemNavigationInternal() { + mOnSystemNavigationObservers.forEach(OnSystemNavigationObserver::onSystemNavigation); + } + + @VisibleForTesting + @RequiresApi(api = Build.VERSION_CODES.TIRAMISU) + void createOnSystemNavigationCallback() { + mOnSystemNavigationCallback = + new OnBackInvokedCallback() { + @Override + public void onBackInvoked() { + onSystemNavigationInternal(); + } + }; + } + @Override public void destroy() { for (int i = 0; i < mHandlers.length; i++) { @@ -372,6 +434,7 @@ removeHandler(i); } } + mOnSystemNavigationObservers.clear(); } @VisibleForTesting
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManagerUnitTest.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManagerUnitTest.java index 32fa8f1..989fdfe 100644 --- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManagerUnitTest.java +++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/BackPressManagerUnitTest.java
@@ -5,9 +5,11 @@ package org.chromium.chrome.browser.back_press; import android.os.Build; +import android.window.OnBackInvokedCallback; import androidx.activity.BackEventCompat; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import org.junit.Assert; import org.junit.Before; @@ -19,6 +21,7 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.base.test.util.CallbackHelper; +import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; import java.util.concurrent.TimeoutException; @@ -473,6 +476,22 @@ callbackHelper.waitForCallback("Callback should be called again", 1); } + @RequiresApi(api = Build.VERSION_CODES.TIRAMISU) + @Test + @MinAndroidSdkLevel(Build.VERSION_CODES.TIRAMISU) + public void testOnSystemNavigationObserver() { + BackPressManager manager = new BackPressManager(); + manager.createOnSystemNavigationCallback(); + OnBackInvokedCallback callback = manager.getOnSystemNavigationCallback(); + CallbackHelper callbackHelper = new CallbackHelper(); + + manager.addOnSystemNavigationObserver(callbackHelper::notifyCalled); + manager.addOnSystemNavigationObserver(callbackHelper::notifyCalled); + + callback.onBackInvoked(); + Assert.assertEquals("All observers should be called", 2, callbackHelper.getCallCount()); + } + private int getHandlerCount(BackPressManager manager) { int count = 0; for (BackPressHandler handler : manager.getHandlersForTesting()) {
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandler.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandler.java index 5d8f37f..913f6677 100644 --- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandler.java +++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandler.java
@@ -18,10 +18,11 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; -import org.chromium.chrome.browser.tab.TabAssociatedApp; import org.chromium.chrome.browser.ui.native_page.NativePage; import org.chromium.components.browser_ui.widget.gesture.BackPressHandler; +import org.chromium.components.browser_ui.widget.gesture.OnSystemNavigationObserver; import org.chromium.content_public.browser.WebContents; import java.util.function.Predicate; @@ -31,7 +32,8 @@ * to manually minimize app and close tab if necessary. */ @NullMarked -public class MinimizeAppAndCloseTabBackPressHandler implements BackPressHandler, Destroyable { +public class MinimizeAppAndCloseTabBackPressHandler + implements BackPressHandler, OnSystemNavigationObserver, Destroyable { static final String HISTOGRAM = "Android.BackPress.MinimizeAppAndCloseTab"; static final String HISTOGRAM_CUSTOM_TAB_SAME_TASK = "Android.BackPress.MinimizeAppAndCloseTab.CustomTab.SameTask"; @@ -47,7 +49,9 @@ private final ObservableSupplierImpl<Boolean> mNonSystemBackPressSupplier = new ObservableSupplierImpl<>(); private final Predicate<Tab> mBackShouldCloseTab; + private final Predicate<Tab> mMinimizationShouldCloseTab; private final Callback<@Nullable Tab> mSendToBackground; + private final Callback<Tab> mCloseTabUponMinimization; private final Callback<Tab> mOnTabChanged = this::onTabChanged; private final ObservableSupplier<Tab> mActivityTabSupplier; private final boolean mUseSystemBack; @@ -67,8 +71,17 @@ int NUM_TYPES = 3; } + /** Whether the feature of closing tab during minimization is supported. */ + public static boolean supportCloseTabUponMinimization() { + boolean isAtLeastB = + (sVersionForTesting == null ? VERSION.SDK_INT : sVersionForTesting) + >= VERSION_CODES.BAKLAVA; + return isAtLeastB && ChromeFeatureList.sAllowTabClosingUponMinimization.isEnabled(); + } + /** * Record metrics of how back press is finally consumed by the app. + * * @param type The action we do when back press is consumed. */ public static void record(@MinimizeAppAndCloseTabType int type) { @@ -92,15 +105,20 @@ /** * @param activityTabSupplier Supplier giving the current interact-able tab. - * @param backShouldCloseTab Test whether the current tab should be closed on back press. + * @param backShouldCloseTab Test whether the back press should be intercepted to close tab. + * @param minimizationShouldCloseTab Test whether the tab should be closed during minimization. + * @param closeTabUponMinimization Callback triggered during minimization to close tab. * @param sendToBackground Callback when app should be sent to background on back press. - * @param callbackOnBackPress Callback when back press is handled. */ public MinimizeAppAndCloseTabBackPressHandler( ObservableSupplier<Tab> activityTabSupplier, Predicate<Tab> backShouldCloseTab, + Predicate<Tab> minimizationShouldCloseTab, + Callback<Tab> closeTabUponMinimization, Callback<@Nullable Tab> sendToBackground) { mBackShouldCloseTab = backShouldCloseTab; + mMinimizationShouldCloseTab = minimizationShouldCloseTab; + mCloseTabUponMinimization = closeTabUponMinimization; mSendToBackground = sendToBackground; mActivityTabSupplier = activityTabSupplier; mUseSystemBack = shouldUseSystemBack(); @@ -132,6 +150,8 @@ } } + if (supportCloseTabUponMinimization()) assert !minimizeApp : "Should be minimized by OS"; + if (minimizeApp) { record( shouldCloseTab @@ -150,13 +170,19 @@ return BackPressResult.SUCCESS; } - private Pair<Boolean, Boolean> determineBackPressAction(Tab currentTab) { + @Override + public void onSystemNavigation() { + Tab currentTab = mActivityTabSupplier.get(); + if (currentTab != null && mMinimizationShouldCloseTab.test(currentTab)) { + mCloseTabUponMinimization.onResult(currentTab); + } + } + + private Pair<Boolean, Boolean> determineBackPressAction(@Nullable Tab currentTab) { boolean minimizeApp; boolean shouldCloseTab; if (currentTab == null) { - assert !mUseSystemBack - : "Should be disabled when there is no valid tab and back press is consumed."; minimizeApp = true; shouldCloseTab = false; } else { @@ -164,9 +190,8 @@ // Minimize the app if either: // - we decided not to close the tab - // - we decided to close the tab, but it was opened by an external app, so we will go - // exit Chrome on top of closing the tab - minimizeApp = !shouldCloseTab || TabAssociatedApp.isOpenedFromExternalApp(currentTab); + // - we decided to close the tab, but this can be closed during minimization. + minimizeApp = !shouldCloseTab || mMinimizationShouldCloseTab.test(currentTab); } return new Pair(minimizeApp, shouldCloseTab); @@ -183,7 +208,13 @@ } private void onTabChanged(Tab tab) { - mSystemBackPressSupplier.set(tab != null && mBackShouldCloseTab.test(tab)); + if (supportCloseTabUponMinimization()) { + Pair<Boolean, Boolean> backPressAction = determineBackPressAction(tab); + boolean minimizeApp = backPressAction.first; + mSystemBackPressSupplier.set(!minimizeApp); + } else { + mSystemBackPressSupplier.set(tab != null && mBackShouldCloseTab.test(tab)); + } } static boolean shouldUseSystemBack() {
diff --git a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandlerUnitTest.java b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandlerUnitTest.java index 8921d2e..ae284072 100644 --- a/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandlerUnitTest.java +++ b/chrome/browser/back_press/android/java/src/org/chromium/chrome/browser/back_press/MinimizeAppAndCloseTabBackPressHandlerUnitTest.java
@@ -11,7 +11,6 @@ import androidx.activity.BackEventCompat; import androidx.test.filters.SmallTest; -import org.hamcrest.Matchers; import org.junit.Assert; import org.junit.Before; import org.junit.Rule; @@ -29,8 +28,10 @@ import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.test.BaseJUnit4ClassRunner; import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.Features; import org.chromium.base.test.util.HistogramWatcher; import org.chromium.chrome.browser.back_press.MinimizeAppAndCloseTabBackPressHandler.MinimizeAppAndCloseTabType; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabAssociatedApp; import org.chromium.chrome.browser.tab.TabLaunchType; @@ -50,6 +51,9 @@ @Mock private Predicate<Tab> mShouldCloseTab; + @Mock private Predicate<Tab> mMinimizationShouldCloseTab; + @Mock private Callback<Tab> mCloseTabUponMinimization; + @Mock private Tab mTab; private MinimizeAppAndCloseTabBackPressHandler mHandler; @@ -68,9 +72,7 @@ MinimizeAppAndCloseTabBackPressHandler.HISTOGRAM, MinimizeAppAndCloseTabType.MINIMIZE_APP_AND_CLOSE_TAB); Mockito.when(mShouldCloseTab.test(mTab)).thenReturn(true); - UserDataHost userDataHost = ThreadUtils.runOnUiThreadBlocking(() -> new UserDataHost()); - Mockito.when(mTab.getUserDataHost()).thenReturn(userDataHost); - ThreadUtils.runOnUiThreadBlocking(() -> TabAssociatedApp.from(mTab)); + Mockito.when(mMinimizationShouldCloseTab.test(mTab)).thenReturn(true); Mockito.when(mTab.getLaunchType()).thenReturn(TabLaunchType.FROM_EXTERNAL_APP); ThreadUtils.runOnUiThreadBlocking(() -> mActivityTabSupplier.set(mTab)); Assert.assertTrue(mHandler.getHandleBackPressChangedSupplier().get()); @@ -153,38 +155,34 @@ @Test @SmallTest - public void testMinimizeApp_NoValidTab_SystemBack() { - createBackPressHandler(true); + @Features.EnableFeatures({ChromeFeatureList.ALLOW_TAB_CLOSING_UPON_MINIMIZATION}) + public void testCloseTabDuringMinimization() { + createBackPressHandler(true, true); + Mockito.when(mShouldCloseTab.test(mTab)).thenReturn(true); + Mockito.when(mMinimizationShouldCloseTab.test(mTab)).thenReturn(true); + Mockito.when(mTab.getLaunchType()).thenReturn(TabLaunchType.FROM_EXTERNAL_APP); + ThreadUtils.runOnUiThreadBlocking(() -> mActivityTabSupplier.set(mTab)); + Assert.assertFalse(mHandler.getHandleBackPressChangedSupplier().get()); - var histogram = - HistogramWatcher.newBuilder() - .expectNoRecords(MinimizeAppAndCloseTabBackPressHandler.HISTOGRAM) - .build(); - ThreadUtils.runOnUiThreadBlocking( - () -> { - mActivityTabSupplier.set(null); - }); - - Assert.assertFalse( - "Back press should be handled by OS.", - mHandler.getHandleBackPressChangedSupplier().get()); - - thrown.expect(Matchers.instanceOf(AssertionError.class)); - thrown.expectMessage( - "Should be disabled when there is no valid tab and back press is consumed."); - - mHandler.handleBackPress(); - histogram.assertExpected(); - verify(mSendToBackground, Mockito.never()).onResult(Mockito.any()); - verify(mShouldCloseTab, Mockito.never()).test(Mockito.any()); + ThreadUtils.runOnUiThreadBlocking(mHandler::onSystemNavigation); + verify( + mCloseTabUponMinimization, + Mockito.description("Tab should be closed during minimizing the app.")) + .onResult(mTab); } private void createBackPressHandler() { - createBackPressHandler(false); + createBackPressHandler(false, false); } private void createBackPressHandler(boolean systemBack) { - if (systemBack) { + createBackPressHandler(systemBack, false); + } + + private void createBackPressHandler(boolean systemBack, boolean systemMinimize) { + if (systemMinimize) { + MinimizeAppAndCloseTabBackPressHandler.setVersionForTesting(VERSION_CODES.BAKLAVA); + } else if (systemBack) { MinimizeAppAndCloseTabBackPressHandler.setVersionForTesting(VERSION_CODES.TIRAMISU); } ThreadUtils.runOnUiThreadBlocking( @@ -195,6 +193,10 @@ ThreadUtils.runOnUiThreadBlocking( () -> new MinimizeAppAndCloseTabBackPressHandler( - mActivityTabSupplier, mShouldCloseTab, mSendToBackground)); + mActivityTabSupplier, + mShouldCloseTab, + mMinimizationShouldCloseTab, + mCloseTabUponMinimization, + mSendToBackground)); } }
diff --git a/chrome/browser/contextual_cueing/contextual_cueing_service.cc b/chrome/browser/contextual_cueing/contextual_cueing_service.cc index 42951fe..9970a85d 100644 --- a/chrome/browser/contextual_cueing/contextual_cueing_service.cc +++ b/chrome/browser/contextual_cueing/contextual_cueing_service.cc
@@ -294,22 +294,31 @@ return; } - // Remote suggestions generation. ZeroStateSuggestionsPageData* page_data = ZeroStateSuggestionsPageData::GetOrCreateForPage( web_contents->GetPrimaryPage()); - page_data->FetchSuggestions(is_fre, std::move(callback)); + page_data->FetchSuggestions( + is_fre, base::BindOnce(&ContextualCueingService::OnSuggestionsReceived, + weak_ptr_factory_.GetWeakPtr(), + base::TimeTicks::Now(), std::move(callback))); #else std::move(callback).Run(std::nullopt); #endif } void ContextualCueingService::OnSuggestionsReceived( - content::WebContents* web_contents, + base::TimeTicks fetch_begin_time, GlicSuggestionsCallback callback, std::optional<std::vector<std::string>> suggestions) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + base::UmaHistogramTimes(suggestions + ? "ContextualCueing.GlicSuggestions." + "SuggestionsFetchLatency.ValidSuggestions" + : "ContextualCueing.GlicSuggestions." + "SuggestionsFetchLatency.EmptySuggestions", + base::TimeTicks::Now() - fetch_begin_time); + std::move(callback).Run(suggestions); }
diff --git a/chrome/browser/contextual_cueing/contextual_cueing_service.h b/chrome/browser/contextual_cueing/contextual_cueing_service.h index 892c1c51..6150ec1 100644 --- a/chrome/browser/contextual_cueing/contextual_cueing_service.h +++ b/chrome/browser/contextual_cueing/contextual_cueing_service.h
@@ -101,7 +101,7 @@ // Called when suggestions are received. Cleans up after suggestions // generation. void OnSuggestionsReceived( - content::WebContents* web_contents, + base::TimeTicks fetch_begin_time, GlicSuggestionsCallback callback, std::optional<std::vector<std::string>> suggestions);
diff --git a/chrome/browser/contextual_cueing/contextual_cueing_service_browsertest.cc b/chrome/browser/contextual_cueing/contextual_cueing_service_browsertest.cc index 565d13e..1d10714 100644 --- a/chrome/browser/contextual_cueing/contextual_cueing_service_browsertest.cc +++ b/chrome/browser/contextual_cueing/contextual_cueing_service_browsertest.cc
@@ -14,6 +14,8 @@ #include "chrome/browser/contextual_cueing/contextual_cueing_service_factory.h" #include "chrome/browser/extensions/keyed_services/browser_context_keyed_service_factories.h" #include "chrome/browser/optimization_guide/browser_test_util.h" +#include "chrome/browser/optimization_guide/mock_optimization_guide_keyed_service.h" +#include "chrome/browser/optimization_guide/optimization_guide_keyed_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/ui/browser.h" @@ -22,6 +24,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "components/optimization_guide/proto/contextual_cueing_metadata.pb.h" #include "components/prefs/pref_service.h" #include "components/search_engines/template_url_service.h" #include "content/public/test/browser_test.h" @@ -34,6 +37,10 @@ namespace contextual_cueing { +using ::testing::_; +using ::testing::An; +using ::testing::WithArgs; + class ContextualCueingServiceBrowserTest : public InProcessBrowserTest { public: ContextualCueingServiceBrowserTest() = default; @@ -308,6 +315,131 @@ "ZeroStateSuggestions", 0); } + +class ContextualCueingServiceBrowserTestZSSHistogram + : public ContextualCueingServiceBrowserTest { + public: + ContextualCueingServiceBrowserTestZSSHistogram() { + scoped_feature_list_.InitAndEnableFeature(kGlicZeroStateSuggestions); + } + + void SetUpOnMainThread() override { + browser()->profile()->GetPrefs()->SetBoolean( + glic::prefs::kGlicTabContextEnabled, true); + base::CommandLine::ForCurrentProcess()->AppendSwitch( + optimization_guide::switches:: + kDisableCheckingUserPermissionsForTesting); + } + + void PostRunTestOnMainThread() override { + mock_optimization_guide_keyed_service_ = nullptr; + InProcessBrowserTest::PostRunTestOnMainThread(); + } + + void SetUpBrowserContextKeyedServices( + content::BrowserContext* browser_context) override { + mock_optimization_guide_keyed_service_ = + static_cast<testing::NiceMock<MockOptimizationGuideKeyedService>*>( + OptimizationGuideKeyedServiceFactory::GetInstance() + ->SetTestingFactoryAndUse( + browser_context, + base::BindRepeating([](content::BrowserContext* context) + -> std::unique_ptr<KeyedService> { + return std::make_unique<testing::NiceMock< + MockOptimizationGuideKeyedService>>(); + }))); + } + + MockOptimizationGuideKeyedService& mock_optimization_guide_keyed_service() { + return *mock_optimization_guide_keyed_service_; + } + + void SetUpHints(bool allow_contextual) { + ON_CALL(mock_optimization_guide_keyed_service(), + CanApplyOptimization( + _, optimization_guide::proto::GLIC_ZERO_STATE_SUGGESTIONS, + An<optimization_guide::OptimizationGuideDecisionCallback>())) + .WillByDefault(WithArgs<2>( + [=](optimization_guide::OptimizationGuideDecisionCallback + callback) { + optimization_guide::proto::GlicZeroStateSuggestionsMetadata + metadata; + metadata.set_contextual_suggestions_eligible(allow_contextual); + if (allow_contextual) { + metadata.mutable_contextual_suggestions()->Add("suggestion"); + } + + optimization_guide::OptimizationMetadata og_metadata; + og_metadata.SetAnyMetadataForTesting(metadata); + std::move(callback).Run( + optimization_guide::OptimizationGuideDecision::kTrue, + og_metadata); + })); + } + + protected: + raw_ptr<testing::NiceMock<MockOptimizationGuideKeyedService>> + mock_optimization_guide_keyed_service_; +}; + +IN_PROC_BROWSER_TEST_F(ContextualCueingServiceBrowserTestZSSHistogram, + LogsLatencyForValidSuggestions) { + base::HistogramTester histogram_tester; + SetUpHints(/*allow_contextual=*/true); + + auto* service = + ContextualCueingServiceFactory::GetForProfile(browser()->profile()); + + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL("/optimization_guide/zss_page.html"))); + + base::test::TestFuture<std::optional<std::vector<std::string>>> future; + auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + service->GetContextualGlicZeroStateSuggestions(web_contents, /*is_fre=*/true, + future.GetCallback()); + ASSERT_TRUE(future.Wait()); + + histogram_tester.ExpectTotalCount( + "ContextualCueing.GlicSuggestions.SuggestionsFetchLatency." + "ValidSuggestions", + 1); + histogram_tester.ExpectTotalCount( + "ContextualCueing.GlicSuggestions.SuggestionsFetchLatency." + "EmptySuggestions", + 0); +} + +IN_PROC_BROWSER_TEST_F(ContextualCueingServiceBrowserTestZSSHistogram, + LogsLatencyForEmptySuggestions) { + base::HistogramTester histogram_tester; + SetUpHints(/*allow_contextual=*/false); + + auto* service = + ContextualCueingServiceFactory::GetForProfile(browser()->profile()); + + ASSERT_TRUE(embedded_test_server()->Start()); + ASSERT_TRUE(ui_test_utils::NavigateToURL( + browser(), + embedded_test_server()->GetURL("/optimization_guide/zss_page.html"))); + + base::test::TestFuture<std::optional<std::vector<std::string>>> future; + auto* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); + service->GetContextualGlicZeroStateSuggestions(web_contents, /*is_fre=*/true, + future.GetCallback()); + ASSERT_TRUE(future.Wait()); + + histogram_tester.ExpectTotalCount( + "ContextualCueing.GlicSuggestions.SuggestionsFetchLatency." + "EmptySuggestions", + 1); + histogram_tester.ExpectTotalCount( + "ContextualCueing.GlicSuggestions.SuggestionsFetchLatency." + "ValidSuggestions", + 0); +} + #endif class ContextualCueingServiceBrowserTestCCFlag
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java index 010f5f3..248d4088 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/DownloadManagerCoordinatorImpl.java
@@ -92,7 +92,8 @@ new ToolbarCoordinator( mActivity, this, - mListCoordinator, + /* listActionDelegate= */ mListCoordinator, + /* listContentView= */ mListCoordinator.getView(), mSelectionDelegate, config.isSeparateActivity, tracker);
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java index cebd99a8..a0b7a11 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/toolbar/DownloadHomeToolbar.java
@@ -11,6 +11,7 @@ import org.chromium.base.BuildInfo; import org.chromium.base.metrics.RecordUserAction; +import org.chromium.build.annotations.Initializer; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; import org.chromium.chrome.browser.download.home.list.ListItem; @@ -24,6 +25,7 @@ @NullMarked public class DownloadHomeToolbar extends SelectableListToolbar<ListItem> { private @Nullable UiConfig mUiConfig; + private View mListContentView; public DownloadHomeToolbar(Context context, AttributeSet attrs) { super(context, attrs); @@ -96,4 +98,21 @@ } } } + + // SelectableListToolbar implementation. + @Override + protected boolean handleEnterKeyPress() { + return getMenu().performIdentifierAction(R.id.search_menu_id, 0); + } + + @Override + protected View getNextFocusForward() { + // Move focus to list content view. + return mListContentView; + } + + @Initializer + void setListContentView(View listContentView) { + mListContentView = listContentView; + } }
diff --git a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java index 14f287d..b20f436 100644 --- a/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java +++ b/chrome/browser/download/internal/android/java/src/org/chromium/chrome/browser/download/home/toolbar/ToolbarCoordinator.java
@@ -93,6 +93,7 @@ Context context, ToolbarActionDelegate delegate, ToolbarListActionDelegate listActionDelegate, + View listContentView, SelectionDelegate<ListItem> selectionDelegate, boolean hasCloseButton, Tracker tracker) { @@ -112,6 +113,8 @@ R.id.selection_mode_menu_group, hasCloseButton); mToolbar.setOnMenuItemClickListener(this::onMenuItemClick); + mToolbar.setFocusable(true); + mToolbar.setListContentView(listContentView); // TODO(crbug.com/41412009): Pass the visible group to the toolbar during initialization. mToolbar.initializeSearchView(
diff --git a/chrome/browser/enterprise/profile_management/oidc_auth_response_capture_navigation_throttle_unittest.cc b/chrome/browser/enterprise/profile_management/oidc_auth_response_capture_navigation_throttle_unittest.cc index 0cda658..c98894ce 100644 --- a/chrome/browser/enterprise/profile_management/oidc_auth_response_capture_navigation_throttle_unittest.cc +++ b/chrome/browser/enterprise/profile_management/oidc_auth_response_capture_navigation_throttle_unittest.cc
@@ -6,6 +6,7 @@ #include "base/base64.h" #include "base/base64url.h" +#include "base/features.h" #include "base/json/json_writer.h" #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" @@ -723,6 +724,23 @@ OidcInterceptionResult::kInvalidUrlOrTokens); } +TEST_P(OidcAuthResponseCaptureNavigationThrottleTest, DataDecoderFailure) { + // Disable the Rust JSON parser, as it is in-process and cannot crash. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatureState(base::features::kUseRustJsonParser, false); + in_process_data_decoder_.SimulateJsonParserCrash(/*drop=*/true); + + std::string redirection_url = + BuildStandardResponseUrl(/*oidc_state=*/std::string()); + + auto* oidc_interceptor = GetMockOidcInterceptor(); + RunThrottleAndExpectNoOidcInterception(oidc_interceptor, redirection_url, + NavigationThrottle::DEFER); + CheckFunnelAndResultHistogram( + OidcInterceptionFunnelStep::kValidRedirectionCaptured, + OidcInterceptionResult::kInvalidUrlOrTokens); +} + TEST_P(OidcAuthResponseCaptureNavigationThrottleTest, NoServiceForGuestMode) { TestNoServiceForInvalidProfile(profile_manager()->CreateGuestProfile()); }
diff --git a/chrome/browser/extensions/ai_language_model_browsertest.cc b/chrome/browser/extensions/ai_language_model_browsertest.cc index 15fcb50..c75e3a6 100644 --- a/chrome/browser/extensions/ai_language_model_browsertest.cc +++ b/chrome/browser/extensions/ai_language_model_browsertest.cc
@@ -79,6 +79,11 @@ ); chrome.test.succeed(); }, + function verifyLanguageModel() { + const expectLanguageModel = %s; + chrome.test.assertEq(expectLanguageModel, !!self.LanguageModel); + chrome.test.succeed(); + }, ]); )JS"; @@ -240,11 +245,12 @@ IsExtensionParticipatingInOriginTrial(GetParam())) && IsExtensionPermissionRequested(GetParam()) && !IsPromptAPIForExtensionKillSwitchTriggered(GetParam()); - test_dir.WriteFile( - FILE_PATH_LITERAL("sw.js"), - base::StringPrintf(kServiceWorkerScript, - base::ToString(is_self_ai_accessible), - base::ToString(is_chrome_ai_accessible))); + bool is_global_accessible = is_self_ai_accessible || is_chrome_ai_accessible; + test_dir.WriteFile(FILE_PATH_LITERAL("sw.js"), + base::StringPrintf(kServiceWorkerScript, + base::ToString(is_self_ai_accessible), + base::ToString(is_chrome_ai_accessible), + base::ToString(is_global_accessible))); ResultCatcher result_catcher; const Extension* extension = LoadExtension(test_dir.UnpackedPath()); ASSERT_TRUE(extension);
diff --git a/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc index b5fe446f..0535f39 100644 --- a/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/action_tracker_unittest.cc
@@ -23,6 +23,8 @@ #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" #include "url/gurl.h" +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + namespace extensions { namespace declarative_net_request {
diff --git a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc index 5bd746d47..5ec7e11 100644 --- a/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc
@@ -62,6 +62,8 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + namespace extensions { namespace declarative_net_request { namespace {
diff --git a/chrome/browser/extensions/api/declarative_net_request/dnr_test_base.cc b/chrome/browser/extensions/api/declarative_net_request/dnr_test_base.cc index bc34460..f7287af 100644 --- a/chrome/browser/extensions/api/declarative_net_request/dnr_test_base.cc +++ b/chrome/browser/extensions/api/declarative_net_request/dnr_test_base.cc
@@ -6,6 +6,8 @@ #include "chrome/browser/extensions/chrome_test_extension_loader.h" +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + namespace extensions { namespace declarative_net_request {
diff --git a/chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h b/chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h index 778dda12..8bf533b 100644 --- a/chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h +++ b/chrome/browser/extensions/api/declarative_net_request/dnr_test_base.h
@@ -11,6 +11,8 @@ #include "extensions/browser/api/declarative_net_request/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + namespace extensions { class ChromeTestExtensionLoader;
diff --git a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc index 7f63e1b..c2dcbfa 100644 --- a/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc +++ b/chrome/browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc
@@ -42,6 +42,8 @@ #include "url/gurl.h" #include "url/origin.h" +static_assert(BUILDFLAG(ENABLE_EXTENSIONS_CORE)); + namespace extensions::declarative_net_request { namespace dnr_api = api::declarative_net_request;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index e17f127..e49ba08f7 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -169,6 +169,11 @@ "expiry_milestone": 140 }, { + "name": "allow-tab-closing-upon-minimization", + "owners": ["lazzzis@google.com", "twellington@chromium.org", "clank-app-team@google.com"], + "expiry_milestone": 142 + }, + { "name": "allow-user-installed-chrome-apps", "owners": ["//apps/DEPRECATION_OWNERS"], "expiry_milestone": 169 @@ -1735,6 +1740,11 @@ "expiry_milestone": 136 }, { + "name": "cpa-spec-update", + "owners": [ "eleanorlee@google.com", "wenyufu@chromium.org" ], + "expiry_milestone": 145 + }, + { "name": "cpe-automatic-passkey-upgrade", "owners": ["sugoi@chromium.org", "bling-transactions-eng@google.com"], "expiry_milestone": 145
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index fdca4d929d..8344a1ae 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -96,6 +96,12 @@ #endif #if BUILDFLAG(IS_ANDROID) +const char kAllowTabClosingUponMinimizationName[] = + "Allow tab to be closed during minimization"; +const char kAllowTabClosingUponMinimizationDescription[] = + "Utilize Android 16's new API to allow tab to be closed during minimization" + " triggered by back press."; + const char kAndroidAdaptiveFrameRateName[] = "Android Adaptive Refresh Rate features"; const char kAndroidAdaptiveFrameRateDescription[] = @@ -4681,6 +4687,11 @@ const char kConvertTrackpadEventsToMouseDescription[] = "Convert trackpad events to mouse events to improve gesture support"; +const char kCpaSpecUpdateName[] = "CpaSpecUpdate"; +const char kCpaSpecUpdateDescription[] = + "Updates the Cpa button animation and changes the shape of the checked " + "state button for stateful CPAs."; + const char kDeprecatedExternalPickerFunctionName[] = "Use deprecated External Picker method"; const char kDeprecatedExternalPickerFunctionDescription[] =
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 482f34bd..13b32f5 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -79,6 +79,9 @@ #endif // BUILDFLAG(ENABLE_EXTENSIONS) // #if BUILDFLAG(IS_ANDROID) +extern const char kAllowTabClosingUponMinimizationName[]; +extern const char kAllowTabClosingUponMinimizationDescription[]; + extern const char kAndroidAdaptiveFrameRateName[]; extern const char kAndroidAdaptiveFrameRateDescription[]; #endif @@ -2739,6 +2742,9 @@ extern const char kConvertTrackpadEventsToMouseName[]; extern const char kConvertTrackpadEventsToMouseDescription[]; +extern const char kCpaSpecUpdateName[]; +extern const char kCpaSpecUpdateDescription[]; + extern const char kDeprecatedExternalPickerFunctionName[]; extern const char kDeprecatedExternalPickerFunctionDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 3bdc9cfb..e641b56 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -182,6 +182,7 @@ &kAdaptiveButtonInTopToolbarCustomizationV2, &kAdaptiveButtonInTopToolbarPageSummary, &kAllowNewIncognitoTabIntents, + &kAllowTabClosingUponMinimization, &kAndroidAppIntegration, &kAndroidAppIntegrationV2, &kNewTabPageCustomization, @@ -269,6 +270,7 @@ &kContextualSearchDisableOnlineDetection, &kContextualSearchSuppressShortView, &kControlsVisibilityFromNavigations, + &kCpaSpecUpdate, &kCrossDeviceTabPaneAndroid, &kDeviceAuthenticatorAndroidx, &kDisableCompositedProgressBar, @@ -468,6 +470,10 @@ "AllowNewIncognitoTabIntents", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kAllowTabClosingUponMinimization, + "AllowTabClosingUponMinimization", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kDisableCompositedProgressBar, "DisableCompositedProgressBar", base::FEATURE_DISABLED_BY_DEFAULT); @@ -531,7 +537,7 @@ BASE_FEATURE(kAndroidNativePagesInNewTab, "AndroidNativePagesInNewTab", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); BASE_FEATURE(kAndroidNoVisibleHintForDifferentTLD, "AndroidNoVisibleHintForDifferentTLD", @@ -845,6 +851,10 @@ "ControlsVisibilityFromNavigations", base::FEATURE_ENABLED_BY_DEFAULT); +BASE_FEATURE(kCpaSpecUpdate, + "CpaSpecUpdate", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kCrossDeviceTabPaneAndroid, "CrossDeviceTabPaneAndroid", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h index bdae2b6..61ea261 100644 --- a/chrome/browser/flags/android/chrome_feature_list.h +++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -18,6 +18,7 @@ BASE_DECLARE_FEATURE(kAdaptiveButtonInTopToolbarCustomizationV2); BASE_DECLARE_FEATURE(kAdaptiveButtonInTopToolbarPageSummary); BASE_DECLARE_FEATURE(kAllowNewIncognitoTabIntents); +BASE_DECLARE_FEATURE(kAllowTabClosingUponMinimization); BASE_DECLARE_FEATURE(kAndroidAppIntegration); BASE_DECLARE_FEATURE(kAndroidAppIntegrationV2); BASE_DECLARE_FEATURE(kNewTabPageCustomization); @@ -107,6 +108,7 @@ BASE_DECLARE_FEATURE(kContextualSearchDisableOnlineDetection); BASE_DECLARE_FEATURE(kContextualSearchSuppressShortView); BASE_DECLARE_FEATURE(kControlsVisibilityFromNavigations); +BASE_DECLARE_FEATURE(kCpaSpecUpdate); BASE_DECLARE_FEATURE(kCrossDeviceTabPaneAndroid); BASE_DECLARE_FEATURE(kDeviceAuthenticatorAndroidx); BASE_DECLARE_FEATURE(kDisableCompositedProgressBar);
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java index a30de65e..ac506bf4 100644 --- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java +++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -159,6 +159,8 @@ public static final String ADAPTIVE_BUTTON_IN_TOP_TOOLBAR_PAGE_SUMMARY = "AdaptiveButtonInTopToolbarPageSummary"; public static final String ALLOW_NEW_INCOGNITO_TAB_INTENTS = "AllowNewIncognitoTabIntents"; + public static final String ALLOW_TAB_CLOSING_UPON_MINIMIZATION = + "AllowTabClosingUponMinimization"; public static final String ALWAYS_BLOCK_3PCS_INCOGNITO = "AlwaysBlock3pcsIncognito"; public static final String ANDROID_APPEARANCE_SETTINGS = "AndroidAppearanceSettings"; public static final String ANDROID_APP_INTEGRATION = "AndroidAppIntegration"; @@ -325,6 +327,7 @@ public static final String CONTROLS_VISIBILITY_FROM_NAVIGATIONS = "ControlsVisibilityFromNavigations"; public static final String CORMORANT = "Cormorant"; + public static final String CPA_SPEC_UPDATE = "CpaSpecUpdate"; public static final String CROSS_DEVICE_TAB_PANE_ANDROID = "CrossDeviceTabPaneAndroid"; public static final String DARKEN_WEBSITES_CHECKBOX_IN_THEMES_SETTING = "DarkenWebsitesCheckboxInThemesSetting"; @@ -611,6 +614,8 @@ public static final String XSURFACE_METRICS_REPORTING = "XsurfaceMetricsReporting"; /* Alphabetical: */ + public static final CachedFlag sAllowTabClosingUponMinimization = + newCachedFlag(ALLOW_TAB_CLOSING_UPON_MINIMIZATION, false); public static final CachedFlag sAndroidAppIntegration = newCachedFlag(ANDROID_APP_INTEGRATION, true); public static final CachedFlag sAndroidAppIntegrationModule = @@ -708,6 +713,7 @@ /* defaultValueInTests= */ true); public static final CachedFlag sCommandLineOnNonRooted = newCachedFlag(COMMAND_LINE_ON_NON_ROOTED, false); + public static final CachedFlag sCpaSpecUpdate = newCachedFlag(CPA_SPEC_UPDATE, false); public static final CachedFlag sCrossDeviceTabPaneAndroid = newCachedFlag(CROSS_DEVICE_TAB_PANE_ANDROID, false); public static final CachedFlag sDisableInstanceLimit = @@ -849,6 +855,7 @@ public static final List<CachedFlag> sFlagsCachedFullBrowser = List.of( + sAllowTabClosingUponMinimization, sAndroidAppIntegration, sAndroidAppIntegrationModule, sAndroidAppIntegrationMultiDataSource, @@ -894,6 +901,7 @@ sClankStartupLatencyInjection, sCollectAndroidFrameTimelineMetrics, sCommandLineOnNonRooted, + sCpaSpecUpdate, sCrossDeviceTabPaneAndroid, sDisableInstanceLimit, sDisableListTabSwitcher, @@ -974,7 +982,7 @@ public static final MutableFlagWithSafeDefault sAndroidDumpOnScrollWithoutResource = newMutableFlagWithSafeDefault(ANDROID_DUMP_ON_SCROLL_WITHOUT_RESOURCE, false); public static final MutableFlagWithSafeDefault sAndroidNativePagesInNewTab = - newMutableFlagWithSafeDefault(ANDROID_NATIVE_PAGES_IN_NEW_TAB, false); + newMutableFlagWithSafeDefault(ANDROID_NATIVE_PAGES_IN_NEW_TAB, true); public static final MutableFlagWithSafeDefault sAndroidTabDeclutter = newMutableFlagWithSafeDefault(ANDROID_TAB_DECLUTTER, true); public static final MutableFlagWithSafeDefault sAndroidTabDeclutterArchiveAllButActiveTab =
diff --git a/chrome/browser/glic/widget/glic_window_controller.cc b/chrome/browser/glic/widget/glic_window_controller.cc index 8f4ef27..010d93b 100644 --- a/chrome/browser/glic/widget/glic_window_controller.cc +++ b/chrome/browser/glic/widget/glic_window_controller.cc
@@ -263,7 +263,7 @@ glic_window_controller_->ShouldStartDrag(initial_press_loc_, mouse_location)) { glic_window_controller_->HandleWindowDragWithOffset( - mouse_location.OffsetFromOrigin()); + initial_press_loc_.OffsetFromOrigin()); } } @@ -1126,7 +1126,7 @@ GetGlicWidget()->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow); } GetGlicWidget()->RunMoveLoop( - GetClampedMouseDragOffset(mouse_offset), move_loop_source, + mouse_offset, move_loop_source, views::Widget::MoveLoopEscapeBehavior::kDontHide); in_move_loop_ = false; scoped_glic_button_indicator_.reset(); @@ -1134,6 +1134,7 @@ // request. glic_window_animator_->MaybeAnimateToTargetSize(); + AdjustPositionIfNeeded(); SaveWidgetPosition(); if (!AlwaysDetached()) { @@ -1150,16 +1151,22 @@ return panel_state_; } -gfx::Vector2d GlicWindowController::GetClampedMouseDragOffset( - const gfx::Vector2d& mouse_offset) { - static const int kMinimumDragOffset = 10; - const int max_x = GetGlicView()->width() - kMinimumDragOffset; - const int max_y = GlicWidget::GetInitialSize().height() - kMinimumDragOffset; - CHECK_GT(max_x, kMinimumDragOffset); - CHECK_GT(max_y, kMinimumDragOffset); +void GlicWindowController::AdjustPositionIfNeeded() { + // Always have at least `kMinimumVisible` px visible from glic window in + // both vertical and horizontal directions. + constexpr int kMinimumVisible = 40; + const auto widget_size = GetGlicWidget()->GetSize(); + const int horizontal_buffer = widget_size.width() - kMinimumVisible; + const int vertical_buffer = widget_size.height() - kMinimumVisible; - return {std::clamp(mouse_offset.x(), kMinimumDragOffset, max_x), - std::clamp(mouse_offset.y(), kMinimumDragOffset, max_y)}; + // Adjust bounds of visible area screen to allow part of glic to go off + // screen. + auto workarea = GetGlicWidget()->GetWorkAreaBoundsInScreen(); + workarea.Outset(gfx::Outsets::VH(vertical_buffer, horizontal_buffer)); + + auto rect = GetGlicWidget()->GetRestoredBounds(); + rect.AdjustToFit(workarea); + GetGlicWidget()->SetBounds(rect); } void GlicWindowController::OnDragComplete() {
diff --git a/chrome/browser/glic/widget/glic_window_controller.h b/chrome/browser/glic/widget/glic_window_controller.h index af6c6e5..1b485bbe 100644 --- a/chrome/browser/glic/widget/glic_window_controller.h +++ b/chrome/browser/glic/widget/glic_window_controller.h
@@ -365,8 +365,8 @@ // TODO(crbug.com/410629338): Reimplement attachment. void AttachToBrowser(Browser& browser, AttachChangeReason reason); - // Clamp the mouse drag offsets to keep glic within the visible region. - gfx::Vector2d GetClampedMouseDragOffset(const gfx::Vector2d& mouse_offset); + // Keep part of glic window within the visible region. + void AdjustPositionIfNeeded(); // Handles end-of-drag: // - If glic is within attachment distance of a browser window's glic button,
diff --git a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/SelectLanguageFragment.java b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/SelectLanguageFragment.java index 7a9d620..e0c7226 100644 --- a/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/SelectLanguageFragment.java +++ b/chrome/browser/language/android/java/src/org/chromium/chrome/browser/language/settings/SelectLanguageFragment.java
@@ -202,4 +202,9 @@ public void setProfile(Profile profile) { mProfile = profile; } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/media/android/java/res/layout/media_capture_picker_button_row.xml b/chrome/browser/media/android/java/res/layout/media_capture_picker_button_row.xml index f64711b..ba22dabf 100644 --- a/chrome/browser/media/android/java/res/layout/media_capture_picker_button_row.xml +++ b/chrome/browser/media/android/java/res/layout/media_capture_picker_button_row.xml
@@ -53,6 +53,15 @@ </LinearLayout> + <org.chromium.ui.widget.ButtonCompat + android:id="@+id/screen_button" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/dialog_padding_sides" + android:layout_gravity="end" + android:text="@string/media_capture_picker_dialog_window_or_screen_text" + style="@style/TextButton" /> + <org.chromium.components.browser_ui.widget.DualControlLayout android:id="@+id/button_bar" android:layout_width="match_parent"
diff --git a/chrome/browser/media/android/media_capture_picker_dialog_bridge.cc b/chrome/browser/media/android/media_capture_picker_dialog_bridge.cc index ab6b4500..d28edc8 100644 --- a/chrome/browser/media/android/media_capture_picker_dialog_bridge.cc +++ b/chrome/browser/media/android/media_capture_picker_dialog_bridge.cc
@@ -52,26 +52,35 @@ request_audio); } -void MediaCapturePickerDialogBridge::OnResult( +void MediaCapturePickerDialogBridge::OnPickTab( JNIEnv* env, const base::android::JavaParamRef<jobject>& java_web_contents, bool audio_share) { - content::DesktopMediaID desktop_media_id; - - // If no web contents was selected to capture, return a null DesktopMediaID. - // TODO(crbug.com/352186941): Implement for window and screen sharing. content::WebContents* web_contents = content::WebContents::FromJavaWebContents(java_web_contents); - if (web_contents) { - desktop_media_id = content::DesktopMediaID( - content::DesktopMediaID::TYPE_WEB_CONTENTS, - content::DesktopMediaID::kNullId, - content::WebContentsMediaCaptureId( - web_contents->GetPrimaryMainFrame() - ->GetProcess() - ->GetDeprecatedID(), - web_contents->GetPrimaryMainFrame()->GetRoutingID())); - desktop_media_id.audio_share = audio_share; - } + CHECK(web_contents); + auto desktop_media_id = content::DesktopMediaID( + content::DesktopMediaID::TYPE_WEB_CONTENTS, + content::DesktopMediaID::kNullId, + content::WebContentsMediaCaptureId( + web_contents->GetPrimaryMainFrame()->GetProcess()->GetDeprecatedID(), + web_contents->GetPrimaryMainFrame()->GetRoutingID())); + desktop_media_id.audio_share = audio_share; std::move(callback_).Run(desktop_media_id); } + +void MediaCapturePickerDialogBridge::OnPickWindow(JNIEnv* env) { + auto desktop_media_id = content::DesktopMediaID( + content::DesktopMediaID::TYPE_WINDOW, content::DesktopMediaID::kNullId); + std::move(callback_).Run(desktop_media_id); +} + +void MediaCapturePickerDialogBridge::OnPickScreen(JNIEnv* env) { + auto desktop_media_id = content::DesktopMediaID( + content::DesktopMediaID::TYPE_SCREEN, content::DesktopMediaID::kNullId); + std::move(callback_).Run(desktop_media_id); +} + +void MediaCapturePickerDialogBridge::OnCancel(JNIEnv* env) { + std::move(callback_).Run({}); +}
diff --git a/chrome/browser/media/android/media_capture_picker_dialog_bridge.h b/chrome/browser/media/android/media_capture_picker_dialog_bridge.h index a3d3dbc..4f0df251 100644 --- a/chrome/browser/media/android/media_capture_picker_dialog_bridge.h +++ b/chrome/browser/media/android/media_capture_picker_dialog_bridge.h
@@ -41,9 +41,18 @@ MediaCapturePickerDialogCallback callback); // Called from Java via JNI when the dialog resolves. - void OnResult(JNIEnv* env, - const base::android::JavaParamRef<jobject>& java_web_contents, - bool audio_share); + void OnPickTab(JNIEnv* env, + const base::android::JavaParamRef<jobject>& java_web_contents, + bool audio_share); + + // Called from Java via JNI when the dialog resolves. + void OnPickWindow(JNIEnv* env); + + // Called from Java via JNI when the dialog resolves. + void OnPickScreen(JNIEnv* env); + + // Called from Java via JNI when the dialog resolves. + void OnCancel(JNIEnv* env); private: MediaCapturePickerDialogCallback callback_;
diff --git a/chrome/browser/media/media_engagement_preloaded_list.cc b/chrome/browser/media/media_engagement_preloaded_list.cc index 9f775e0..bc08f85 100644 --- a/chrome/browser/media/media_engagement_preloaded_list.cc +++ b/chrome/browser/media/media_engagement_preloaded_list.cc
@@ -127,5 +127,5 @@ MediaEngagementPreloadedList::CheckStringIsPresent( const std::string& input) const { return static_cast<MediaEngagementPreloadedList::DafsaResult>( - net::LookupStringInFixedSet(dafsa_, input.c_str(), input.size())); + net::LookupStringInFixedSet(dafsa_, input)); }
diff --git a/chrome/browser/predictors/loading_predictor.cc b/chrome/browser/predictors/loading_predictor.cc index 46bf870b9..02ec770 100644 --- a/chrome/browser/predictors/loading_predictor.cc +++ b/chrome/browser/predictors/loading_predictor.cc
@@ -151,8 +151,7 @@ HintOrigin origin, bool preconnectable, std::optional<PreconnectPrediction> preconnect_prediction) { - if (shutdown_) - return true; + CHECK(!shutdown_); TRACE_EVENT("loading", "LoadingPredictor::PrepareForPageLoad"); @@ -290,14 +289,11 @@ shutdown_ = true; } -bool LoadingPredictor::OnNavigationStarted( - NavigationId navigation_id, - ukm::SourceId ukm_source_id, - const std::optional<url::Origin>& initiator_origin, - const GURL& main_frame_url, - base::TimeTicks creation_time) { - if (shutdown_) - return true; +void LoadingPredictor::OnNavigationStarted(NavigationId navigation_id, + ukm::SourceId ukm_source_id, + const GURL& main_frame_url, + base::TimeTicks creation_time) { + CHECK(!shutdown_); TRACE_EVENT("loading", "LoadingPredictor::OnNavigationStarted"); @@ -307,8 +303,6 @@ active_navigations_.emplace(navigation_id, NavigationInfo{main_frame_url, creation_time}); active_urls_to_navigations_[main_frame_url].insert(navigation_id); - return PrepareForPageLoad(initiator_origin, main_frame_url, - HintOrigin::NAVIGATION); } void LoadingPredictor::OnNavigationFinished(NavigationId navigation_id,
diff --git a/chrome/browser/predictors/loading_predictor.h b/chrome/browser/predictors/loading_predictor.h index e3394d4..20f7230 100644 --- a/chrome/browser/predictors/loading_predictor.h +++ b/chrome/browser/predictors/loading_predictor.h
@@ -92,13 +92,12 @@ // KeyedService: void Shutdown() override; + bool WasShutdown() { return shutdown_; } // OnNavigationStarted is invoked when navigation |navigation_id| with - // |main_frame_url| has started navigating. It returns whether any actions - // were taken, such as preconnecting to known resource hosts, at that time. - bool OnNavigationStarted(NavigationId navigation_id, + // |main_frame_url| has started navigating. + void OnNavigationStarted(NavigationId navigation_id, ukm::SourceId ukm_source_id, - const std::optional<url::Origin>& initiator_origin, const GURL& main_frame_url, base::TimeTicks creation_time); void OnNavigationFinished(NavigationId navigation_id,
diff --git a/chrome/browser/predictors/loading_predictor_tab_helper.cc b/chrome/browser/predictors/loading_predictor_tab_helper.cc index 3d59544..e18fbad 100644 --- a/chrome/browser/predictors/loading_predictor_tab_helper.cc +++ b/chrome/browser/predictors/loading_predictor_tab_helper.cc
@@ -357,8 +357,9 @@ DCHECK_CURRENTLY_ON(BrowserThread::UI); TRACE_EVENT("navigation", "LoadingPredictorTabHelper::DidStartNavigation"); - if (!predictor_) + if (!predictor_ || predictor_->WasShutdown()) { return; + } MaybeSetLCPPNavigationHint(*navigation_handle, *predictor_); @@ -369,44 +370,71 @@ return; } + const bool should_consult_optimization_guide = ShouldConsultOptimizationGuide( + navigation_handle->GetURL(), web_contents()); + PageData& page_data = PageData::CreateForNavigationHandle(*navigation_handle); page_data.predictor_ = predictor_; - page_data.has_local_preconnect_predictions_for_current_navigation_ = - predictor_->OnNavigationStarted( - page_data.navigation_id_, - ukm::ConvertToSourceId(navigation_handle->GetNavigationId(), - ukm::SourceIdType::NAVIGATION_ID), - navigation_handle->GetInitiatorOrigin(), navigation_handle->GetURL(), - navigation_handle->NavigationStart()); - if (page_data.has_local_preconnect_predictions_for_current_navigation_ && - !features::ShouldAlwaysRetrieveOptimizationGuidePredictions()) { + predictor_->OnNavigationStarted( + page_data.navigation_id_, + ukm::ConvertToSourceId(navigation_handle->GetNavigationId(), + ukm::SourceIdType::NAVIGATION_ID), + navigation_handle->GetURL(), navigation_handle->NavigationStart()); + + if (base::FeatureList::IsEnabled( + blink::features::kLCPPPrefetchSubresourceAsync)) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce( + &LoadingPredictorTabHelper::PrepareForPageLoad, + weak_ptr_factory_.GetWeakPtr(), base::WrapRefCounted(&page_data), + navigation_handle->GetInitiatorOrigin(), + navigation_handle->GetURL(), should_consult_optimization_guide)); + } else { + PrepareForPageLoad(base::WrapRefCounted(&page_data), + navigation_handle->GetInitiatorOrigin(), + navigation_handle->GetURL(), + should_consult_optimization_guide); + } +} + +void LoadingPredictorTabHelper::PrepareForPageLoad( + scoped_refptr<PageData> page_data, + const std::optional<url::Origin> initiator_origin, + const GURL main_frame_url, + bool should_consult_optimization_guide) { + TRACE_EVENT("navigation", "LoadingPredictorTabHelper::PrepareForPageLoad."); + is_prepare_for_pageload_called_for_testing_ = true; + if (!predictor_ || predictor_->WasShutdown()) { return; } + page_data->has_local_preconnect_predictions_for_current_navigation_ = + predictor_->PrepareForPageLoad(initiator_origin, main_frame_url, + HintOrigin::NAVIGATION); - if (!optimization_guide_decider_) - return; - - if (!ShouldConsultOptimizationGuide(navigation_handle->GetURL(), - web_contents())) { + if ((page_data->has_local_preconnect_predictions_for_current_navigation_ && + !features::ShouldAlwaysRetrieveOptimizationGuidePredictions()) || + !optimization_guide_decider_ || !should_consult_optimization_guide) { return; } TRACE_EVENT("navigation", - "LoadingPredictorTabHelper::DidStartNavigation." + "LoadingPredictorTabHelper::PrepareForPageLoad." "OptimizationGuidePrediction"); - - page_data.last_optimization_guide_prediction_ = OptimizationGuidePrediction(); - page_data.last_optimization_guide_prediction_->decision = + page_data->last_optimization_guide_prediction_ = + OptimizationGuidePrediction(); + page_data->last_optimization_guide_prediction_->decision = optimization_guide::OptimizationGuideDecision::kUnknown; optimization_guide_decider_->CanApplyOptimization( - navigation_handle->GetURL(), optimization_guide::proto::LOADING_PREDICTOR, + main_frame_url, optimization_guide::proto::LOADING_PREDICTOR, base::BindOnce( &LoadingPredictorTabHelper::OnOptimizationGuideDecision, - weak_ptr_factory_.GetWeakPtr(), base::WrapRefCounted(&page_data), - navigation_handle->GetInitiatorOrigin(), navigation_handle->GetURL(), - !page_data.has_local_preconnect_predictions_for_current_navigation_)); + weak_ptr_factory_.GetWeakPtr(), std::move(page_data), + initiator_origin, main_frame_url, + !page_data + ->has_local_preconnect_predictions_for_current_navigation_)); } void LoadingPredictorTabHelper::DidRedirectNavigation(
diff --git a/chrome/browser/predictors/loading_predictor_tab_helper.h b/chrome/browser/predictors/loading_predictor_tab_helper.h index dd0778d..7403980 100644 --- a/chrome/browser/predictors/loading_predictor_tab_helper.h +++ b/chrome/browser/predictors/loading_predictor_tab_helper.h
@@ -70,6 +70,10 @@ predictor_ = predictor; } + bool IsPrepareForPageloadCalledForTesting() const { + return is_prepare_for_pageload_called_for_testing_; + } + private: // The PageData stores the state needed for each page. It is primarily owned // by the DocumentPageDataHolder or NavigationPageDataHolder, depending on @@ -158,6 +162,16 @@ optimization_guide::OptimizationGuideDecision decision, const optimization_guide::OptimizationMetadata& metadata); + // Calls LoadingPredictor::PrepareForPageLoad doing prefetch and/or + // preconnect. This is called asynchronously after main resource fetching if + // kLCPPPrefetchSubresourceAsync is enabled. + void PrepareForPageLoad(scoped_refptr<PageData> page_data, + const std::optional<url::Origin> initiator_origin, + const GURL main_frame_url, + bool should_consult_optimization_guide); + + bool is_prepare_for_pageload_called_for_testing_ = false; + // Owned by profile. base::WeakPtr<LoadingPredictor> predictor_;
diff --git a/chrome/browser/predictors/loading_predictor_tab_helper_unittest.cc b/chrome/browser/predictors/loading_predictor_tab_helper_unittest.cc index 117a9b4..8a7bfdd 100644 --- a/chrome/browser/predictors/loading_predictor_tab_helper_unittest.cc +++ b/chrome/browser/predictors/loading_predictor_tab_helper_unittest.cc
@@ -8,6 +8,7 @@ #include "base/run_loop.h" #include "base/test/gmock_callback_support.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/run_until.h" #include "base/test/scoped_feature_list.h" #include "chrome/browser/optimization_guide/mock_optimization_guide_keyed_service.h" #include "chrome/browser/optimization_guide/optimization_guide_keyed_service.h" @@ -64,8 +65,16 @@ const LoadingPredictorConfig& config) : LoadingDataCollector(nullptr, nullptr, config) {} -class LoadingPredictorTabHelperTest : public ChromeRenderViewHostTestHarness { +class LoadingPredictorTabHelperTest : public ChromeRenderViewHostTestHarness, + public testing::WithParamInterface<bool> { public: + LoadingPredictorTabHelperTest() { + if (GetParam()) { + scoped_feature_list_.InitAndEnableFeature( + blink::features::kLCPPPrefetchSubresourceAsync); + } + } + void SetUp() override; void TearDown() override; @@ -83,6 +92,8 @@ mock_optimization_guide_keyed_service_; // Owned by |web_contents()|. raw_ptr<LoadingPredictorTabHelper, DanglingUntriaged> tab_helper_; + + base::test::ScopedFeatureList scoped_feature_list_; }; void LoadingPredictorTabHelperTest::SetUp() { @@ -159,18 +170,20 @@ // events dispatched by NavigationSimulator. navigation->SetKeepLoading(true); navigation->Start(); + EXPECT_TRUE(base::test::RunUntil( + [&]() { return tab_helper_->IsPrepareForPageloadCalledForTesting(); })); navigation->Commit(); } // Tests that a main frame navigation is correctly recorded by the // LoadingDataCollector. -TEST_F(LoadingPredictorTabHelperTest, MainFrameNavigation) { +TEST_P(LoadingPredictorTabHelperTest, MainFrameNavigation) { NavigateAndCommitInMainFrameAndVerifyMetrics("http://test.org"); } // Tests that an old and new navigation ids are correctly set if a navigation // has redirects. -TEST_F(LoadingPredictorTabHelperTest, MainFrameNavigationWithRedirects) { +TEST_P(LoadingPredictorTabHelperTest, MainFrameNavigationWithRedirects) { GURL main_frame_url("http://test.org"); auto navigation = content::NavigationSimulator::CreateRendererInitiated( main_frame_url, main_rfh()); @@ -197,7 +210,7 @@ } // Tests that a subframe navigation is not recorded. -TEST_F(LoadingPredictorTabHelperTest, SubframeNavigation) { +TEST_P(LoadingPredictorTabHelperTest, SubframeNavigation) { // We need to have a committed main frame navigation before navigating in sub // frames. NavigateAndCommitInMainFrameAndVerifyMetrics("http://test.org"); @@ -209,7 +222,7 @@ } // Tests that a failed navigation is correctly recorded. -TEST_F(LoadingPredictorTabHelperTest, MainFrameNavigationFailed) { +TEST_P(LoadingPredictorTabHelperTest, MainFrameNavigationFailed) { GURL url("http://test.org"); auto navigation = content::NavigationSimulator::CreateRendererInitiated(url, main_rfh()); @@ -234,7 +247,7 @@ } // Tests that a same document navigation is not recorded. -TEST_F(LoadingPredictorTabHelperTest, MainFrameNavigationSameDocument) { +TEST_P(LoadingPredictorTabHelperTest, MainFrameNavigationSameDocument) { NavigateAndCommitInMainFrameAndVerifyMetrics("http://test.org"); // Same document navigation shouldn't be recorded. @@ -245,7 +258,7 @@ // Tests that document on load completed is recorded with correct navigation // id. -TEST_F(LoadingPredictorTabHelperTest, DocumentOnLoadCompleted) { +TEST_P(LoadingPredictorTabHelperTest, DocumentOnLoadCompleted) { NavigateAndCommitInMainFrameAndVerifyMetrics("http://test.org"); // Adding subframe navigation to ensure that the committed main frame url will @@ -259,7 +272,7 @@ } // Tests that a resource load is correctly recorded. -TEST_F(LoadingPredictorTabHelperTest, ResourceLoadComplete) { +TEST_P(LoadingPredictorTabHelperTest, ResourceLoadComplete) { NavigateAndCommitInMainFrameAndVerifyMetrics("http://test.org"); auto resource_load_info = CreateResourceLoadInfo( @@ -271,7 +284,7 @@ } // Tests that a resource loaded in a subframe is not recorded. -TEST_F(LoadingPredictorTabHelperTest, ResourceLoadCompleteInSubFrame) { +TEST_P(LoadingPredictorTabHelperTest, ResourceLoadCompleteInSubFrame) { NavigateAndCommitInMainFrameAndVerifyMetrics("http://test.org"); auto* subframe = @@ -288,7 +301,7 @@ } // Tests that a resource load from the memory cache is correctly recorded. -TEST_F(LoadingPredictorTabHelperTest, LoadResourceFromMemoryCache) { +TEST_P(LoadingPredictorTabHelperTest, LoadResourceFromMemoryCache) { NavigateAndCommitInMainFrameAndVerifyMetrics("http://test.org"); auto resource_load_info = CreateResourceLoadInfo( @@ -303,6 +316,10 @@ network::mojom::RequestDestination::kScript); } +INSTANTIATE_TEST_SUITE_P(LCPPPrefetchSubresourceAsyncFlag, + LoadingPredictorTabHelperTest, + testing::Bool()); + class LoadingPredictorTabHelperOptimizationGuideDeciderTest : public LoadingPredictorTabHelperTest { public: @@ -328,7 +345,7 @@ // Tests that document on load completed is recorded with correct navigation // id and that optimization guide is not consulted when from same-origin. -TEST_F(LoadingPredictorTabHelperOptimizationGuideDeciderTest, +TEST_P(LoadingPredictorTabHelperOptimizationGuideDeciderTest, DocumentOnLoadCompletedOptimizationGuideSameOrigin) { NavigateAndCommitInMainFrameAndVerifyMetrics("http://test.org"); @@ -350,7 +367,7 @@ } // Tests that document on load completed is recorded. -TEST_F(LoadingPredictorTabHelperOptimizationGuideDeciderTest, +TEST_P(LoadingPredictorTabHelperOptimizationGuideDeciderTest, DocumentOnLoadCompletedOptimizationGuide) { base::HistogramTester histogram_tester; @@ -379,7 +396,7 @@ // Tests that page destruction is recorded with the correct navigation id and // optimization guide prediction. -TEST_F(LoadingPredictorTabHelperOptimizationGuideDeciderTest, +TEST_P(LoadingPredictorTabHelperOptimizationGuideDeciderTest, PageDestroyedOptimizationGuide) { base::HistogramTester histogram_tester; @@ -422,7 +439,7 @@ // Tests that predictions are recorded correctly when they come after the // navigation commits. -TEST_F(LoadingPredictorTabHelperOptimizationGuideDeciderTest, +TEST_P(LoadingPredictorTabHelperOptimizationGuideDeciderTest, PageDestroyedOptimizationGuidePredictionComesAfterCommit) { base::HistogramTester histogram_tester; @@ -472,7 +489,7 @@ // Tests that predictions are recorded correctly when they arrive after a // redirect. -TEST_F(LoadingPredictorTabHelperOptimizationGuideDeciderTest, +TEST_P(LoadingPredictorTabHelperOptimizationGuideDeciderTest, PageDestroyedOptimizationGuidePredictionArrivedAfterRedirect) { base::HistogramTester histogram_tester; @@ -541,7 +558,7 @@ // Tests that page destruction is recorded with correct navigation id and // optimization guide prediction when the prediction has not arrived. -TEST_F(LoadingPredictorTabHelperOptimizationGuideDeciderTest, +TEST_P(LoadingPredictorTabHelperOptimizationGuideDeciderTest, PageDestroyedOptimizationGuidePredictionHasNotArrived) { base::HistogramTester histogram_tester; @@ -566,7 +583,7 @@ // Tests that page destroyed is recorded with correct navigation id and // optimization guide prediction and does not crash if callback comes after // everything has been recorded. -TEST_F(LoadingPredictorTabHelperOptimizationGuideDeciderTest, +TEST_P(LoadingPredictorTabHelperOptimizationGuideDeciderTest, PageDestroyedOptimizationGuidePredictionComesAfterPageDestroyed) { base::HistogramTester histogram_tester; @@ -615,7 +632,7 @@ // Tests that page destruction is recorded with correct navigation and // optimization guide prediction with no prediction.. -TEST_F(LoadingPredictorTabHelperOptimizationGuideDeciderTest, +TEST_P(LoadingPredictorTabHelperOptimizationGuideDeciderTest, PageDestroyedOptimizationGuidePredictionArrivedNoPrediction) { base::HistogramTester histogram_tester; @@ -648,7 +665,7 @@ // Tests that page destruction is recorded with correct navigation id and // optimization guide prediction with no prediction.. -TEST_F( +TEST_P( LoadingPredictorTabHelperOptimizationGuideDeciderTest, PageDestroyedOptimizationGuidePredictionArrivedNoLoadingPredictorMetadata) { base::HistogramTester histogram_tester; @@ -683,6 +700,10 @@ RecordPageDestroyed(_, optimization_guide_prediction)); } +INSTANTIATE_TEST_SUITE_P(LCPPPrefetchSubresourceAsyncFlag, + LoadingPredictorTabHelperOptimizationGuideDeciderTest, + testing::Bool()); + class LoadingPredictorTabHelperOptimizationGuideDeciderWithPrefetchTest : public LoadingPredictorTabHelperOptimizationGuideDeciderTest { public: @@ -703,7 +724,7 @@ // Tests that page destruction is recorded with correct navigation id and // optimization guide prediction. -TEST_F(LoadingPredictorTabHelperOptimizationGuideDeciderWithPrefetchTest, +TEST_P(LoadingPredictorTabHelperOptimizationGuideDeciderWithPrefetchTest, PageDestroyedOptimizationGuide) { base::HistogramTester histogram_tester; @@ -757,6 +778,11 @@ EXPECT_CALL(*mock_collector_, RecordPageDestroyed(_, prediction)); } +INSTANTIATE_TEST_SUITE_P( + LCPPPrefetchSubresourceAsyncFlag, + LoadingPredictorTabHelperOptimizationGuideDeciderWithPrefetchTest, + testing::Bool()); + class TestLoadingDataCollector : public LoadingDataCollector { public: explicit TestLoadingDataCollector(const LoadingPredictorConfig& config); @@ -826,7 +852,7 @@ } // Tests that a resource load is correctly recorded with the correct priority. -TEST_F(LoadingPredictorTabHelperTestCollectorTest, ResourceLoadComplete) { +TEST_P(LoadingPredictorTabHelperTestCollectorTest, ResourceLoadComplete) { NavigateAndCommitInFrame("http://test.org", main_rfh()); // Set expected priority to HIGHEST and load a HIGHEST priority resource. @@ -846,6 +872,10 @@ EXPECT_EQ(2u, test_collector_->count_resource_loads_completed()); } +INSTANTIATE_TEST_SUITE_P(LCPPPrefetchSubresourceAsyncFlag, + LoadingPredictorTabHelperTestCollectorTest, + testing::Bool()); + class LoadingPredictorTabHelperTestCollectorFencedFramesTest : public LoadingPredictorTabHelperTestCollectorTest { public: @@ -859,7 +889,7 @@ base::test::ScopedFeatureList scoped_feature_list_; }; -TEST_F(LoadingPredictorTabHelperTestCollectorFencedFramesTest, +TEST_P(LoadingPredictorTabHelperTestCollectorFencedFramesTest, DoNotRecordResourceLoadComplete) { NavigateAndCommitInFrame("http://test.org", main_rfh()); content::RenderFrameHost* fenced_frame_root = @@ -888,4 +918,8 @@ EXPECT_EQ(1u, test_collector_->count_resource_loads_completed()); } +INSTANTIATE_TEST_SUITE_P(LCPPPrefetchSubresourceAsyncFlag, + LoadingPredictorTabHelperTestCollectorFencedFramesTest, + testing::Bool()); + } // namespace predictors
diff --git a/chrome/browser/predictors/loading_predictor_unittest.cc b/chrome/browser/predictors/loading_predictor_unittest.cc index 846ba4aa..2421b52 100644 --- a/chrome/browser/predictors/loading_predictor_unittest.cc +++ b/chrome/browser/predictors/loading_predictor_unittest.cc
@@ -183,16 +183,12 @@ TEST_F(LoadingPredictorTest, TestOnNavigationStarted) { // Should return true if there are predictions. - auto navigation_id = GetNextId(); - EXPECT_TRUE(predictor_->OnNavigationStarted( - navigation_id, ukm::SourceId(), /*initiator_origin=*/std::nullopt, - GURL(kUrl), base::TimeTicks::Now())); + EXPECT_TRUE(predictor_->PrepareForPageLoad( + /*initiator_origin=*/std::nullopt, GURL(kUrl), HintOrigin::NAVIGATION)); // Should return false since there are no predictions. - auto navigation_id2 = GetNextId(); - EXPECT_FALSE(predictor_->OnNavigationStarted( - navigation_id2, ukm::SourceId(), /*initiator_origin=*/std::nullopt, - GURL(kUrl3), base::TimeTicks::Now())); + EXPECT_FALSE(predictor_->PrepareForPageLoad( + /*initiator_origin=*/std::nullopt, GURL(kUrl3), HintOrigin::NAVIGATION)); } TEST_F(LoadingPredictorTest, TestMainFrameResponseCancelsHint) { @@ -216,9 +212,10 @@ auto navigation_id = GetNextId(); - predictor_->OnNavigationStarted(navigation_id, ukm::SourceId(), - /*initiator_origin=*/std::nullopt, url, + predictor_->OnNavigationStarted(navigation_id, ukm::SourceId(), url, base::TimeTicks::Now()); + predictor_->PrepareForPageLoad(/*initiator_origin=*/std::nullopt, url, + HintOrigin::EXTERNAL); EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end()); EXPECT_FALSE(active_hints.empty()); EXPECT_NE(active_urls_to_navigations.find(url), @@ -230,9 +227,10 @@ EXPECT_TRUE(active_urls_to_navigations.empty()); // With redirects. - predictor_->OnNavigationStarted(navigation_id, ukm::SourceId(), - /*initiator_origin=*/std::nullopt, url, + predictor_->OnNavigationStarted(navigation_id, ukm::SourceId(), url, base::TimeTicks::Now()); + predictor_->PrepareForPageLoad(/*initiator_origin=*/std::nullopt, url, + HintOrigin::EXTERNAL); EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end()); EXPECT_FALSE(active_hints.empty()); EXPECT_NE(active_urls_to_navigations.find(url), @@ -263,7 +261,6 @@ auto navigation_id = GetNextId(); predictor_->OnNavigationStarted(navigation_id, ukm::SourceId(), - /*initiator_origin=*/std::nullopt, GURL(url.spec()), base::TimeTicks::Now()); EXPECT_NE(active_navigations.find(navigation_id), active_navigations.end()); it = active_hints.find(url);
diff --git a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/PrivacyGuideFragment.java b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/PrivacyGuideFragment.java index 6ec70e5..80ffcbd 100644 --- a/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/PrivacyGuideFragment.java +++ b/chrome/browser/privacy_guide/android/java/src/org/chromium/chrome/browser/privacy_guide/PrivacyGuideFragment.java
@@ -163,9 +163,14 @@ } @Override + public void onStart() { + super.onStart(); + updateButtonVisibility(); + } + + @Override public void onResume() { super.onResume(); - updateButtonVisibility(); mHandleBackPressChangedSupplier.set(shouldHandleBackPress()); } @@ -312,4 +317,9 @@ public void setProfile(Profile profile) { mProfile = profile; } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/resources/ash/settings/OWNERS b/chrome/browser/resources/ash/settings/OWNERS index 6866620..c0978e5 100644 --- a/chrome/browser/resources/ash/settings/OWNERS +++ b/chrome/browser/resources/ash/settings/OWNERS
@@ -13,6 +13,7 @@ # user so that our GWSQ is prioritized instead. wesokuhara@google.com #{LAST_RESORT_SUGGESTION} xiaohuic@chromium.org #{LAST_RESORT_SUGGESTION} +moteva@google.com #{LAST_RESORT_SUGGESTION} # Subdir OWNERS can approve icon changes related to their subdir. per-file os_settings_icons.html=file://chrome/browser/resources/ash/settings/crostini_page/OWNERS
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/accessibility_common_loader.ts b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/accessibility_common_loader.ts index 0b661cb0..36e927b95 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/accessibility_common_loader.ts +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common/mv3/accessibility_common_loader.ts
@@ -5,7 +5,7 @@ import '/common/testing/test_import_manager.js'; import {Flags} from '/common/flags.js'; -import {InstanceChecker} from '/common/mv2/instance_checker.js'; +import {InstanceChecker} from '/common/mv3/instance_checker.js'; import {TestImportManager} from '/common/testing/test_import_manager.js'; import {Autoclick} from './autoclick/autoclick.js';
diff --git a/chrome/browser/resources/chromeos/accessibility/accessibility_common_manifest.json.jinja2 b/chrome/browser/resources/chromeos/accessibility/accessibility_common_manifest.json.jinja2 index 44a86f5..37b946a 100644 --- a/chrome/browser/resources/chromeos/accessibility/accessibility_common_manifest.json.jinja2 +++ b/chrome/browser/resources/chromeos/accessibility/accessibility_common_manifest.json.jinja2
@@ -6,7 +6,7 @@ "manifest_version": 3, "minimum_chrome_version": "93", "background": { - "service_worker": "accessibility_common/mv3/accessibility_common_loader.ts", + "service_worker": "accessibility_common/mv3/accessibility_common_loader.js", "type": "module" }, "content_security_policy": {
diff --git a/chrome/browser/resources/omnibox/omnibox_output_column_widths.css b/chrome/browser/resources/omnibox/omnibox_output_column_widths.css index beff9fa..49de272 100644 --- a/chrome/browser/resources/omnibox/omnibox_output_column_widths.css +++ b/chrome/browser/resources/omnibox/omnibox_output_column_widths.css
@@ -9,9 +9,11 @@ .header-relevance { width: 100%; } + .header-image-and-icon { width: 85px; } + .header-contents-and-description { width: 480%; }
diff --git a/chrome/browser/resources/side_panel/customize_chrome/app.html.ts b/chrome/browser/resources/side_panel/customize_chrome/app.html.ts index 6504139..b3019bb 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/app.html.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/app.html.ts
@@ -33,14 +33,14 @@ </sp-heading> <cr-icon icon="cr:chevron-right" slot="suffix-icon"></cr-icon> </cr-button> - ${this.isSourceTabFirstPartyNtp_() ? html`<hr class="sp-cards-separator"> + ${this.isSourceTabFirstPartyNtp_ ? html`<hr class="sp-cards-separator"> <div id="shortcuts" class="section sp-card"> <sp-heading hide-back-button> <h2 slot="heading">$i18n{shortcutsHeader}</h2> </sp-heading> <customize-chrome-shortcuts></customize-chrome-shortcuts> </div>`: ''} - ${(this.modulesEnabled_ && this.isSourceTabFirstPartyNtp_()) ? html` + ${(this.modulesEnabled_ && this.isSourceTabFirstPartyNtp_) ? html` <hr class="sp-cards-separator"> <div id="modules" class="section sp-card"> <sp-heading hide-back-button> @@ -77,7 +77,7 @@ </div> </div> ` : ''} - ${(this.footerEnabled_ && this.isSourceTabExtension_()) ? html` + ${this.footerEnabled_ ? html` <hr class="sp-cards-separator"> <div id="footer" class="section sp-card"> <sp-heading hide-back-button>
diff --git a/chrome/browser/resources/side_panel/customize_chrome/app.ts b/chrome/browser/resources/side_panel/customize_chrome/app.ts index 4fbb739a..ea99b2d 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/app.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/app.ts
@@ -29,7 +29,7 @@ import type {CategoriesElement} from './categories.js'; import {CustomizeChromeImpression, recordCustomizeChromeImpression} from './common.js'; import type {BackgroundCollection, CustomizeChromePageHandlerInterface} from './customize_chrome.mojom-webui.js'; -import {ChromeWebStoreCategory, ChromeWebStoreCollection, CustomizeChromeSection, NewTabPageType} from './customize_chrome.mojom-webui.js'; +import {ChromeWebStoreCategory, ChromeWebStoreCollection, CustomizeChromeSection} from './customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from './customize_chrome_api_proxy.js'; import type {ThemesElement} from './themes.js'; @@ -82,7 +82,7 @@ extensionsCardEnabled_: {type: Boolean}, footerEnabled_: {type: Boolean}, wallpaperSearchEnabled_: {type: Boolean}, - newTabPageType_: {type: NewTabPageType}, + isSourceTabFirstPartyNtp_: {type: Boolean}, showEditTheme_: {type: Boolean}, }; } @@ -106,8 +106,7 @@ loadTimeData.getBoolean('footerEnabled'); protected accessor wallpaperSearchEnabled_: boolean = loadTimeData.getBoolean('wallpaperSearchEnabled'); - protected accessor newTabPageType_: NewTabPageType = - NewTabPageType.kFirstPartyWebUI; + protected accessor isSourceTabFirstPartyNtp_: boolean = true; protected accessor showEditTheme_: boolean = true; private scrollToSectionListenerId_: number|null = null; private attachedTabStateUpdatedId_: number|null = null; @@ -143,16 +142,17 @@ this.attachedTabStateUpdatedId_ = CustomizeChromeApiProxy.getInstance() .callbackRouter.attachedTabStateUpdated.addListener( - (newTabPageType: NewTabPageType) => { - if (this.newTabPageType_ === newTabPageType) { + (isSourceTabFirstPartyNtp: boolean) => { + if (this.isSourceTabFirstPartyNtp_ === + isSourceTabFirstPartyNtp) { return; } - this.newTabPageType_ = newTabPageType; + this.isSourceTabFirstPartyNtp_ = isSourceTabFirstPartyNtp; // Since some pages aren't supported in non first party mode, // change the section back to the overview. - if (!this.isSourceTabFirstPartyNtp_() && + if (!this.isSourceTabFirstPartyNtp_ && !this.pageSupportedOnNonFirstPartyNtps()) { this.page_ = CustomizeChromePage.OVERVIEW; } @@ -207,14 +207,6 @@ this.setThemeEditableId_); } - protected isSourceTabFirstPartyNtp_(): boolean { - return this.newTabPageType_ === NewTabPageType.kFirstPartyWebUI; - } - - protected isSourceTabExtension_(): boolean { - return this.newTabPageType_ === NewTabPageType.kExtension; - } - protected async onBackClick_() { switch (this.page_) { case CustomizeChromePage.CATEGORIES:
diff --git a/chrome/browser/screen_ai/optical_character_recognizer_browsertest.cc b/chrome/browser/screen_ai/optical_character_recognizer_browsertest.cc index 3991abe05..7b0bf949 100644 --- a/chrome/browser/screen_ai/optical_character_recognizer_browsertest.cc +++ b/chrome/browser/screen_ai/optical_character_recognizer_browsertest.cc
@@ -38,6 +38,10 @@ namespace { +// LINT.IfChange(kServiceIdleCheckingDelay) +constexpr base::TimeDelta kServiceIdleCheckingDelay = base::Seconds(3); +// LINT.ThenChange(//services/screen_ai/screen_ai_service_impl.cc:kIdleCheckingDelay) + using ::testing::ElementsAre; using ::testing::Field; using ::testing::IsEmpty; @@ -88,14 +92,13 @@ std::move(callback).Run(); return; } - router->ShutDownIfNoClientsForTesting(); // Wait more... base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask( FROM_HERE, base::BindOnce(&WaitForDisconnecting, router, std::move(callback), remaining_tries - 1), - base::Milliseconds(200)); + kServiceIdleCheckingDelay); } // bool: PDF OCR service enabled. @@ -497,9 +500,9 @@ ASSERT_TRUE(router->IsProcessRunningForTesting()); } - // Trigger service shut down and wait for disconnecting. + // Wait for shut down due to being idle. base::test::TestFuture<void> future; - WaitForDisconnecting(router, future.GetCallback(), /*remaining_tries=*/10); + WaitForDisconnecting(router, future.GetCallback(), /*remaining_tries=*/2); ASSERT_TRUE(future.Wait()); ASSERT_FALSE(router->IsProcessRunningForTesting());
diff --git a/chrome/browser/screen_ai/screen_ai_service_router.h b/chrome/browser/screen_ai/screen_ai_service_router.h index 04f7ab1..90dd422 100644 --- a/chrome/browser/screen_ai/screen_ai_service_router.h +++ b/chrome/browser/screen_ai/screen_ai_service_router.h
@@ -69,12 +69,6 @@ // Returns true if sandboxed process is running. bool IsProcessRunningForTesting(); - void ShutDownIfNoClientsForTesting() { - if (screen_ai_service_factory_.is_bound()) { - screen_ai_service_factory_->ShutDownIfNoClients(); - } - } - private: friend class ScreenAIServiceRouterFactory; friend class ScreenAIServiceShutdownHandlerTest;
diff --git a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/TestStandaloneFragment.java b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/TestStandaloneFragment.java index 13effc6c..2a8574b 100644 --- a/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/TestStandaloneFragment.java +++ b/chrome/browser/settings/android/java/src/org/chromium/chrome/browser/settings/TestStandaloneFragment.java
@@ -53,4 +53,9 @@ public ObservableSupplierImpl<Boolean> getHandleBackPressChangedSupplier() { return mBackPressStateSupplier; } + + @Override + public @AnimationType int getAnimationType() { + return AnimationType.PROPERTY; + } }
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index c9201e6..bcb98c7 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -2305,6 +2305,10 @@ desc="Text for the dialog showing a list of tabs for capture to ask user if tab audio should be shared."> Also share tab audio </message> + <message name="IDS_MEDIA_CAPTURE_PICKER_DIALOG_WINDOW_OR_SCREEN_TEXT" + desc="Text for the dialog showing a list of tabs for capture to ask user whether to share a window or screen instead of a tab."> + Share window or screen instead + </message> </if> <!-- Download open dialog -->
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MEDIA_CAPTURE_PICKER_DIALOG_WINDOW_OR_SCREEN_TEXT.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MEDIA_CAPTURE_PICKER_DIALOG_WINDOW_OR_SCREEN_TEXT.png.sha1 new file mode 100644 index 0000000..8397a9e --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_MEDIA_CAPTURE_PICKER_DIALOG_WINDOW_OR_SCREEN_TEXT.png.sha1
@@ -0,0 +1 @@ +fd9be039a93799c2ba95db39bc3fe69ee77a76cf \ No newline at end of file
diff --git a/chrome/browser/ui/android/toolbar/BUILD.gn b/chrome/browser/ui/android/toolbar/BUILD.gn index 2bfb4248..0ef0e9d 100644 --- a/chrome/browser/ui/android/toolbar/BUILD.gn +++ b/chrome/browser/ui/android/toolbar/BUILD.gn
@@ -60,6 +60,7 @@ "java/src/org/chromium/chrome/browser/toolbar/bottom/BottomControlsViewBinder.java", "java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewResourceFrameLayout.java", "java/src/org/chromium/chrome/browser/toolbar/bottom/ScrollingBottomViewSceneLayer.java", + "java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManager.java", "java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButton.java", "java/src/org/chromium/chrome/browser/toolbar/home_button/HomeButtonCoordinator.java", "java/src/org/chromium/chrome/browser/toolbar/load_progress/LoadProgressCoordinator.java", @@ -127,6 +128,7 @@ deps = [ ":java_resources", "//base:base_java", + "//base:service_loader_java", "//build/android:build_java", "//cc:cc_java", "//chrome/android/features/tab_ui/public:java", @@ -316,6 +318,7 @@ "java/res/layout/address_bar_preference.xml", "java/res/layout/bottom_control_container.xml", "java/res/layout/control_container.xml", + "java/res/layout/extension_toolbar_container.xml", "java/res/layout/menu_button.xml", "java/res/layout/navigation_popup_item.xml", "java/res/layout/optional_button_layout.xml",
diff --git a/chrome/browser/ui/android/toolbar/java/res/layout/extension_toolbar_container.xml b/chrome/browser/ui/android/toolbar/java/res/layout/extension_toolbar_container.xml new file mode 100644 index 0000000..7a7aea82 --- /dev/null +++ b/chrome/browser/ui/android/toolbar/java/res/layout/extension_toolbar_container.xml
@@ -0,0 +1,12 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2025 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<!-- TODO(crbug.com/385984462): Replace this with a real implementation. --> +<FrameLayout + xmlns:android="http://schemas.android.com/apk/res/android" + android:layout_width="wrap_content" + android:layout_height="match_parent" />
diff --git a/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_tablet.xml b/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_tablet.xml index 04125b9..633a77eae 100644 --- a/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_tablet.xml +++ b/chrome/browser/ui/android/toolbar/java/res/layout/toolbar_tablet.xml
@@ -98,6 +98,13 @@ app:menuMaxWidth="@dimen/tab_switcher_menu_width" app:menuVerticalOverlapAnchor="false" /> + <ViewStub + android:id="@+id/extension_toolbar_container_stub" + android:inflatedId="@+id/extension_toolbar_container" + android:layout="@layout/extension_toolbar_container" + android:layout_width="wrap_content" + android:layout_height="match_parent" /> + <include layout="@layout/menu_button"/> </LinearLayout> </org.chromium.chrome.browser.toolbar.top.ToolbarTablet>
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManager.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManager.java new file mode 100644 index 0000000..5b4915a --- /dev/null +++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/extensions/ExtensionToolbarManager.java
@@ -0,0 +1,43 @@ +// Copyright 2025 The Chromium Authors +// 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.toolbar.extensions; + +import android.content.Context; +import android.view.ViewStub; + +import org.chromium.base.ServiceLoaderUtil; +import org.chromium.base.lifetime.Destroyable; +import org.chromium.base.supplier.ObservableSupplier; +import org.chromium.build.annotations.NullMarked; +import org.chromium.build.annotations.Nullable; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.tab.Tab; + +/** Provides extension-related buttons for {@link ToolbarManager}. */ +@NullMarked +public interface ExtensionToolbarManager extends Destroyable { + /** Initializes the manager. */ + public void initialize( + Context context, + ViewStub extensionToolbarStub, + ObservableSupplier<Profile> profileSupplier, + ObservableSupplier<Tab> currentTabSupplier); + + /** Instantiates the implementation of {@link ExtensionToolbarManager} if it is available. */ + @Nullable + public static ExtensionToolbarManager maybeCreate( + Context context, + ViewStub extensionToolbarStub, + ObservableSupplier<Profile> profileSupplier, + ObservableSupplier<Tab> currentTabSupplier) { + ExtensionToolbarManager manager = + ServiceLoaderUtil.maybeCreate(ExtensionToolbarManager.class); + if (manager == null) { + return null; + } + manager.initialize(context, extensionToolbarStub, profileSupplier, currentTabSupplier); + return manager; + } +}
diff --git a/chrome/browser/ui/browser_window_state.cc b/chrome/browser/ui/browser_window_state.cc index ce77dbe..074dc56b 100644 --- a/chrome/browser/ui/browser_window_state.cc +++ b/chrome/browser/ui/browser_window_state.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "chrome/browser/ui/browser_window_state.h"
diff --git a/chrome/browser/ui/certificate_dialogs.cc b/chrome/browser/ui/certificate_dialogs.cc index 691bda4..9b418d2 100644 --- a/chrome/browser/ui/certificate_dialogs.cc +++ b/chrome/browser/ui/certificate_dialogs.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "chrome/browser/ui/certificate_dialogs.h"
diff --git a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc index 30676b0..624d05fc 100644 --- a/chrome/browser/ui/content_settings/content_setting_bubble_model.cc +++ b/chrome/browser/ui/content_settings/content_setting_bubble_model.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "chrome/browser/ui/content_settings/content_setting_bubble_model.h"
diff --git a/chrome/browser/ui/content_settings/content_setting_image_model_states.cc b/chrome/browser/ui/content_settings/content_setting_image_model_states.cc index 9c0a64f..443a2ea 100644 --- a/chrome/browser/ui/content_settings/content_setting_image_model_states.cc +++ b/chrome/browser/ui/content_settings/content_setting_image_model_states.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "chrome/browser/ui/content_settings/content_setting_image_model_states.h"
diff --git a/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc b/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc index 078ac7b..7c292b9 100644 --- a/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc +++ b/chrome/browser/ui/lens/lens_overlay_untrusted_ui.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "chrome/browser/ui/lens/lens_overlay_untrusted_ui.h"
diff --git a/chrome/browser/ui/lens/lens_side_panel_untrusted_ui.cc b/chrome/browser/ui/lens/lens_side_panel_untrusted_ui.cc index 6323702..9bb7b6c1 100644 --- a/chrome/browser/ui/lens/lens_side_panel_untrusted_ui.cc +++ b/chrome/browser/ui/lens/lens_side_panel_untrusted_ui.cc
@@ -4,10 +4,6 @@ #include "chrome/browser/ui/lens/lens_side_panel_untrusted_ui.h" -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "base/strings/strcat.h" #include "chrome/browser/profiles/profile.h"
diff --git a/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc b/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc index 591ec115..43a2a5e 100644 --- a/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc +++ b/chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "chrome/browser/ui/tab_contents/chrome_web_contents_view_handle_drop.h"
diff --git a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc index dfa86b4..9214c67 100644 --- a/chrome/browser/ui/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/ui/tabs/tab_strip_model_unittest.cc
@@ -1,11 +1,6 @@ // Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "ui/base/models/list_selection_model.h" -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "chrome/browser/ui/tabs/tab_strip_model.h" @@ -68,6 +63,7 @@ #include "content/public/test/web_contents_tester.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkColor.h" +#include "ui/base/models/list_selection_model.h" using content::WebContents;
diff --git a/chrome/browser/ui/task_manager/task_manager_table_model.cc b/chrome/browser/ui/task_manager/task_manager_table_model.cc index 311207e..d8caa1da 100644 --- a/chrome/browser/ui/task_manager/task_manager_table_model.cc +++ b/chrome/browser/ui/task_manager/task_manager_table_model.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "chrome/browser/ui/task_manager/task_manager_table_model.h"
diff --git a/chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.cc b/chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.cc index f4e590f..2d99db4 100644 --- a/chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.cc +++ b/chrome/browser/ui/views/data_sharing/collaboration_controller_delegate_desktop.cc
@@ -390,7 +390,8 @@ ShowSignInAndSyncUi(profile); break; case collaboration::SyncStatus::kSyncWithoutTabGroup: - chrome::ShowSettingsSubPage(browser_, chrome::kSyncSetupSubPage); + chrome::ShowSettingsSubPage(browser_, + chrome::kSyncSetupAdvancedSubPage); break; case collaboration::SyncStatus::kSyncEnabled: NOTREACHED();
diff --git a/chrome/browser/ui/views/omnibox/omnibox_popup_view_views_browsertest.cc b/chrome/browser/ui/views/omnibox/omnibox_popup_view_views_browsertest.cc index ea9f3b2..c994f1d 100644 --- a/chrome/browser/ui/views/omnibox/omnibox_popup_view_views_browsertest.cc +++ b/chrome/browser/ui/views/omnibox/omnibox_popup_view_views_browsertest.cc
@@ -30,6 +30,7 @@ #include "chrome/test/base/search_test_utils.h" #include "chrome/test/base/ui_test_utils.h" #include "components/omnibox/browser/actions/tab_switch_action.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_result.h" #include "components/omnibox/browser/fake_autocomplete_provider.h" #include "components/omnibox/browser/omnibox_field_trial.h" @@ -646,7 +647,8 @@ ax::mojom::IntAttribute::kPopupForId)); // Check accessibility of list box while it's closed. - controller()->autocomplete_controller()->Stop(true); + controller()->autocomplete_controller()->Stop( + AutocompleteStopReason::kClobbered); popup_view()->UpdatePopupAppearance(); popup_node_data_while_open = ui::AXNodeData(); popup_view()->GetViewAccessibility().GetAccessibleNodeData( @@ -892,7 +894,8 @@ // Check accessibility when popup is closed. ax_node_data_omnibox = ui::AXNodeData(); - controller()->autocomplete_controller()->Stop(true); + controller()->autocomplete_controller()->Stop( + AutocompleteStopReason::kClobbered); omnibox_view()->GetViewAccessibility().GetAccessibleNodeData( &ax_node_data_omnibox); EXPECT_FALSE(popup_view()->IsOpen()); @@ -924,7 +927,8 @@ // Check accessibility when popup is closed. ax_node_data_omnibox = ui::AXNodeData(); - controller()->autocomplete_controller()->Stop(true); + controller()->autocomplete_controller()->Stop( + AutocompleteStopReason::kClobbered); omnibox_view()->GetViewAccessibility().GetAccessibleNodeData( &ax_node_data_omnibox); EXPECT_FALSE(popup_view()->IsOpen());
diff --git a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.cc b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.cc index d2d2759..5075ce8 100644 --- a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.cc +++ b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.cc
@@ -15,7 +15,6 @@ #include "extensions/browser/disable_reason.h" #include "extensions/browser/extension_registrar.h" #include "extensions/browser/extension_system.h" -#include "extensions/common/constants.h" #include "extensions/common/extension.h" namespace customize_chrome { @@ -56,19 +55,4 @@ {extensions::disable_reason::DISABLE_USER_ACTION}); } -bool IsExtensionNtp(const GURL& url, Profile* profile) { - if (!url.SchemeIs(extensions::kExtensionScheme)) { - return false; - } - - const extensions::Extension* extension_managing_ntp = - extensions::GetExtensionOverridingNewTabPage(profile); - - if (!extension_managing_ntp) { - return false; - } - - return extension_managing_ntp->id() == url.host(); -} - } // namespace customize_chrome
diff --git a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h index 2dcdde48..fdb5725 100644 --- a/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h +++ b/chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h
@@ -5,9 +5,6 @@ #ifndef CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_CUSTOMIZE_CHROME_CUSTOMIZE_CHROME_UTILS_H_ #define CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_CUSTOMIZE_CHROME_CUSTOMIZE_CHROME_UTILS_H_ -#include "chrome/browser/profiles/profile.h" -#include "url/gurl.h" - namespace content { class BrowserContext; } @@ -22,9 +19,6 @@ void MaybeDisableExtensionOverridingNtp( content::BrowserContext* browser_context); -// Returns whether `url` belongs to an extension NTP. -bool IsExtensionNtp(const GURL& url, Profile* profile); - } // namespace customize_chrome #endif // CHROME_BROWSER_UI_VIEWS_SIDE_PANEL_CUSTOMIZE_CHROME_CUSTOMIZE_CHROME_UTILS_H_
diff --git a/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.cc b/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.cc index d10e30d9..5254f69b 100644 --- a/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.cc +++ b/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.cc
@@ -15,7 +15,6 @@ #include "chrome/browser/ui/browser_window/public/browser_window_interface.h" #include "chrome/browser/ui/tabs/public/tab_features.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" -#include "chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h" #include "chrome/browser/ui/views/side_panel/side_panel_coordinator.h" #include "chrome/browser/ui/views/side_panel/side_panel_web_ui_view.h" #include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h" @@ -98,11 +97,26 @@ } bool SidePanelControllerViews::ShouldEnableEditTheme(const GURL& url) const { - Profile* const profile = - Profile::FromBrowserContext(tab_->GetContents()->GetBrowserContext()); return NewTabPageUI::IsNewTabPageOrigin(url) || (base::FeatureList::IsEnabled(ntp_features::kNtpFooter) && - customize_chrome::IsExtensionNtp(url, profile)); + IsExtensionNtp(url)); +} + +bool SidePanelControllerViews::IsExtensionNtp(const GURL& url) const { + if (!url.SchemeIs(extensions::kExtensionScheme)) { + return false; + } + + Profile* const profile = + Profile::FromBrowserContext(tab_->GetContents()->GetBrowserContext()); + const extensions::Extension* extension_managing_ntp = + extensions::GetExtensionOverridingNewTabPage(profile); + + if (!extension_managing_ntp) { + return false; + } + + return extension_managing_ntp->id() == url.host(); } void SidePanelControllerViews::DidFinishNavigation( @@ -120,7 +134,8 @@ if (CanShowOnURL(url)) { CreateAndRegisterEntry(); if (customize_chrome_ui_) { - customize_chrome_ui_->AttachedTabStateUpdated(url); + customize_chrome_ui_->AttachedTabStateUpdated( + NewTabPageUI::IsNewTabPageOrigin(url)); customize_chrome_ui_->UpdateThemeEditable(ShouldEnableEditTheme(url)); } } else { @@ -226,7 +241,8 @@ entry = tab_->GetContents()->GetController().GetVisibleEntry(); } const GURL& url = entry->GetURL(); - customize_chrome_ui_->AttachedTabStateUpdated(url); + customize_chrome_ui_->AttachedTabStateUpdated( + NewTabPageUI::IsNewTabPageOrigin(url)); customize_chrome_ui_->UpdateThemeEditable(ShouldEnableEditTheme(url)); return customize_chrome_web_view;
diff --git a/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.h b/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.h index 9842ad05..7ec206b1 100644 --- a/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.h +++ b/chrome/browser/ui/views/side_panel/customize_chrome/side_panel_controller_views.h
@@ -66,6 +66,9 @@ // Returns true for 1P NTP or extension NTP, otherwise returns false. bool ShouldEnableEditTheme(const GURL& url) const; + // Helper function to check if the URL belongs to an extension NTP. + bool IsExtensionNtp(const GURL& url) const; + // Generates the view for the SidePanel contents. This is the WebUI for the // SidePanel. Used by the SidepanelRegistry to create the view. std::unique_ptr<views::View> CreateCustomizeChromeWebView(
diff --git a/chrome/browser/ui/webui/cr_components/history/history_util.cc b/chrome/browser/ui/webui/cr_components/history/history_util.cc index 17ad4a9..801d755 100644 --- a/chrome/browser/ui/webui/cr_components/history/history_util.cc +++ b/chrome/browser/ui/webui/cr_components/history/history_util.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "chrome/browser/ui/webui/cr_components/history/history_util.h"
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom index 8996d03..e23bca0 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom
@@ -111,17 +111,6 @@ kShopping, }; -// Types of New Tabs that CustomizeChromePage can attach to. -enum NewTabPageType { - kFirstPartyWebUI, - kThirdPartyWebUI, - kThirdPartyRemote, - kExtension, - kIncognito, - kGuestMode, - kNone, -}; - // Used by the WebUI page to bootstrap bidirectional communication. interface CustomizeChromePageHandlerFactory { // The WebUI calls this method when the page is first initialized. @@ -237,7 +226,7 @@ // |CustomizeChromePageHandler.UpdateScrollToSection()|. ScrollToSection(CustomizeChromeSection section); // Sets Information about the tab that is attached to the CustomizeChromePage. - AttachedTabStateUpdated(NewTabPageType ntp_type); + AttachedTabStateUpdated(bool is_source_tab_first_party_ntp); // Sets the name of the system that manages the new tab page if there is one. // If not, empty string should be provided. NtpManagedByNameUpdated(string ntp_managed_by_name);
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_interactive_uitest.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_interactive_uitest.cc index fa4acd6..13bc5ed 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_interactive_uitest.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_interactive_uitest.cc
@@ -5,7 +5,6 @@ #include "base/test/scoped_feature_list.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" -#include "chrome/browser/extensions/install_verifier.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_commands.h" #include "chrome/browser/ui/browser_element_identifiers.h" @@ -68,12 +67,12 @@ extensions::ChromeTestExtensionLoader extension_loader(profile); extension_loader.set_ignore_manifest_warnings(true); - const extensions::Extension* extension = - extension_loader.LoadExtension(extension_dir.Pack()).get(); - ASSERT_TRUE(extension); + // TODO(temao) Not blocking the test, but note that LoadExtension() + // occasionally returns null. + extension_loader.LoadExtension(extension_dir.Pack()).get(); } - void OpenNewTabPage() { + void OpenExtensionNewTabPage() { chrome::NewTab(browser()); content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); @@ -85,7 +84,6 @@ protected: base::test::ScopedFeatureList scoped_feature_list_; - extensions::ScopedInstallVerifierBypassForTest install_verifier_bypass_; }; } // namespace @@ -100,7 +98,8 @@ InstallExtension(browser()->profile()); RunTestSequence( // 2. Open extension new tab page. - Do(base::BindLambdaForTesting([&, this]() { OpenNewTabPage(); })), + Do(base::BindLambdaForTesting( + [&, this]() { OpenExtensionNewTabPage(); })), // 3. Open customize chrome side panel. OpenCustomizeChromeSidePanel(kLocalCustomizeChromeElementId), // 4. Check edit theme is enabled in customize chrome side panel. @@ -109,38 +108,3 @@ WaitForElementToRender(kLocalCustomizeChromeElementId, kEditThemeButton))); } - -IN_PROC_BROWSER_TEST_F(CustomizeChromeInteractiveTest, - ShowsFooterSectionForExtensionNtp) { - DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kLocalCustomizeChromeElementId); - const DeepQuery kFooterSection = {"customize-chrome-app", "#footer", - "customize-chrome-footer", - "#showToggleContainer"}; - // 1. Load extension that overrides NTP. - InstallExtension(browser()->profile()); - RunTestSequence( - // 2. Open extension new tab page. - Do(base::BindLambdaForTesting([&, this]() { OpenNewTabPage(); })), - // 3. Open customize chrome side panel. - OpenCustomizeChromeSidePanel(kLocalCustomizeChromeElementId), - // 4. Check that the footer section exists. - Steps( - WaitForElementExists(kLocalCustomizeChromeElementId, kFooterSection), - WaitForElementToRender(kLocalCustomizeChromeElementId, - kFooterSection))); -} - -IN_PROC_BROWSER_TEST_F(CustomizeChromeInteractiveTest, - FooterSectionNotShownForNonExtensionNtp) { - DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kLocalCustomizeChromeElementId); - const DeepQuery kFooterSection = {"customize-chrome-app", "#footer", - "customize-chrome-footer", - "#showToggleContainer"}; - RunTestSequence( - // 1. Open non-extension new tab page. - Do(base::BindLambdaForTesting([&, this]() { OpenNewTabPage(); })), - // 2. Open customize chrome side panel. - OpenCustomizeChromeSidePanel(kLocalCustomizeChromeElementId), - // 3. Check that the footer section does not exist. - EnsureNotPresent(kLocalCustomizeChromeElementId, kFooterSection)); -}
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc index 981d88d2..01fcf2f3 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.cc
@@ -29,10 +29,7 @@ #include "chrome/browser/ui/color/chrome_color_id.h" #include "chrome/browser/ui/search/ntp_user_data_types.h" #include "chrome/browser/ui/views/side_panel/customize_chrome/customize_chrome_utils.h" -#include "chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.h" #include "chrome/browser/ui/webui/new_tab_page/ntp_pref_names.h" -#include "chrome/browser/ui/webui/new_tab_page_third_party/new_tab_page_third_party_ui.h" -#include "chrome/browser/ui/webui/ntp/new_tab_ui.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_section.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" @@ -186,9 +183,10 @@ page_->ScrollToSection(mojo_section); } -void CustomizeChromePageHandler::AttachedTabStateUpdated(const GURL& url) { - last_source_url_ = url; - page_->AttachedTabStateUpdated(GetNewTabPageType(url)); +void CustomizeChromePageHandler::AttachedTabStateUpdated( + bool is_source_tab_first_party_ntp) { + last_is_source_tab_first_party_ntp_ = is_source_tab_first_party_ntp; + page_->AttachedTabStateUpdated(is_source_tab_first_party_ntp); } bool CustomizeChromePageHandler::IsNtpManagedByThirdPartySearchEngine() const { @@ -541,7 +539,7 @@ } void CustomizeChromePageHandler::UpdateAttachedTabState() { - AttachedTabStateUpdated(last_source_url_); + AttachedTabStateUpdated(last_is_source_tab_first_party_ntp_); } void CustomizeChromePageHandler::UpdateNtpManagedByName() { @@ -728,22 +726,3 @@ LogEvent(NTP_BACKGROUND_UPLOAD_CANCEL); std::move(choose_local_custom_background_callback_).Run(false); } - -side_panel::mojom::NewTabPageType CustomizeChromePageHandler::GetNewTabPageType( - const GURL& url) { - if (NewTabPageUI::IsNewTabPageOrigin(url)) { - return side_panel::mojom::NewTabPageType::kFirstPartyWebUI; - } else if (customize_chrome::IsExtensionNtp(url, profile_)) { - return side_panel::mojom::NewTabPageType::kExtension; - } else if (NewTabPageThirdPartyUI::IsNewTabPageOrigin(url)) { - return side_panel::mojom::NewTabPageType::kThirdPartyWebUI; - } else if (IsNtpManagedByThirdPartySearchEngine()) { - return side_panel::mojom::NewTabPageType::kThirdPartyRemote; - } else if (NewTabUI::IsNewTab(url)) { - return profile_->IsGuestSession() - ? side_panel::mojom::NewTabPageType::kGuestMode - : side_panel::mojom::NewTabPageType::kIncognito; - } - - return side_panel::mojom::NewTabPageType::kNone; -}
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h index 460c8dd..a128141 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler.h
@@ -21,7 +21,6 @@ #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome.mojom.h" #include "chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_section.h" #include "chrome/common/search/ntp_logging_events.h" -#include "chrome/common/webui_url_constants.h" #include "components/prefs/pref_change_registrar.h" #include "components/search_engines/template_url_service_observer.h" #include "components/themes/ntp_background_service.h" @@ -91,7 +90,7 @@ void ScrollToSection(CustomizeChromeSection section); // Passes AttachedTabStateUpdated calls to the CustomizeChromePage. - void AttachedTabStateUpdated(const GURL& url); + void AttachedTabStateUpdated(bool is_source_tab_first_party_ntp); // Helper method to determine if the search engine is overriding the first // party NTP. @@ -146,9 +145,6 @@ std::u16string GetManagingThirdPartyName() const; - // Returns the type of New Tab Page the SidePanel is attached to. - side_panel::mojom::NewTabPageType GetNewTabPageType(const GURL& url); - // ui::NativeThemeObserver: void OnNativeThemeUpdated(ui::NativeTheme* observed_theme) override; @@ -194,7 +190,7 @@ // Caches the attached tab state provided to the handler, in cases where the // value needs to be requeried by the page. - GURL last_source_url_{GURL(chrome::kChromeUINewTabPageURL)}; + bool last_is_source_tab_first_party_ntp_ = true; PrefChangeRegistrar pref_change_registrar_; base::ScopedObservation<ui::NativeTheme, ui::NativeThemeObserver>
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc index f0b26493..43e2f3b 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_page_handler_unittest.cc
@@ -169,9 +169,7 @@ MOCK_METHOD(void, ScrollToSection, (side_panel::mojom::CustomizeChromeSection)); - MOCK_METHOD(void, - AttachedTabStateUpdated, - (side_panel::mojom::NewTabPageType)); + MOCK_METHOD(void, AttachedTabStateUpdated, (bool)); MOCK_METHOD(void, NtpManagedByNameUpdated, (const std::string&)); MOCK_METHOD(void, SetFooterSettings, (bool visible)); @@ -812,38 +810,18 @@ EXPECT_EQ(side_panel::mojom::CustomizeChromeSection::kAppearance, section); } -// Ensures that url's are correctly mapped to their NewTabPage type. -// Does not include test for `side_panel::mojom::NewTabPageType::kExtension` -// See `CustomizeChromeInteractiveTest.FooterSectionForExtensionNtp` for -// confirming Customize Chrome shows the footer section for Extension NTPs. TEST_F(CustomizeChromePageHandlerTest, AttachedTabStateUpdated) { - std::vector<std::pair<side_panel::mojom::NewTabPageType, GURL>> - ntp_types_and_urls = { - {side_panel::mojom::NewTabPageType::kNone, - GURL("https://www.google.com/")}, - {side_panel::mojom::NewTabPageType::kFirstPartyWebUI, - GURL(chrome::kChromeUINewTabPageURL)}, - {side_panel::mojom::NewTabPageType::kThirdPartyWebUI, - GURL(chrome::kChromeUINewTabPageThirdPartyURL)}, - {side_panel::mojom::NewTabPageType::kIncognito, - GURL(chrome::kChromeUINewTabURL)}, - {side_panel::mojom::NewTabPageType::kGuestMode, - GURL(chrome::kChromeUINewTabURL)}}; + bool kIsSourceTabFirstPartyNtpValue = false; - for (const auto& ntp_type_and_url : ntp_types_and_urls) { - if (ntp_type_and_url.first == - side_panel::mojom::NewTabPageType::kGuestMode) { - profile().SetGuestSession(true); - } + bool isSourceTabFirstPartyNtp; + EXPECT_CALL(mock_page_, AttachedTabStateUpdated) + .Times(1) + .WillOnce(SaveArg<0>(&isSourceTabFirstPartyNtp)); - side_panel::mojom::NewTabPageType source_tab; - EXPECT_CALL(mock_page_, AttachedTabStateUpdated) - .Times(1) - .WillOnce(SaveArg<0>(&source_tab)); - handler().AttachedTabStateUpdated(ntp_type_and_url.second); - mock_page_.FlushForTesting(); - EXPECT_EQ(ntp_type_and_url.first, source_tab); - } + handler().AttachedTabStateUpdated(kIsSourceTabFirstPartyNtpValue); + mock_page_.FlushForTesting(); + + EXPECT_EQ(kIsSourceTabFirstPartyNtpValue, isSourceTabFirstPartyNtp); } TEST_F(CustomizeChromePageHandlerTest, ScrollToUnspecifiedSection) {
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc index 05502f4..1c9e0c1 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.cc
@@ -305,11 +305,13 @@ } } -void CustomizeChromeUI::AttachedTabStateUpdated(const GURL& url) { +void CustomizeChromeUI::AttachedTabStateUpdated( + bool is_source_tab_first_party_ntp) { if (customize_chrome_page_handler_) { - customize_chrome_page_handler_->AttachedTabStateUpdated(url); + customize_chrome_page_handler_->AttachedTabStateUpdated( + is_source_tab_first_party_ntp); } else { - source_tab_url_ = url; + is_source_tab_first_party_ntp_ = is_source_tab_first_party_ntp; } } @@ -407,8 +409,10 @@ customize_chrome_page_handler_->ScrollToSection(*section_); section_.reset(); } - if (!source_tab_url_.is_empty()) { - customize_chrome_page_handler_->AttachedTabStateUpdated(source_tab_url_); + if (is_source_tab_first_party_ntp_.has_value()) { + customize_chrome_page_handler_->AttachedTabStateUpdated( + is_source_tab_first_party_ntp_.value()); + is_source_tab_first_party_ntp_.reset(); } if (is_theme_editable_.has_value()) { customize_chrome_page_handler_->UpdateThemeEditable(
diff --git a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.h b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.h index 33bc34fe..8445464 100644 --- a/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.h +++ b/chrome/browser/ui/webui/side_panel/customize_chrome/customize_chrome_ui.h
@@ -83,7 +83,7 @@ void ScrollToSection(CustomizeChromeSection section); // Passthrough that calls the CustomizeChromePage's AttachedTabStateUpdated. - void AttachedTabStateUpdated(const GURL& url); + void AttachedTabStateUpdated(bool is_attached_tab_first_party_ntp); // Passthrough that calls to CustomizeChromePage's UpdateThemeEditable. void UpdateThemeEditable(bool is_theme_editable); @@ -187,7 +187,7 @@ // Caches a request to scroll to a section in case the request happens before // the front-end is ready to receive the request. std::optional<CustomizeChromeSection> section_; - GURL source_tab_url_; + std::optional<bool> is_source_tab_first_party_ntp_; std::optional<bool> is_theme_editable_; std::unique_ptr<user_education::HelpBubbleHandler> help_bubble_handler_;
diff --git a/chrome/build/android-arm64.pgo.txt b/chrome/build/android-arm64.pgo.txt index 2121e42..7a3178a5 100644 --- a/chrome/build/android-arm64.pgo.txt +++ b/chrome/build/android-arm64.pgo.txt
@@ -1 +1 @@ -chrome-android64-main-1746044609-24b97d12ffd181c7270a89ff64582030f8202794-15f70a334873425aa887d4cdb216796f676c015a.profdata +chrome-android64-main-1746073150-e92a3ea778a2815127221f459aba3e74187a47c6-be45dde8005e8554979ffe8c2068f7f97f9536b6.profdata
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 82e6ec5..e389d034 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1746013960-7f7f0468d166b5e0c336ff95294ca554bc904703-85c17e9abc4ed443ef6794a715b5e9430d7ab21c.profdata +chrome-linux-main-1746057556-0fdc03a59cb9b581cdcbda430bb7355493197536-388545bb627f929d012e37faf58450a138d69a77.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index c5b90f4..a3e1b2fa 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1746050330-29bcdbb49f3e79fe3a8f9df22753151932f89e38-f56a6acf56996a56ef31a581d16665e62070b42d.profdata +chrome-mac-arm-main-1746071557-3183843248cde74d232190341032509f8140f87a-0eebbc236620fd680660c61b3a2febfaa7267c3b.profdata
diff --git a/chrome/build/win-arm64.pgo.txt b/chrome/build/win-arm64.pgo.txt index 667b77d..ecf607e 100644 --- a/chrome/build/win-arm64.pgo.txt +++ b/chrome/build/win-arm64.pgo.txt
@@ -1 +1 @@ -chrome-win-arm64-main-1746035971-4213c9308da5133e6bb3567981d16a60b087804b-b23738f45a2bc90b4fca6b0754754deaa3612f40.profdata +chrome-win-arm64-main-1746057556-111f17ef8fee0aa54dc18d6c9f3717d66fcfd919-388545bb627f929d012e37faf58450a138d69a77.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 091f2aa..3b3c8a8 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1746025195-882f8772ccd05493ec80fcf6548955fc1f9bb170-ab50c042d650061c65e5a9bceae223f7647b0df9.profdata +chrome-win32-main-1746035971-e8c9b3ee9a88f2d39d106757119693bc42b9ff66-b23738f45a2bc90b4fca6b0754754deaa3612f40.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index d336a639..1befe76 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1746013960-ece2f36b9cef2b73a3d83dd17d4b877bea06bf92-85c17e9abc4ed443ef6794a715b5e9430d7ab21c.profdata +chrome-win64-main-1746035971-081f85400de8f1a46812aecdb6bc4a2dcd104407-b23738f45a2bc90b4fca6b0754754deaa3612f40.profdata
diff --git a/chrome/common/webui_url_constants.h b/chrome/common/webui_url_constants.h index af2bad43..d2e895d 100644 --- a/chrome/common/webui_url_constants.h +++ b/chrome/common/webui_url_constants.h
@@ -652,6 +652,7 @@ inline constexpr char kSignOutSubPage[] = "signOut"; inline constexpr char kSiteDetailsSubpage[] = "content/siteDetails"; inline constexpr char kSyncSetupSubPage[] = "syncSetup"; +inline constexpr char kSyncSetupAdvancedSubPage[] = "syncSetup/advanced"; inline constexpr char kTriggeredResetProfileSettingsSubPage[] = "triggeredResetProfileSettings";
diff --git a/chrome/release_scripts b/chrome/release_scripts index 6ad235a..38a00a2 160000 --- a/chrome/release_scripts +++ b/chrome/release_scripts
@@ -1 +1 @@ -Subproject commit 6ad235a921b16b76e60316629f799e4fef593769 +Subproject commit 38a00a22c91fb29e2b8f6e88fae3d151a52e8f21
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index 839ff13..3b762714 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1709,6 +1709,7 @@ #if !BUILDFLAG(IS_ANDROID) blink::WebRuntimeFeatures::EnableWebHIDOnServiceWorkers(true); #endif // !BUILDFLAG(IS_ANDROID) + blink::WebRuntimeFeatures::EnableAIPromptAPIForWorkers(true); blink::WebRuntimeFeatures::EnableAIRewriterAPIForWorkers(true); blink::WebRuntimeFeatures::EnableAISummarizationAPIForWorkers(true); blink::WebRuntimeFeatures::EnableAIWriterAPIForWorkers(true);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 4afda06..117e1d5 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -8898,6 +8898,11 @@ # Unit tests that run on Win/Mac/Linux and Android desktop. if (enable_extensions_core) { sources += [ + "../browser/extensions/api/declarative_net_request/action_tracker_unittest.cc", + "../browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc", + "../browser/extensions/api/declarative_net_request/dnr_test_base.cc", + "../browser/extensions/api/declarative_net_request/dnr_test_base.h", + "../browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc", "../browser/extensions/api/webstore_private/extension_install_status_unittest.cc", "../browser/extensions/api/webstore_private/webstore_private_unittest.cc", "../browser/extensions/chrome_content_verifier_unittest.cc", @@ -9007,11 +9012,6 @@ "../browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc", "../browser/extensions/api/declarative_content/declarative_content_is_bookmarked_condition_tracker_unittest.cc", "../browser/extensions/api/declarative_content/declarative_content_page_url_condition_tracker_unittest.cc", - "../browser/extensions/api/declarative_net_request/action_tracker_unittest.cc", - "../browser/extensions/api/declarative_net_request/declarative_net_request_unittest.cc", - "../browser/extensions/api/declarative_net_request/dnr_test_base.cc", - "../browser/extensions/api/declarative_net_request/dnr_test_base.h", - "../browser/extensions/api/declarative_net_request/ruleset_manager_unittest.cc", "../browser/extensions/api/declarative_webrequest/webrequest_action_unittest.cc", "../browser/extensions/api/declarative_webrequest/webrequest_rules_registry_unittest.cc", "../browser/extensions/api/developer_private/developer_private_api_unittest.cc",
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/app_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/app_test.ts index 64f2981..6d06f6f 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/app_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/app_test.ts
@@ -7,7 +7,7 @@ import type {AppElement} from 'chrome://customize-chrome-side-panel.top-chrome/app.js'; import {CustomizeChromeImpression} from 'chrome://customize-chrome-side-panel.top-chrome/common.js'; import type {BackgroundCollection, CustomizeChromePageRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; -import {CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote, CustomizeChromeSection, NewTabPageType} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; +import {CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote, CustomizeChromeSection} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js'; import {CustomizeToolbarClientCallbackRouter, CustomizeToolbarHandlerRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_toolbar.mojom-webui.js'; import type {CustomizeToolbarHandlerInterface} from 'chrome://customize-chrome-side-panel.top-chrome/customize_toolbar.mojom-webui.js'; @@ -230,7 +230,7 @@ }); }); - test('source tab type should update the cards', async () => { + test('isSourceTabFirstPartyNtp should update the cards', async () => { const idsControlledByIsSourceTabFirstPartyNtp = [ '#shortcuts', '#modules', @@ -249,29 +249,19 @@ '#buttonContainer', ]; - const newTabPageTypes = [ - NewTabPageType.kFirstPartyWebUI, - NewTabPageType.kThirdPartyWebUI, - NewTabPageType.kThirdPartyRemote, - NewTabPageType.kExtension, - NewTabPageType.kIncognito, - NewTabPageType.kGuestMode, - NewTabPageType.kNone, - ]; - - const checkIdsVisibility = (sourceTabType: NewTabPageType) => { + const checkIdsVisibility = (isSourceTabFirstPartyNtp: boolean) => { idsControlledByIsSourceTabFirstPartyNtp.forEach( id => assertEquals( - sourceTabType === NewTabPageType.kFirstPartyWebUI, + isSourceTabFirstPartyNtp, !!customizeChromeApp.shadowRoot.querySelector(id))); idsNotControlledByIsSourceTabFirstPartyNtp.forEach( id => assertTrue(!!customizeChromeApp.shadowRoot.querySelector(id))); }; - await newTabPageTypes.forEach(async t => { - callbackRouter.attachedTabStateUpdated(t); + await[true, false].forEach(async b => { + callbackRouter.attachedTabStateUpdated(b); await microtasksFinished(); - checkIdsVisibility(t); + checkIdsVisibility(b); }); }); @@ -311,7 +301,7 @@ 'selected')); assertEquals(customizeChromeApp, document.activeElement); - callbackRouter.attachedTabStateUpdated(NewTabPageType.kExtension); + callbackRouter.attachedTabStateUpdated(false); callbackRouter.setThemeEditable(false); await microtasksFinished(); @@ -336,7 +326,7 @@ customizeChromeApp.shadowRoot.querySelector('#toolbarPage')! .classList.contains('selected')); - callbackRouter.attachedTabStateUpdated(NewTabPageType.kExtension); + callbackRouter.attachedTabStateUpdated(false); await microtasksFinished(); // Current page should now be toolbar.
diff --git a/chrome/test/data/webui/side_panel/customize_chrome/appearance_test.ts b/chrome/test/data/webui/side_panel/customize_chrome/appearance_test.ts index b2dc801b..ae64285 100644 --- a/chrome/test/data/webui/side_panel/customize_chrome/appearance_test.ts +++ b/chrome/test/data/webui/side_panel/customize_chrome/appearance_test.ts
@@ -7,7 +7,7 @@ import type {AppearanceElement} from 'chrome://customize-chrome-side-panel.top-chrome/appearance.js'; import {CustomizeChromeAction} from 'chrome://customize-chrome-side-panel.top-chrome/common.js'; import type {CustomizeChromePageRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; -import {CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote, NewTabPageType} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; +import {CustomizeChromePageCallbackRouter, CustomizeChromePageHandlerRemote} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome.mojom-webui.js'; import {CustomizeChromeApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_chrome_api_proxy.js'; import type {ManagedDialogElement} from 'chrome://resources/cr_components/managed_dialog/managed_dialog.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; @@ -619,7 +619,7 @@ }); }); - test('source tab type should update the content', async () => { + test('isSourceTabFirstPartyNtp should update the content', async () => { const idsControlledByIsSourceTabFirstPartyNtp = [ '#editButtonsContainer', '#themeSnapshot', @@ -637,29 +637,19 @@ '#editThemeIcon', ]; - const newTabPageTypes = [ - NewTabPageType.kFirstPartyWebUI, - NewTabPageType.kThirdPartyWebUI, - NewTabPageType.kThirdPartyRemote, - NewTabPageType.kExtension, - NewTabPageType.kIncognito, - NewTabPageType.kGuestMode, - NewTabPageType.kNone, - ]; - - const checkIdsVisibility = (sourceTabType: NewTabPageType) => { + const checkIdsVisibility = (isSourceTabFirstPartyNtp: boolean) => { idsControlledByIsSourceTabFirstPartyNtp.forEach( id => assertEquals( - sourceTabType === NewTabPageType.kFirstPartyWebUI, + isSourceTabFirstPartyNtp, !!appearanceElement.shadowRoot.querySelector(id))); idsNotControlledByIsSourceTabFirstPartyNtp.forEach( id => assertTrue(!!appearanceElement.shadowRoot.querySelector(id))); }; - await newTabPageTypes.forEach(async t => { - callbackRouterRemote.attachedTabStateUpdated(t); + await[true, false].forEach(async b => { + callbackRouterRemote.attachedTabStateUpdated(b); await microtasksFinished(); - checkIdsVisibility(t); + checkIdsVisibility(b); }); }); });
diff --git a/chrome/updater/app/app_net_worker.cc b/chrome/updater/app/app_net_worker.cc index e2d3022..5664d48 100644 --- a/chrome/updater/app/app_net_worker.cc +++ b/chrome/updater/app/app_net_worker.cc
@@ -62,10 +62,11 @@ int32_t net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); observer_->OnRequestComplete(*response_body, net_error, header_etag, - header_x_cup_server_proof, + header_x_cup_server_proof, header_cookie, xheader_retry_after_sec); } @@ -172,7 +173,8 @@ base::MakeRefCounted<PostRequestObserverWrapper>(std::move(callback)); if (fetcher_ || file_fetcher_) { LOG(ERROR) << "Each service instance can do only one fetch request."; - wrapper->OnRequestComplete(nullptr, kErrorMojoRequestRejected, {}, {}, -1); + wrapper->OnRequestComplete(nullptr, kErrorMojoRequestRejected, {}, {}, {}, + -1); std::move(on_complete_callback_).Run(kErrorMojoRequestRejected); return; } @@ -195,10 +197,11 @@ std::optional<std::string> response_body, int32_t net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec) { wrapper->OnRequestComplete(std::move(response_body), net_error, header_etag, header_x_cup_server_proof, - xheader_retry_after_sec); + header_cookie, xheader_retry_after_sec); std::move(callback).Run(net_error); }, wrapper, std::move(on_complete_callback_)));
diff --git a/chrome/updater/app/app_net_worker_unittest.cc b/chrome/updater/app/app_net_worker_unittest.cc index 96f10cf..5ef1ae3 100644 --- a/chrome/updater/app/app_net_worker_unittest.cc +++ b/chrome/updater/app/app_net_worker_unittest.cc
@@ -99,6 +99,8 @@ http_response->AddCustomHeader( update_client::NetworkFetcher::kHeaderXCupServerProof, "cup-server-proof-xyz"); + http_response->AddCustomHeader( + update_client::NetworkFetcher::kHeaderCookie, "cookie-for-testing"); http_response->AddCustomHeader("SomeOtherHeader", "foo-bar"); return http_response; })); @@ -120,11 +122,13 @@ [&](std::optional<std::string> response_body, int32_t net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec) { EXPECT_EQ(net_error, 0); EXPECT_EQ(*response_body, "hello world!"); EXPECT_EQ(header_etag, "etag-for-test"); EXPECT_EQ(header_x_cup_server_proof, "cup-server-proof-xyz"); + EXPECT_EQ(header_cookie, "cookie-for-testing"); run_loop.Quit(); }))); run_loop.Run(); @@ -190,6 +194,7 @@ [&](std::optional<std::string> response_body, int32_t net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec) { EXPECT_NE(net_error, 0); run_loop.Quit();
diff --git a/chrome/updater/device_management/dm_client.cc b/chrome/updater/device_management/dm_client.cc index f98b612..062fe0a7 100644 --- a/chrome/updater/device_management/dm_client.cc +++ b/chrome/updater/device_management/dm_client.cc
@@ -162,6 +162,7 @@ int net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec); std::unique_ptr<DMClient::Configurator> config_; @@ -275,6 +276,7 @@ int net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); VLOG(2) << __func__;
diff --git a/chrome/updater/net/fallback_net_fetcher.cc b/chrome/updater/net/fallback_net_fetcher.cc index 466dcf7..02315dc7 100644 --- a/chrome/updater/net/fallback_net_fetcher.cc +++ b/chrome/updater/net/fallback_net_fetcher.cc
@@ -75,6 +75,7 @@ int net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const int should_fallback = net_error || (http_status_code_ != 200); @@ -89,7 +90,7 @@ } std::move(post_request_complete_callback) .Run(std::move(response_body), net_error, header_etag, - header_x_cup_server_proof, xheader_retry_after_sec); + header_x_cup_server_proof, header_cookie, xheader_retry_after_sec); } base::OnceClosure FallbackNetFetcher::DownloadToFile(
diff --git a/chrome/updater/net/fallback_net_fetcher.h b/chrome/updater/net/fallback_net_fetcher.h index 93b773b..015ec1a8 100644 --- a/chrome/updater/net/fallback_net_fetcher.h +++ b/chrome/updater/net/fallback_net_fetcher.h
@@ -74,6 +74,7 @@ int net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec); void DownloadToFileDone(
diff --git a/chrome/updater/net/fallback_net_fetcher_unittest.cc b/chrome/updater/net/fallback_net_fetcher_unittest.cc index 2aa1d127..7aa2bcf 100644 --- a/chrome/updater/net/fallback_net_fetcher_unittest.cc +++ b/chrome/updater/net/fallback_net_fetcher_unittest.cc
@@ -77,8 +77,8 @@ [](base::OnceCallback<int(void)> error_supplier, update_client::NetworkFetcher::PostRequestCompleteCallback callback) { - std::move(callback).Run(std::nullopt, - std::move(error_supplier).Run(), {}, {}, 0); + std::move(callback).Run( + std::nullopt, std::move(error_supplier).Run(), {}, {}, {}, 0); }, std::move(error_supplier)), base::BindOnce( @@ -95,7 +95,7 @@ base::BindOnce( [](update_client::NetworkFetcher::PostRequestCompleteCallback callback) { - std::move(callback).Run(std::nullopt, 0, {}, {}, 0); + std::move(callback).Run(std::nullopt, 0, {}, {}, {}, 0); }), base::BindOnce( [](base::OnceCallback<int(void)> error_supplier, @@ -121,11 +121,11 @@ ran2 = true; return 0; }))) - .PostRequest( - {}, {}, {}, {}, base::DoNothing(), base::DoNothing(), - base::BindLambdaForTesting([&](std::optional<std::string>, int, - const std::string&, const std::string&, - int64_t) { called_back = true; })); + .PostRequest({}, {}, {}, {}, base::DoNothing(), base::DoNothing(), + base::BindLambdaForTesting( + [&](std::optional<std::string>, int, const std::string&, + const std::string&, const std::string&, + int64_t) { called_back = true; })); EXPECT_TRUE(ran1); EXPECT_FALSE(ran2); EXPECT_TRUE(called_back); @@ -163,11 +163,11 @@ ran2 = true; return 0; }))) - .PostRequest( - {}, {}, {}, {}, base::DoNothing(), base::DoNothing(), - base::BindLambdaForTesting([&](std::optional<std::string>, int, - const std::string&, const std::string&, - int64_t) { called_back = true; })); + .PostRequest({}, {}, {}, {}, base::DoNothing(), base::DoNothing(), + base::BindLambdaForTesting( + [&](std::optional<std::string>, int, const std::string&, + const std::string&, const std::string&, + int64_t) { called_back = true; })); EXPECT_TRUE(ran1); EXPECT_TRUE(ran2); EXPECT_TRUE(called_back); @@ -201,11 +201,11 @@ return 1; })), nullptr) - .PostRequest( - {}, {}, {}, {}, base::DoNothing(), base::DoNothing(), - base::BindLambdaForTesting([&](std::optional<std::string>, int, - const std::string&, const std::string&, - int64_t) { called_back = true; })); + .PostRequest({}, {}, {}, {}, base::DoNothing(), base::DoNothing(), + base::BindLambdaForTesting( + [&](std::optional<std::string>, int, const std::string&, + const std::string&, const std::string&, + int64_t) { called_back = true; })); EXPECT_TRUE(ran1); EXPECT_TRUE(called_back); }
diff --git a/chrome/updater/net/fetcher_callback_adapter.cc b/chrome/updater/net/fetcher_callback_adapter.cc index 9686409..e04b8c6 100644 --- a/chrome/updater/net/fetcher_callback_adapter.cc +++ b/chrome/updater/net/fetcher_callback_adapter.cc
@@ -58,12 +58,15 @@ int32_t net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, std::optional<uint64_t> xheader_retry_after_sec) override { CHECK(post_request_complete_callback_) << __func__ << " is called without a valid callback. Was " << __func__ << " called mulitple times?"; + std::move(post_request_complete_callback_) .Run(response_body, net_error, header_etag, header_x_cup_server_proof, + header_cookie, xheader_retry_after_sec ? ToSignedIntegral(*xheader_retry_after_sec) : -1);
diff --git a/chrome/updater/net/mac/mojom/updater_fetcher.mojom b/chrome/updater/net/mac/mojom/updater_fetcher.mojom index 606d5a3e..6de8f40 100644 --- a/chrome/updater/net/mac/mojom/updater_fetcher.mojom +++ b/chrome/updater/net/mac/mojom/updater_fetcher.mojom
@@ -28,6 +28,7 @@ int32 net_error, string header_etag, string header_x_cup_server_proof, + string header_cookie, uint64? xheader_retry_after_sec); };
diff --git a/chrome/updater/net/network_fetcher_linux.cc b/chrome/updater/net/network_fetcher_linux.cc index 7821b905e..e0a867cf 100644 --- a/chrome/updater/net/network_fetcher_linux.cc +++ b/chrome/updater/net/network_fetcher_linux.cc
@@ -211,6 +211,8 @@ update_client::NetworkFetcher::kHeaderEtag), GetHeaderValue(response_headers, update_client::NetworkFetcher::kHeaderXCupServerProof), + GetHeaderValue(response_headers, + update_client::NetworkFetcher::kHeaderCookie), x_retry_after)); curl_slist_free_all(headers);
diff --git a/chrome/updater/net/network_fetcher_mac.mm b/chrome/updater/net/network_fetcher_mac.mm index e7d8ba6..68cef73 100644 --- a/chrome/updater/net/network_fetcher_mac.mm +++ b/chrome/updater/net/network_fetcher_mac.mm
@@ -176,6 +176,13 @@ if ([headers objectForKey:headerXCupServerProof]) { cupServerProof = [headers objectForKey:headerXCupServerProof]; } + NSString* headerCookie = + base::SysUTF8ToNSString(update_client::NetworkFetcher::kHeaderCookie); + NSString* cookie = @""; + if ([headers objectForKey:headerCookie]) { + cookie = [headers objectForKey:headerCookie]; + } + int64_t retryAfterResult = -1; NSString* xRetryAfter = [headers objectForKey:base::SysUTF8ToNSString( @@ -191,7 +198,8 @@ std::string(reinterpret_cast<const char*>([_downloadedData bytes]), [_downloadedData length]), error.code, base::SysNSStringToUTF8(etag), - base::SysNSStringToUTF8(cupServerProof), retryAfterResult)); + base::SysNSStringToUTF8(cupServerProof), + base::SysNSStringToUTF8(cookie), retryAfterResult)); } @end @@ -638,7 +646,7 @@ if (const int dial_result = DialFetchService(); dial_result != kErrorOk) { LOG(ERROR) << "Failed to dial the fetch service: " << dial_result; std::move(post_request_complete_callback) - .Run(nullptr, dial_result, {}, {}, -1); + .Run(nullptr, dial_result, {}, {}, {}, -1); return; }
diff --git a/chrome/updater/net/network_fetcher_win.cc b/chrome/updater/net/network_fetcher_win.cc index b3f8abe2..df74bd5b 100644 --- a/chrome/updater/net/network_fetcher_win.cc +++ b/chrome/updater/net/network_fetcher_win.cc
@@ -154,6 +154,7 @@ // this is best effort only. std::wstring x_cup_server_proof; std::wstring etag; + std::wstring cookie; int x_retry_after_sec = -1; winhttp_network_fetcher_->QueryHeaderString( base::SysUTF8ToWide( @@ -161,6 +162,9 @@ &x_cup_server_proof); winhttp_network_fetcher_->QueryHeaderString( base::SysUTF8ToWide(update_client::NetworkFetcher::kHeaderEtag), &etag); + winhttp_network_fetcher_->QueryHeaderString( + base::SysUTF8ToWide(update_client::NetworkFetcher::kHeaderCookie), + &cookie); winhttp_network_fetcher_->QueryHeaderInt( base::SysUTF8ToWide(update_client::NetworkFetcher::kHeaderXRetryAfter), &x_retry_after_sec); @@ -168,7 +172,8 @@ std::move(post_request_complete_callback_) .Run(winhttp_network_fetcher_->GetResponseBody(), winhttp_network_fetcher_->GetNetError(), base::SysWideToUTF8(etag), - base::SysWideToUTF8(x_cup_server_proof), x_retry_after_sec); + base::SysWideToUTF8(x_cup_server_proof), base::SysWideToUTF8(cookie), + x_retry_after_sec); } void NetworkFetcher::DownloadToFileComplete(int /*response_code*/) {
diff --git a/chrome/updater/net/network_unittest.cc b/chrome/updater/net/network_unittest.cc index 6ee6bb9..43f71f2 100644 --- a/chrome/updater/net/network_unittest.cc +++ b/chrome/updater/net/network_unittest.cc
@@ -66,11 +66,13 @@ int net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec) { EXPECT_EQ(*response_body, expected_body); EXPECT_EQ(net_error, 0); EXPECT_EQ(header_etag, "Wfhw789h"); EXPECT_EQ(header_x_cup_server_proof, "server-proof"); + EXPECT_EQ(header_cookie, "cookie"); EXPECT_EQ(xheader_retry_after_sec, 67); PostRequestCompleted(); } @@ -95,6 +97,7 @@ http_response->AddCustomHeader("x-retry-after", "67"); http_response->AddCustomHeader("etag", "Wfhw789h"); http_response->AddCustomHeader("x-cup-server-proof", "server-proof"); + http_response->AddCustomHeader("Cookie", "cookie"); } else if (request.method == net::test_server::HttpMethod::METHOD_GET) { http_response->set_content("hello"); http_response->set_content_type("application/octet-stream");
diff --git a/chromeos/ash/services/ime/public/mojom/input_method.mojom b/chromeos/ash/services/ime/public/mojom/input_method.mojom index 1395430a..b53f2f9d62 100644 --- a/chromeos/ash/services/ime/public/mojom/input_method.mojom +++ b/chromeos/ash/services/ime/public/mojom/input_method.mojom
@@ -6,7 +6,7 @@ // the Chromium repo. This file should be updated first, before syncing in the // other repos. -// Next MinVersion: 25 +// Next MinVersion: 26 module ash.ime.mojom; @@ -25,7 +25,7 @@ // If a key is not listed here, then it means that the Chrome OS first-party // IMEs do not handle it and it is safe for the OS to handle the key itself. // -// Next ordinal: 41 +// Next ordinal: 42 [Stable, Extensible, RenamedFrom="chromeos.ime.mojom.NamedDomKey"] enum NamedDomKey { [Default] kOther = 0, @@ -75,6 +75,7 @@ [MinVersion=23] kAudioVolumeDown = 38, [MinVersion=23] kAudioVolumeUp = 39, [MinVersion=24] kDelete = 40, + [MinVersion=25] kNumLock = 41, }; // Represents a key pressed by the user, taking into account aspects like
diff --git a/clank b/clank index cfb3b18..b8e94f7 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit cfb3b184379b5491aafc36c95a2d8effd010eea2 +Subproject commit b8e94f74cdf17fd4bad068bed25f841a4b566dce
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index f2ec66ae..7618a839 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -498,6 +498,8 @@ "payments/payments_request_details.h", "payments/payments_requests/create_bnpl_payment_instrument_request.cc", "payments/payments_requests/create_bnpl_payment_instrument_request.h", + "payments/payments_requests/create_card_request.cc", + "payments/payments_requests/create_card_request.h", "payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.cc", "payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request.h", "payments/payments_requests/get_bnpl_payment_instrument_for_fetching_vcn_request.cc", @@ -1386,6 +1388,7 @@ "payments/payments_data_cleaner_unittest.cc", "payments/payments_network_interface_unittest.cc", "payments/payments_requests/create_bnpl_payment_instrument_request_unittest.cc", + "payments/payments_requests/create_card_request_unittest.cc", "payments/payments_requests/get_bnpl_payment_instrument_for_fetching_url_request_unittest.cc", "payments/payments_requests/get_bnpl_payment_instrument_for_fetching_vcn_request_unittest.cc", "payments/payments_requests/get_card_upload_details_request_unittest.cc",
diff --git a/components/autofill/core/browser/payments/payments_request_details.h b/components/autofill/core/browser/payments/payments_request_details.h index 0efd0d2..9f2c0bc 100644 --- a/components/autofill/core/browser/payments/payments_request_details.h +++ b/components/autofill/core/browser/payments/payments_request_details.h
@@ -300,38 +300,6 @@ LegalMessageLines issuer_legal_message; }; -// A collection of the information required to make a credit card upload -// request. -struct UploadCardRequestDetails { - UploadCardRequestDetails(); - UploadCardRequestDetails(const UploadCardRequestDetails& other); - ~UploadCardRequestDetails(); - - int64_t billing_customer_number = 0; - int detected_values; - CreditCard card; - std::u16string cvc; - std::vector<AutofillProfile> profiles; - std::u16string context_token; - std::string risk_data; - std::string app_locale; - std::vector<ClientBehaviorConstants> client_behavior_signals; -}; - -// A collection of information required to make an IBAN upload request. -struct UploadIbanRequestDetails { - UploadIbanRequestDetails(); - UploadIbanRequestDetails(const UploadIbanRequestDetails& other); - ~UploadIbanRequestDetails(); - - std::string app_locale; - int64_t billing_customer_number = 0; - std::u16string context_token; - std::u16string value; - std::u16string nickname; - std::string risk_data; -}; - // An enum set in the GetCardUploadDetailsRequest indicating the source of the // request when uploading a card to Google Payments. It should stay consistent // with the same enum in Google Payments server code. @@ -350,6 +318,40 @@ UPSTREAM_SAVE_AND_FILL, }; +// A collection of the information required to make a credit card upload +// request. +struct UploadCardRequestDetails { + UploadCardRequestDetails(); + UploadCardRequestDetails(const UploadCardRequestDetails& other); + ~UploadCardRequestDetails(); + + int64_t billing_customer_number = 0; + int detected_values; + CreditCard card; + std::u16string cvc; + std::vector<AutofillProfile> profiles; + std::u16string context_token; + std::string risk_data; + std::string app_locale; + std::vector<ClientBehaviorConstants> client_behavior_signals; + UploadCardSource upload_card_source = + UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE; +}; + +// A collection of information required to make an IBAN upload request. +struct UploadIbanRequestDetails { + UploadIbanRequestDetails(); + UploadIbanRequestDetails(const UploadIbanRequestDetails& other); + ~UploadIbanRequestDetails(); + + std::string app_locale; + int64_t billing_customer_number = 0; + std::u16string context_token; + std::u16string value; + std::u16string nickname; + std::string risk_data; +}; + // A collection of information received in the response for an // UploadCardRequest. struct UploadCardResponseDetails {
diff --git a/components/autofill/core/browser/payments/payments_requests/create_card_request.cc b/components/autofill/core/browser/payments/payments_requests/create_card_request.cc new file mode 100644 index 0000000..206e69d346 --- /dev/null +++ b/components/autofill/core/browser/payments/payments_requests/create_card_request.cc
@@ -0,0 +1,168 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/payments/payments_requests/create_card_request.h" + +#include "base/json/json_writer.h" +#include "base/strings/escape.h" +#include "base/strings/utf_string_conversions.h" + +namespace autofill::payments { + +namespace { +const char kCreateCardRequestPath[] = + "payments/apis-secure/chromepaymentsservice/createpaymentinstrument" + "?s7e_suffix=chromewallet"; +const char kCreateCardRequestFormat[] = + "requestContentType=application/json; charset=utf-8&request=%s" + "&s7e_21_pan=%s&s7e_13_cvc=%s"; +const char kCreateCardRequestFormatWithoutCvc[] = + "requestContentType=application/json; charset=utf-8&request=%s" + "&s7e_21_pan=%s"; +} // namespace + +CreateCardRequest::CreateCardRequest( + const UploadCardRequestDetails& request_details, + base::OnceCallback<void(PaymentsAutofillClient::PaymentsRpcResult, + const std::string&)> callback) + : request_details_(request_details), callback_(std::move(callback)) {} + +CreateCardRequest::~CreateCardRequest() = default; + +std::string CreateCardRequest::GetRequestUrlPath() { + return kCreateCardRequestPath; +} + +std::string CreateCardRequest::GetRequestContentType() { + return "application/x-www-form-urlencoded"; +} + +std::string CreateCardRequest::GetRequestContent() { + base::Value::Dict request_dict; + + const std::string& app_locale = request_details_.app_locale; + base::Value::Dict context; + context.Set("language_code", app_locale); + context.Set("billable_service", kUploadPaymentMethodBillableServiceNumber); + if (request_details_.billing_customer_number != 0) { + context.Set("customer_context", + BuildCustomerContextDictionary( + request_details_.billing_customer_number)); + } + request_dict.Set("context", std::move(context)); + + request_dict.Set( + "chrome_user_context", + BuildChromeUserContext(request_details_.client_behavior_signals)); + + request_dict.Set("context_token", request_details_.context_token); + + if (request_details_.card.HasNonEmptyValidNickname()) { + request_dict.Set("nickname", request_details_.card.nickname()); + } + + request_dict.Set("risk_data_encoded", + BuildRiskDictionary(request_details_.risk_data)); + + base::Value::Dict card_info; + card_info.Set("pan", "__param:s7e_21_pan"); + if (!request_details_.cvc.empty()) { + card_info.Set("cvc", "__param:s7e_13_cvc"); + } + int value = 0; + const std::u16string exp_month = + request_details_.card.GetInfo(CREDIT_CARD_EXP_MONTH, app_locale); + const std::u16string exp_year = + request_details_.card.GetInfo(CREDIT_CARD_EXP_4_DIGIT_YEAR, app_locale); + if (base::StringToInt(exp_month, &value)) { + card_info.Set("expiration_month", value); + } + if (base::StringToInt(exp_year, &value)) { + card_info.Set("expiration_year", value); + } + SetStringIfNotEmpty(request_details_.card, CREDIT_CARD_NAME_FULL, app_locale, + "cardholder_name", card_info); + // When this is invoked, caller is guaranteed to send only one unique address, + // if not an empty list. + CHECK_LE(request_details_.profiles.size(), 1U); + if (!request_details_.profiles.empty()) { + card_info.Set( + "address", + BuildAddressDictionary(request_details_.profiles[0], app_locale, true)); + } + + switch (request_details_.upload_card_source) { + case UploadCardSource::UNKNOWN_UPLOAD_CARD_SOURCE: + card_info.Set("upload_card_source", "UNKNOWN_UPLOAD_CARD_SOURCE"); + break; + case UploadCardSource::UPSTREAM_SAVE_AND_FILL: + card_info.Set("upload_card_source", "UPSTREAM_SAVE_AND_FILL"); + break; + default: + // This class has not been integrated with other Upstream flows yet. + NOTREACHED(); + } + request_dict.Set("card_info", std::move(card_info)); + + const std::u16string pan = + request_details_.card.GetInfo(CREDIT_CARD_NUMBER, app_locale); + std::string json_request; + base::JSONWriter::Write(request_dict, &json_request); + std::string request_content; + if (request_details_.cvc.empty()) { + request_content = base::StringPrintf( + kCreateCardRequestFormatWithoutCvc, + base::EscapeUrlEncodedData(json_request, true).c_str(), + base::EscapeUrlEncodedData(base::UTF16ToASCII(pan), true).c_str()); + } else { + request_content = base::StringPrintf( + kCreateCardRequestFormat, + base::EscapeUrlEncodedData(json_request, true).c_str(), + base::EscapeUrlEncodedData(base::UTF16ToASCII(pan), true).c_str(), + base::EscapeUrlEncodedData(base::UTF16ToASCII(request_details_.cvc), + true) + .c_str()); + } + + DVLOG(3) << "createcard request body: " << request_content; + return request_content; +} + +void CreateCardRequest::ParseResponse(const base::Value::Dict& response) { + if (const base::Value::Dict* card_info = response.FindDict("card_info")) { + contains_card_info_ = true; + if (const std::string* instrument_id = + card_info->FindString("instrument_id")) { + instrument_id_ = std::move(*instrument_id); + } + } +} + +bool CreateCardRequest::IsResponseComplete() { + return contains_card_info_; +} + +void CreateCardRequest::RespondToDelegate( + PaymentsAutofillClient::PaymentsRpcResult result) { + std::move(callback_).Run(result, instrument_id_); +} + +std::string CreateCardRequest::GetHistogramName() const { + return "CreateCardRequest"; +} + +std::optional<base::TimeDelta> CreateCardRequest::GetTimeout() const { + if (!base::FeatureList::IsEnabled( + features::kAutofillUploadCardRequestTimeout)) { + return std::nullopt; + } + return base::Milliseconds( + features::kAutofillUploadCardRequestTimeoutMilliseconds.Get()); +} + +std::string CreateCardRequest::GetInstrumentIdForTesting() const { + return instrument_id_; +} + +} // namespace autofill::payments
diff --git a/components/autofill/core/browser/payments/payments_requests/create_card_request.h b/components/autofill/core/browser/payments/payments_requests/create_card_request.h new file mode 100644 index 0000000..0b1e475 --- /dev/null +++ b/components/autofill/core/browser/payments/payments_requests/create_card_request.h
@@ -0,0 +1,47 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_CREATE_CARD_REQUEST_H_ +#define COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_CREATE_CARD_REQUEST_H_ + +#include "components/autofill/core/browser/payments/payments_request_details.h" +#include "components/autofill/core/browser/payments/payments_requests/payments_request.h" + +namespace autofill::payments { + +class CreateCardRequest : public PaymentsRequest { + public: + CreateCardRequest( + const UploadCardRequestDetails& request_details, + base::OnceCallback<void(PaymentsAutofillClient::PaymentsRpcResult, + const std::string&)> callback); + CreateCardRequest(const CreateCardRequest&) = delete; + CreateCardRequest& operator=(const CreateCardRequest&) = delete; + ~CreateCardRequest() override; + + // PaymentsRequest: + std::string GetRequestUrlPath() override; + std::string GetRequestContentType() override; + std::string GetRequestContent() override; + void ParseResponse(const base::Value::Dict& response) override; + bool IsResponseComplete() override; + void RespondToDelegate( + PaymentsAutofillClient::PaymentsRpcResult result) override; + std::string GetHistogramName() const override; + std::optional<base::TimeDelta> GetTimeout() const override; + + std::string GetInstrumentIdForTesting() const; + + private: + bool contains_card_info_ = false; + const UploadCardRequestDetails request_details_; + std::string instrument_id_; + base::OnceCallback<void(PaymentsAutofillClient::PaymentsRpcResult, + const std::string&)> + callback_; +}; + +} // namespace autofill::payments + +#endif // COMPONENTS_AUTOFILL_CORE_BROWSER_PAYMENTS_PAYMENTS_REQUESTS_CREATE_CARD_REQUEST_H_
diff --git a/components/autofill/core/browser/payments/payments_requests/create_card_request_unittest.cc b/components/autofill/core/browser/payments/payments_requests/create_card_request_unittest.cc new file mode 100644 index 0000000..47076f9 --- /dev/null +++ b/components/autofill/core/browser/payments/payments_requests/create_card_request_unittest.cc
@@ -0,0 +1,210 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/autofill/core/browser/payments/payments_requests/create_card_request.h" + +#include "base/functional/callback_helpers.h" +#include "base/json/json_writer.h" +#include "base/strings/escape.h" +#include "base/strings/utf_string_conversions.h" +#include "base/test/values_test_util.h" +#include "components/autofill/core/browser/payments/payments_request_details.h" +#include "components/autofill/core/browser/payments/test/autofill_payments_test_utils.h" +#include "components/autofill/core/browser/test_utils/autofill_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace autofill::payments { + +namespace { + +struct CreateCardOptions { + CreateCardOptions& with_cvc_in_request(bool b) { + include_cvc = b; + return *this; + } + + CreateCardOptions& with_nickname_in_request(bool b) { + include_nickname = b; + return *this; + } + + CreateCardOptions& with_address_in_request(bool b) { + include_address = b; + return *this; + } + + bool include_cvc = true; + bool include_nickname = true; + bool include_address = true; +}; + +std::unique_ptr<CreateCardRequest> BuildCreateCardRequest( + const CreateCardOptions& option = CreateCardOptions()) { + UploadCardRequestDetails request_details; + request_details.billing_customer_number = 111122223333; + request_details.card = test::GetCreditCard(); + if (option.include_cvc) { + request_details.cvc = u"123"; + } + if (option.include_nickname) { + request_details.card.SetNickname(u"some nickname"); + } + request_details.client_behavior_signals = { + ClientBehaviorConstants::kOfferingToSaveCvc}; + request_details.context_token = u"some context token"; + request_details.risk_data = "some risk data"; + request_details.app_locale = "en"; + if (option.include_address) { + request_details.profiles.emplace_back( + test::GetFullProfile(AddressCountryCode("US"))); + } + request_details.upload_card_source = UploadCardSource::UPSTREAM_SAVE_AND_FILL; + + return std::make_unique<CreateCardRequest>(request_details, + base::DoNothing()); +} + +TEST(CreateCardRequestTest, GetRequestUrlPath) { + std::unique_ptr<CreateCardRequest> request = BuildCreateCardRequest(); + + EXPECT_EQ(request->GetRequestUrlPath(), + "payments/apis-secure/chromepaymentsservice/" + "createpaymentinstrument?s7e_suffix=chromewallet"); +} + +TEST(CreateCardRequestTest, GetRequestContent_ContainsExpectedData) { + std::unique_ptr<CreateCardRequest> request = BuildCreateCardRequest(); + base::Value::Dict address = + base::Value::Dict() + .Set("phone_number", "16502111111") + .Set("postal_address", + base::Value::Dict() + .Set("address_line", base::Value::List() + .Append("666 Erebus St.") + .Append("Apt 8")) + .Set("administrative_area_name", "CA") + .Set("country_name_code", "US") + .Set("locality_name", "Elysium") + .Set("postal_code_number", "91111") + .Set("recipient_name", "John H. Doe")); + int exp_month, exp_year; + base::StringToInt(test::NextMonth(), &exp_month); + base::StringToInt(test::NextYear(), &exp_year); + base::Value::Dict json_dict = + base::Value::Dict() + .Set("context", + base::Value::Dict() + .Set("billable_service", + payments::kUploadPaymentMethodBillableServiceNumber) + .Set("customer_context", + PaymentsRequest::BuildCustomerContextDictionary( + 111122223333)) + .Set("language_code", "en")) + .Set("chrome_user_context", + base::Value::Dict().Set( + "client_behavior_signals", + base::Value::List().Append(static_cast<int>( + ClientBehaviorConstants::kOfferingToSaveCvc)))) + .Set("context_token", "some context token") + .Set("risk_data_encoded", + PaymentsRequest::BuildRiskDictionary("some risk data")) + .Set("nickname", "some nickname") + .Set("card_info", + base::Value::Dict() + .Set("pan", "__param:s7e_21_pan") + .Set("cvc", "__param:s7e_13_cvc") + .Set("expiration_month", exp_month) + .Set("expiration_year", exp_year) + .Set("cardholder_name", "Test User") + .Set("address", std::move(address)) + .Set("upload_card_source", "UPSTREAM_SAVE_AND_FILL")); + std::string expected_json_content; + base::JSONWriter::Write(json_dict, &expected_json_content); + + std::string expected_request_content = base::StringPrintf( + "requestContentType=application/json; charset=utf-8&request=%s" + "&s7e_21_pan=%s&s7e_13_cvc=%s", + base::EscapeUrlEncodedData(expected_json_content, true).c_str(), + base::EscapeUrlEncodedData(base::UTF16ToASCII(u"4111111111111111"), true) + .c_str(), + base::EscapeUrlEncodedData(base::UTF16ToASCII(u"123"), true).c_str()); + + EXPECT_EQ(request->GetRequestContent(), expected_request_content); +} + +TEST(CreateCardRequestTest, NoCvcInRequestIfNotProvided) { + std::unique_ptr<CreateCardRequest> request = + BuildCreateCardRequest(CreateCardOptions().with_cvc_in_request(false)); + + EXPECT_TRUE(!request->GetRequestContent().empty()); + // Verify that the encrypted_cvc and s7e_13_cvc parameters were not included + // in the request. + EXPECT_TRUE(request->GetRequestContent().find("encrypted_cvc") == + std::string::npos); + EXPECT_TRUE(request->GetRequestContent().find("__param:s7e_13_cvc") == + std::string::npos); + EXPECT_TRUE(request->GetRequestContent().find("&s7e_13_cvc=") == + std::string::npos); +} + +TEST(CreateCardRequestTest, NoNicknameInRequestIfNicknameNotProvided) { + std::unique_ptr<CreateCardRequest> request = BuildCreateCardRequest( + CreateCardOptions().with_nickname_in_request(false)); + + // Card nickname was not set. + EXPECT_TRUE(request->GetRequestContent().find("nickname") == + std::string::npos); +} + +TEST(CreateCardRequestTest, NoAddressInRequestIfAddressNotProvided) { + std::unique_ptr<CreateCardRequest> request = BuildCreateCardRequest( + CreateCardOptions().with_address_in_request(false)); + + // Address was not set. + EXPECT_TRUE(request->GetRequestContent().find("address") == + std::string::npos); +} + +TEST(CreateCardRequestTest, GetTimeOutIfFlagDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature( + features::kAutofillUploadCardRequestTimeout); + std::unique_ptr<CreateCardRequest> request = BuildCreateCardRequest(); + EXPECT_FALSE(request->GetTimeout().has_value()); +} + +TEST(CreateCardRequestTest, GetTimeOut) { + base::FieldTrialParams params; + params["autofill_upload_card_request_timeout_milliseconds"] = "6000"; + base::test::ScopedFeatureList feature_list; + feature_list.InitAndEnableFeatureWithParameters( + features::kAutofillUploadCardRequestTimeout, params); + std::unique_ptr<CreateCardRequest> request = BuildCreateCardRequest(); + + EXPECT_EQ(*request->GetTimeout(), base::Milliseconds(6000)); +} + +TEST(CreateCardRequestTest, ParseResponse) { + std::unique_ptr<CreateCardRequest> request = BuildCreateCardRequest(); + + base::Value::Dict response = base::Value::Dict().Set( + "card_info", base::Value::Dict().Set("instrument_id", "11223344")); + + request->ParseResponse(response); + + EXPECT_EQ(request->GetInstrumentIdForTesting(), "11223344"); + EXPECT_TRUE(request->IsResponseComplete()); +} + +TEST(CreateCardRequestTest, ParseResponse_MissingCardInfo) { + std::unique_ptr<CreateCardRequest> request = BuildCreateCardRequest(); + + request->ParseResponse(base::Value::Dict()); + + EXPECT_FALSE(request->IsResponseComplete()); +} + +} // namespace + +} // namespace autofill::payments
diff --git a/components/bookmarks/browser/bookmark_model_unittest.cc b/components/bookmarks/browser/bookmark_model_unittest.cc index c9173f3c..8b23124 100644 --- a/components/bookmarks/browser/bookmark_model_unittest.cc +++ b/components/bookmarks/browser/bookmark_model_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/bookmarks/browser/bookmark_model.h"
diff --git a/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc b/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc index 38b01cf..7eea636 100644 --- a/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc +++ b/components/breadcrumbs/core/breadcrumb_persistent_storage_manager.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/breadcrumbs/core/breadcrumb_persistent_storage_manager.h"
diff --git a/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/AsyncNotificationManagerProxyImpl.java b/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/AsyncNotificationManagerProxyImpl.java index 7e8db98..11465898 100644 --- a/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/AsyncNotificationManagerProxyImpl.java +++ b/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/AsyncNotificationManagerProxyImpl.java
@@ -17,7 +17,6 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.NullUnmarked; import org.chromium.build.annotations.Nullable; -import org.chromium.components.browser_ui.notifications.NotificationProxyUtils.NotificationEvent; import java.util.ArrayList; import java.util.Collections; @@ -177,15 +176,9 @@ AsyncTask.SERIAL_EXECUTOR.execute( () -> { try (TraceEvent te = TraceEvent.scoped(eventName)) { - NotificationProxyUtils.recordNotificationEventHistogram( - NotificationEvent.NO_CALLBACK_START); runnable.run(); - NotificationProxyUtils.recordNotificationEventHistogram( - NotificationEvent.NO_CALLBACK_SUCCESS); } catch (Exception e) { Log.e(TAG, "unable to run a runnable.", e); - NotificationProxyUtils.recordNotificationEventHistogram( - NotificationEvent.NO_CALLBACK_FAILED); } }); } @@ -202,8 +195,6 @@ @Override protected @Nullable T doInBackground() { try (TraceEvent te = TraceEvent.scoped(eventName)) { - NotificationProxyUtils.recordNotificationEventHistogram( - NotificationEvent.HAS_CALLBACK_START); return callable.call(); } catch (Exception e) { Log.e(TAG, "Unable to call method.", e); @@ -213,10 +204,6 @@ @Override protected void onPostExecute(@Nullable T result) { - NotificationProxyUtils.recordNotificationEventHistogram( - result == null - ? NotificationEvent.HAS_CALLBACK_FAILED - : NotificationEvent.HAS_CALLBACK_SUCCESS); callback.onResult(result); } }.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
diff --git a/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/NotificationManagerProxyImpl.java b/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/NotificationManagerProxyImpl.java index 280b91b..3dc7e0354 100644 --- a/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/NotificationManagerProxyImpl.java +++ b/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/NotificationManagerProxyImpl.java
@@ -22,7 +22,6 @@ import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.NullUnmarked; import org.chromium.build.annotations.Nullable; -import org.chromium.components.browser_ui.notifications.NotificationProxyUtils.NotificationEvent; import java.util.ArrayList; import java.util.Collections; @@ -253,15 +252,9 @@ /** Helper method to run an runnable inside a scoped event. */ private void runRunnable(@Nullable TraceEvent scopedEvent, Runnable runnable) { try (scopedEvent) { - NotificationProxyUtils.recordNotificationEventHistogram( - NotificationEvent.NO_CALLBACK_START); runnable.run(); - NotificationProxyUtils.recordNotificationEventHistogram( - NotificationEvent.NO_CALLBACK_SUCCESS); } catch (Exception e) { Log.e(TAG, "unable to run a runnable.", e); - NotificationProxyUtils.recordNotificationEventHistogram( - NotificationEvent.NO_CALLBACK_FAILED); } } @@ -276,18 +269,12 @@ Callback<T> callback, T defaultValue) { T result; - @NotificationEvent int event; try (scopedEvent) { - NotificationProxyUtils.recordNotificationEventHistogram( - NotificationEvent.HAS_CALLBACK_START); result = callable.call(); - event = NotificationEvent.HAS_CALLBACK_SUCCESS; } catch (Exception e) { Log.e(TAG, "Unable to call method.", e); - event = NotificationEvent.HAS_CALLBACK_FAILED; result = defaultValue; } - NotificationProxyUtils.recordNotificationEventHistogram(event); T finalResult = result; PostTask.postTask(TaskTraits.UI_DEFAULT, () -> callback.onResult(finalResult)); }
diff --git a/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/NotificationProxyUtils.java b/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/NotificationProxyUtils.java index 2084d8e..409228f 100644 --- a/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/NotificationProxyUtils.java +++ b/components/browser_ui/notifications/android/java/src/org/chromium/components/browser_ui/notifications/NotificationProxyUtils.java
@@ -6,18 +6,13 @@ import android.os.Build; -import androidx.annotation.IntDef; import androidx.core.app.NotificationManagerCompat; import org.chromium.base.ContextUtils; import org.chromium.base.ResettersForTesting; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - /** * Base interface for NofificationManagerProxy that only supports simple functionalities. Remove * this once AsyncNofificationManagerProxy is set to default. @@ -27,32 +22,6 @@ private static @Nullable Boolean sAreNotificationsEnabled; private static @Nullable Boolean sAreNotificationsEnabledForTest; - /** Defines the notification event */ - @IntDef({ - NotificationEvent.NO_CALLBACK_START, - NotificationEvent.NO_CALLBACK_SUCCESS, - NotificationEvent.NO_CALLBACK_FAILED, - NotificationEvent.HAS_CALLBACK_START, - NotificationEvent.HAS_CALLBACK_SUCCESS, - NotificationEvent.HAS_CALLBACK_FAILED, - NotificationEvent.COUNT - }) - @Retention(RetentionPolicy.SOURCE) - public @interface NotificationEvent { - int NO_CALLBACK_START = 0; /* A notification call without a callback started */ - int NO_CALLBACK_SUCCESS = 1; /* A notification call without a callback succeeded */ - int NO_CALLBACK_FAILED = 2; /* A notification call without a callback failed */ - int HAS_CALLBACK_START = 3; /* A notification call with a callback started */ - int HAS_CALLBACK_SUCCESS = 4; /* A notification call with a callback succeeded */ - int HAS_CALLBACK_FAILED = 5; /* A notification call with a callback failed */ - int COUNT = 6; - } - - public static void recordNotificationEventHistogram(@NotificationEvent int event) { - RecordHistogram.recordEnumeratedHistogram( - "Notifications.Android.NotificationEvent", event, NotificationEvent.COUNT); - } - /** Returns whether notifications are enabled for the app. */ public static boolean areNotificationsEnabled() { if (sAreNotificationsEnabledForTest != null) {
diff --git a/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/EmbeddableSettingsPage.java b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/EmbeddableSettingsPage.java index 809c4c1..322cb5b8 100644 --- a/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/EmbeddableSettingsPage.java +++ b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/EmbeddableSettingsPage.java
@@ -30,4 +30,11 @@ * <p>The activity will observe changes to this value and update the UI as necessary. */ ObservableSupplier<String> getPageTitle(); + + @Override + default @AnimationType int getAnimationType() { + // TODO(crbug.com/404074032): Each leaf subclass should override this method to use + // PROPERTY animation with auditing. + return AnimationType.TWEEN; + } }
diff --git a/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/SettingsFragment.java b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/SettingsFragment.java index 992751c..6fb44b83 100644 --- a/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/SettingsFragment.java +++ b/components/browser_ui/settings/android/java/src/org/chromium/components/browser_ui/settings/SettingsFragment.java
@@ -33,9 +33,5 @@ } /** Returns animation type to be used for fragment transition. */ - default @AnimationType int getAnimationType() { - // TODO(crbug.com/404074032): Each leaf subclass should override this method to use - // PROPERTY animation with auditing. - return AnimationType.TWEEN; - } + public @AnimationType int getAnimationType(); }
diff --git a/components/browser_ui/widget/android/BUILD.gn b/components/browser_ui/widget/android/BUILD.gn index 8eff26d..5030bd1 100644 --- a/components/browser_ui/widget/android/BUILD.gn +++ b/components/browser_ui/widget/android/BUILD.gn
@@ -74,6 +74,7 @@ "java/src/org/chromium/components/browser_ui/widget/dragreorder/DragStateDelegate.java", "java/src/org/chromium/components/browser_ui/widget/dragreorder/DragUtils.java", "java/src/org/chromium/components/browser_ui/widget/gesture/BackPressHandler.java", + "java/src/org/chromium/components/browser_ui/widget/gesture/OnSystemNavigationObserver.java", "java/src/org/chromium/components/browser_ui/widget/gesture/SwipeGestureListener.java", "java/src/org/chromium/components/browser_ui/widget/highlight/PulseDrawable.java", "java/src/org/chromium/components/browser_ui/widget/highlight/PulseInterpolator.java",
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/OnSystemNavigationObserver.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/OnSystemNavigationObserver.java new file mode 100644 index 0000000..57998e8 --- /dev/null +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/gesture/OnSystemNavigationObserver.java
@@ -0,0 +1,22 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.components.browser_ui.widget.gesture; + +import org.chromium.build.annotations.NullMarked; + +/** Observer of the system navigation. */ +@NullMarked +public interface OnSystemNavigationObserver { + /** + * Invoked when a back navigation event is handled by the Android OS itself, rather than by a + * specific in-app feature (see {@link BackPressHandler}). This typically occurs when the app is + * about to minimize or close. This callback is intended primary for logging and recording + * purposes and must not be used for any heavy task. + * + * <p>All registered observers will be called and so any two observers should be mutually + * exclusive. + */ + void onSystemNavigation(); +}
diff --git a/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc b/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc index 6a8232b9..0b31cb6 100644 --- a/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc +++ b/components/gcm_driver/crypto/gcm_message_cryptographer_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/gcm_driver/crypto/gcm_message_cryptographer.h"
diff --git a/components/gwp_asan/client/lightweight_detector/poison_metadata_recorder_unittest.cc b/components/gwp_asan/client/lightweight_detector/poison_metadata_recorder_unittest.cc index 1925b0e..fdb1b9c3 100644 --- a/components/gwp_asan/client/lightweight_detector/poison_metadata_recorder_unittest.cc +++ b/components/gwp_asan/client/lightweight_detector/poison_metadata_recorder_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/gwp_asan/client/lightweight_detector/poison_metadata_recorder.h"
diff --git a/components/omnibox/browser/BUILD.gn b/components/omnibox/browser/BUILD.gn index 7ccab5d..216c56c 100644 --- a/components/omnibox/browser/BUILD.gn +++ b/components/omnibox/browser/BUILD.gn
@@ -161,6 +161,7 @@ "autocomplete_controller_emitter.h", "autocomplete_controller_metrics.cc", "autocomplete_controller_metrics.h", + "autocomplete_enums.h", "autocomplete_grouper_groups.cc", "autocomplete_grouper_groups.h", "autocomplete_grouper_sections.cc",
diff --git a/components/omnibox/browser/autocomplete_controller.cc b/components/omnibox/browser/autocomplete_controller.cc index c9fc066d..dc8eefa 100644 --- a/components/omnibox/browser/autocomplete_controller.cc +++ b/components/omnibox/browser/autocomplete_controller.cc
@@ -45,6 +45,7 @@ #include "components/omnibox/browser/actions/omnibox_action_in_suggest.h" #include "components/omnibox/browser/actions/omnibox_answer_action.h" #include "components/omnibox/browser/actions/omnibox_pedal_provider.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_type.h" @@ -356,7 +357,7 @@ } // namespace AutocompleteController::OldResult::OldResult(UpdateType update_type, - AutocompleteInput input, + const AutocompleteInput& input, AutocompleteResult* result) { if (result->default_match()) { last_default_match = *result->default_match(); @@ -612,15 +613,11 @@ AutocompleteController::~AutocompleteController() { base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( this); - - // The providers may have tasks outstanding that hold refs to them. We need - // to ensure they won't call us back if they outlive us. (Practically, - // calling Stop() should also cancel those tasks and make it so that we hold - // the only refs.) We also don't want to bother notifying anyone of our - // result changes here, because the notification observer is in the midst of - // shutdown too, so we don't ask Stop() to clear `internal_result_` (and - // notify). - Stop(false); + // Must stop providers because they may have unowned tasks that continue to + // run or hold refs to them; e.g. remote requests or DB reads. Don't bother + // notifying observers or using `kClobbered` to clear provider caches and + // state, since the observers and providers are being destroyed too. + Stop(AutocompleteStopReason::kInteraction); } void AutocompleteController::AddObserver(Observer* observer) { @@ -772,7 +769,7 @@ // Avoid starting a prefetch request if a non-prefetch request is in // progress. Though explicitly discouraged as per documentation in - // AutocompleteProvider::StartPrefetch(), a provider may still cancel its + // `AutocompleteProvider::StartPrefetch()`, a provider may still cancel its // in-flight non-prefetch request when a prefetch request is started. This // may cause the provider to never get a chance to notify the controller of // its status; resulting in the controller to remain in an invalid state. @@ -785,8 +782,7 @@ } } -void AutocompleteController::Stop(bool clear_result, - bool due_to_user_inactivity) { +void AutocompleteController::Stop(AutocompleteStopReason stop_reason) { // Must be called before `expire_timer_.Stop()`, modifying `done_`, or // modifying `AutocompleteProvider::done_` below. If the current request has // not completed, and therefore has not been logged yet, will log it now. @@ -797,17 +793,16 @@ for (const auto& provider : providers_) { if (!ShouldRunProvider(provider.get())) continue; - provider->Stop(clear_result, due_to_user_inactivity); + provider->Stop(stop_reason); } - UpdateResult(UpdateType::kStop); - // Cancel any pending requests that may update the results. Otherwise, e.g., // the user's suggestion selection may be reset. + UpdateResult(UpdateType::kStop); CancelNotifyChangedRequest(); const bool non_empty_result = !internal_result_.empty(); - if (clear_result) { + if (stop_reason == AutocompleteStopReason::kClobbered) { internal_result_.Reset(); if (non_empty_result) { // Pass `notify_default_match` as false to clear only the popup and not @@ -2128,7 +2123,7 @@ } void AutocompleteController::OnStopTimerTriggered() { - Stop(false, true); + Stop(AutocompleteStopReason::kInactivity); for (Observer& obs : observers_) { obs.OnAutocompleteStopTimerTriggered(input_); }
diff --git a/components/omnibox/browser/autocomplete_controller.h b/components/omnibox/browser/autocomplete_controller.h index 9423d8e..8eba8dd 100644 --- a/components/omnibox/browser/autocomplete_controller.h +++ b/components/omnibox/browser/autocomplete_controller.h
@@ -23,6 +23,7 @@ #include "base/trace_event/memory_dump_provider.h" #include "build/build_config.h" #include "components/omnibox/browser/autocomplete_controller_metrics.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/autocomplete_provider_client.h" @@ -206,12 +207,11 @@ // Made virtual for mocking in tests. virtual void StartPrefetch(const AutocompleteInput& input); - // Cancels the current query, ensuring there will be no future notifications - // fired. If new matches have come in since the most recent notification was - // fired, they will be discarded. If `clear_result` is true, the controller - // will also erase the result set. `due_to_user_inactivity` means this call - // was triggered by a user's idleness, i.e., not an explicit user action. - void Stop(bool clear_result, bool due_to_user_inactivity = false); + // Cancels the current query, ensuring most future updates won't fire + // notifications. If new matches have come in since the most recent + // notification was fired, they may be discarded. See + // `AutocompleteProvider::Stop()` & `AutocompleteStopReason`. + void Stop(AutocompleteStopReason stop_reason); // Asks the relevant provider to delete |match|, and ensures observers are // notified of resulting changes immediately. This should only be called when @@ -400,7 +400,7 @@ // `UpdateResult()`'s helper methods. struct OldResult { OldResult(UpdateType update_type, - AutocompleteInput input, + const AutocompleteInput& input, AutocompleteResult* result); ~OldResult();
diff --git a/components/omnibox/browser/autocomplete_controller_metrics_unittest.cc b/components/omnibox/browser/autocomplete_controller_metrics_unittest.cc index 70cdb4e..7d39bf4 100644 --- a/components/omnibox/browser/autocomplete_controller_metrics_unittest.cc +++ b/components/omnibox/browser/autocomplete_controller_metrics_unittest.cc
@@ -17,6 +17,7 @@ #include "base/test/task_environment.h" #include "base/time/time.h" #include "components/omnibox/browser/autocomplete_controller.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_result.h" #include "components/omnibox/browser/fake_autocomplete_controller.h" #include "components/omnibox/browser/fake_autocomplete_provider.h" @@ -116,7 +117,7 @@ // Simulates `AutocompleteController::Stop()`. void SimulateOnStop() { task_environment_.FastForwardBy(base::Milliseconds(1)); - controller_.Stop(false); + controller_.Stop(AutocompleteStopReason::kInteraction); } // Convenience function to be called before/after EXPECT'ing histograms to @@ -132,7 +133,7 @@ // when the controller is interrupted in which case metrics are expected to be // logged. Does not check provider or cross stability metrics. void StopAndExpectNoSuggestionFinalizationMetrics() { - controller_.Stop(false, false); + controller_.Stop(AutocompleteStopReason::kClobbered); ExpectNoSuggestionFinalizationMetrics(); }
diff --git a/components/omnibox/browser/autocomplete_controller_unittest.cc b/components/omnibox/browser/autocomplete_controller_unittest.cc index c46c4e5..c5ab43f 100644 --- a/components/omnibox/browser/autocomplete_controller_unittest.cc +++ b/components/omnibox/browser/autocomplete_controller_unittest.cc
@@ -19,6 +19,7 @@ #include "build/build_config.h" #include "components/omnibox/browser/actions/omnibox_answer_action.h" #include "components/omnibox/browser/autocomplete_controller.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_test_util.h" #include "components/omnibox/browser/autocomplete_match_type.h" @@ -740,7 +741,7 @@ } { SCOPED_TRACE("Stop with clear_result=false is called due to user idleness"); - controller_.Stop(/*clear_result=*/false); + controller_.Stop(AutocompleteStopReason::kInteraction); // Stop with clear_result=false does not clear the internal result set and // does not notify `OnResultChanged()`. EXPECT_FALSE(controller_.internal_result_.empty()); @@ -799,7 +800,7 @@ } { SCOPED_TRACE("Stop with clear_result=true is called due to popup closing"); - controller_.Stop(/*clear_result=*/true); + controller_.Stop(AutocompleteStopReason::kClobbered); // Stop with clear_result=true clears the internal result set and notifies // `OnResultChanged()`. EXPECT_TRUE(controller_.internal_result_.empty()); @@ -1875,34 +1876,34 @@ { SCOPED_TRACE( - "Stop with clear_result=false and no pending changes should not notify" + "Stop with `kInteraction` and no pending changes should not notify " "`OnResultChanged()` - there's no change to notify of."); controller_.SimulateAutocompletePass(true, false, matches); - controller_.Stop(false); + controller_.Stop(AutocompleteStopReason::kInteraction); controller_.ExpectStopAfter(0, true); EXPECT_FALSE(controller_.published_result_.empty()); controller_.ExpectNoNotificationOrStop(); } { SCOPED_TRACE( - "Stop with clear_result=false and pending changes should not notify" - "`OnResultChanged()` - the last pending change should be abandoned to " - "avoid changes as the user's e.g. down arrowing.."); + "Stop with `kInteraction` and pending changes should not notify " + "`OnResultChanged()` - the last pending change should be " + "abandoned to avoid changes as the user's e.g. down arrowing."); controller_.SimulateAutocompletePass(true, false, matches); controller_.SimulateAutocompletePass(false, false, matches); - controller_.Stop(false); + controller_.Stop(AutocompleteStopReason::kInteraction); EXPECT_FALSE(controller_.published_result_.empty()); controller_.ExpectStopAfter(0, true); controller_.ExpectNoNotificationOrStop(); } { SCOPED_TRACE( - "Stop with clear_result=true and no pending notifications should " - "notify `OnResultChanged()` - observers should know the results were " + "Stop with `kClobbered` and no pending notifications should notify " + "`OnResultChanged()` - observers should know the results were " "cleared."); controller_.SimulateAutocompletePass(true, false, matches); controller_.observer_->last_default_match_changed = true; - controller_.Stop(true); + controller_.Stop(AutocompleteStopReason::kClobbered); EXPECT_TRUE(controller_.published_result_.empty()); controller_.ExpectOnResultChanged( 0, AutocompleteController::UpdateType::kStop); @@ -1911,13 +1912,13 @@ } { SCOPED_TRACE( - "Stop with clear_result=true and pending notifications should notify " - "`OnResultChanged()` - observers should know the results were " + "Stop with `kClobbered` and pending notifications should notify " + "`OnResultChanged()` - observers should know the results were cleared." "cleared."); controller_.SimulateAutocompletePass(true, false, matches); controller_.SimulateAutocompletePass(false, false, matches); controller_.observer_->last_default_match_changed = true; - controller_.Stop(true); + controller_.Stop(AutocompleteStopReason::kClobbered); EXPECT_TRUE(controller_.published_result_.empty()); controller_.ExpectOnResultChanged( 0, AutocompleteController::UpdateType::kStop); @@ -2445,7 +2446,7 @@ AutocompleteMatch match1 = CreateSearchMatch("match1", true, 1300); match1.actions.push_back(answer_action); - controller_.Stop(true); + controller_.Stop(AutocompleteStopReason::kClobbered); EXPECT_THAT(controller_.SimulateAutocompletePass( /*sync=*/true, /*done=*/true, {match1, CreateSearchMatch("match2", true, 1200), @@ -2561,11 +2562,11 @@ controller_.AttachActions(); // The takeover action should be for the contextual search action, not pedals. - EXPECT_TRUE(controller_.internal_result_.match_at(0)->takeover_action); + ASSERT_TRUE(controller_.internal_result_.match_at(0)->takeover_action); EXPECT_EQ( OmniboxActionId::CONTEXTUAL_SEARCH_FULFILLMENT, controller_.internal_result_.match_at(0)->takeover_action->ActionId()); - EXPECT_TRUE(controller_.internal_result_.match_at(1)->takeover_action); + ASSERT_TRUE(controller_.internal_result_.match_at(1)->takeover_action); EXPECT_EQ( OmniboxActionId::CONTEXTUAL_SEARCH_FULFILLMENT, controller_.internal_result_.match_at(1)->takeover_action->ActionId()); @@ -2619,11 +2620,11 @@ EXPECT_FALSE(controller_.internal_result_.match_at(0)->takeover_action); EXPECT_FALSE(controller_.internal_result_.match_at(3)->takeover_action); - EXPECT_TRUE(controller_.internal_result_.match_at(1)->takeover_action); + ASSERT_TRUE(controller_.internal_result_.match_at(1)->takeover_action); EXPECT_EQ( OmniboxActionId::CONTEXTUAL_SEARCH_FULFILLMENT, controller_.internal_result_.match_at(1)->takeover_action->ActionId()); - EXPECT_TRUE(controller_.internal_result_.match_at(2)->takeover_action); + ASSERT_TRUE(controller_.internal_result_.match_at(2)->takeover_action); EXPECT_EQ( OmniboxActionId::CONTEXTUAL_SEARCH_FULFILLMENT, controller_.internal_result_.match_at(2)->takeover_action->ActionId());
diff --git a/components/omnibox/browser/autocomplete_enums.h b/components/omnibox/browser/autocomplete_enums.h new file mode 100644 index 0000000..e88bdfc --- /dev/null +++ b/components/omnibox/browser/autocomplete_enums.h
@@ -0,0 +1,38 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_ENUMS_H_ +#define COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_ENUMS_H_ + +// The reason `AutocompleteController::Stop()` or `AutocompleteProvider::Stop()` +// were called. +enum class AutocompleteStopReason { + + // - Called when: Significant change occurred and the existing state is no + // longer useful. + // - Action taken: Stop all providers and clear results. + // - Example calls: The omnibox popup is closed or when some providers + // `Start()`. + kClobbered, + + // - Called when: Omnibox was interacted with in a way that requires its state + // to be frozen. + // - Action taken: Stop all providers and keep results. + // - Example calls: Entered/left keyword mode, arrowed down through + // suggestions, arrowed left through text, match deleted , or when some + // providers `Start()`. + kInteraction, + + // - Called when: User hasn't interacted with the omnibox for a while. See + // `AutocompleteController::stop_timer_duration_` comment. + // - Action taken: Stop most providers and keep results. Some providers are + // allowed to continue if there's a good reason the user is likely to want + // even long-delayed asynchronous results, e.g. the user has explicitly + // invoked a keyword extension and the extension is still processing the + // request. + // - Example calls: `stop_timer_` triggers. + kInactivity, +}; + +#endif // COMPONENTS_OMNIBOX_BROWSER_AUTOCOMPLETE_ENUMS_H_
diff --git a/components/omnibox/browser/autocomplete_input.cc b/components/omnibox/browser/autocomplete_input.cc index d0026474..5534ab7b 100644 --- a/components/omnibox/browser/autocomplete_input.cc +++ b/components/omnibox/browser/autocomplete_input.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/omnibox/browser/autocomplete_input.h"
diff --git a/components/omnibox/browser/autocomplete_provider.cc b/components/omnibox/browser/autocomplete_provider.cc index 1b4d7e3b5..c9bf366 100644 --- a/components/omnibox/browser/autocomplete_provider.cc +++ b/components/omnibox/browser/autocomplete_provider.cc
@@ -18,6 +18,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/trace_event/memory_usage_estimator.h" #include "components/bookmarks/browser/bookmark_utils.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_i18n.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" @@ -138,10 +139,9 @@ DCHECK(!input.omit_asynchronous_matches()); } -void AutocompleteProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { +void AutocompleteProvider::Stop(AutocompleteStopReason stop_reason) { done_ = true; - if (clear_cached_results) { + if (stop_reason == AutocompleteStopReason::kClobbered) { matches_.clear(); suggestion_groups_map_.clear(); } @@ -239,7 +239,9 @@ } AutocompleteProvider::~AutocompleteProvider() { - Stop(false, false); + // Don't bother using `kClobbered` to clear caches and state, since those will + // be destroyed with the provider. + Stop(AutocompleteStopReason::kInteraction); } // static
diff --git a/components/omnibox/browser/autocomplete_provider.h b/components/omnibox/browser/autocomplete_provider.h index d3d3db6..ae24c62 100644 --- a/components/omnibox/browser/autocomplete_provider.h +++ b/components/omnibox/browser/autocomplete_provider.h
@@ -15,6 +15,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/in_memory_url_index_types.h" #include "components/omnibox/browser/suggestion_group_util.h" @@ -249,25 +250,12 @@ // AutocompleteController::Start(). virtual void Start(const AutocompleteInput& input, bool minimal_changes) = 0; - // Advises the provider to stop processing. This may be called even if the - // provider is already done. If the provider caches any results, it should - // clear the cache based on the value of `clear_cached_results`. Normally, - // once this is called, the provider should not send more notifications to - // the controller. - // - // If `user_inactivity_timer` is true, Stop() is being called because it's - // been a long time since the user started the current query, and returning - // further asynchronous results would normally just be disruptive. Most - // providers should still stop processing in this case, but continuing is - // legal if there's a good reason the user is likely to want even long- - // delayed asynchronous results, e.g. the user has explicitly invoked a - // keyword extension and the extension is still processing the request. - // - // The default implementation sets `done_` to true and clears `matches_` if - // `clear_cached_results` is true. Overridden functions must call - // `AutocompleteProvider::Stop()` with the same arguments passed to the - // function. - virtual void Stop(bool clear_cached_results, bool due_to_user_inactivity); + // Advises the provider to stop processing. This may be called even if the + // provider is already done. Normally, once this is called, the provider + // should not send more notifications to the controller. Overridden functions + // must call `AutocompleteProvider::Stop()` with the same `stop_reason` passed + // to the function. + virtual void Stop(AutocompleteStopReason stop_reason); // Returns the enum equivalent to the name of this provider. // TODO(derat): Make metrics use AutocompleteProvider::Type directly, or at
diff --git a/components/omnibox/browser/bookmark_provider_unittest.cc b/components/omnibox/browser/bookmark_provider_unittest.cc index b1e8ff4..5823e7a 100644 --- a/components/omnibox/browser/bookmark_provider_unittest.cc +++ b/components/omnibox/browser/bookmark_provider_unittest.cc
@@ -8,10 +8,6 @@ #include "components/query_parser/query_parser.h" #include "third_party/omnibox_proto/groups.pb.h" -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include <stddef.h>
diff --git a/components/omnibox/browser/calculator_provider.cc b/components/omnibox/browser/calculator_provider.cc index f8894e5..0d0a348 100644 --- a/components/omnibox/browser/calculator_provider.cc +++ b/components/omnibox/browser/calculator_provider.cc
@@ -64,11 +64,6 @@ } } -void CalculatorProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - done_ = true; -} - void CalculatorProvider::DeleteMatch(const AutocompleteMatch& match) { auto it = std::ranges::find_if(Cache(), [&](const auto& cached) { return cached.match.destination_url == match.destination_url;
diff --git a/components/omnibox/browser/calculator_provider.h b/components/omnibox/browser/calculator_provider.h index 3902597..b9abbc5f 100644 --- a/components/omnibox/browser/calculator_provider.h +++ b/components/omnibox/browser/calculator_provider.h
@@ -48,7 +48,6 @@ // AutocompleteProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; void DeleteMatch(const AutocompleteMatch& match) override; // AutocompleteProviderListener:
diff --git a/components/omnibox/browser/clipboard_provider.cc b/components/omnibox/browser/clipboard_provider.cc index a6320c3..7f7f11b 100644 --- a/components/omnibox/browser/clipboard_provider.cc +++ b/components/omnibox/browser/clipboard_provider.cc
@@ -21,6 +21,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/task/thread_pool.h" #include "build/build_config.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_provider_client.h" @@ -198,10 +199,8 @@ } } -void ClipboardProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); - +void ClipboardProvider::Stop(AutocompleteStopReason stop_reason) { + AutocompleteProvider::Stop(stop_reason); callback_weak_ptr_factory_.InvalidateWeakPtrs(); }
diff --git a/components/omnibox/browser/clipboard_provider.h b/components/omnibox/browser/clipboard_provider.h index ea1b2cf..9daf7ebf 100644 --- a/components/omnibox/browser/clipboard_provider.h +++ b/components/omnibox/browser/clipboard_provider.h
@@ -7,6 +7,7 @@ #include "base/gtest_prod_util.h" #include "base/memory/raw_ptr.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_provider.h" class AutocompleteProviderClient; @@ -49,7 +50,7 @@ // AutocompleteProvider implementation. void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; void DeleteMatch(const AutocompleteMatch& match) override; void AddProviderInfo(ProvidersInfo* provider_info) const override;
diff --git a/components/omnibox/browser/contextual_search_provider.cc b/components/omnibox/browser/contextual_search_provider.cc index e02e01d5..72d4d97 100644 --- a/components/omnibox/browser/contextual_search_provider.cc +++ b/components/omnibox/browser/contextual_search_provider.cc
@@ -23,6 +23,7 @@ #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "components/omnibox/browser/actions/contextual_search_action.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" @@ -92,7 +93,7 @@ TRACE_EVENT0("omnibox", "ContextualSearchProvider::Start"); // Clear the cached results to remove the page search action matches. Also, // matches the behavior of the `ZeroSuggestProvider`. - Stop(/*clear_cached_results=*/true, /*due_to_user_inactivity=*/false); + Stop(AutocompleteStopReason::kClobbered); if (client()->IsOffTheRecord()) { done_ = true; @@ -128,17 +129,16 @@ StartSuggestRequest(std::move(input)); } -void ContextualSearchProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - if (!due_to_user_inactivity) { - // Stop the pending request if the sotp is not due to user inactivity. If - // it is due to user inactivity, the request will continue so the - // suggestions can be shown when they are ready. - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); - lens_suggest_inputs_subscription_ = {}; - loader_.reset(); - input_keyword_.clear(); +void ContextualSearchProvider::Stop(AutocompleteStopReason stop_reason) { + // If the stop is due to user inactivity, the request will continue so the + // suggestions can be shown when they are ready. + if (stop_reason == AutocompleteStopReason::kInactivity) { + return; } + AutocompleteProvider::Stop(stop_reason); + lens_suggest_inputs_subscription_ = {}; + loader_.reset(); + input_keyword_.clear(); } void ContextualSearchProvider::AddProviderInfo(
diff --git a/components/omnibox/browser/contextual_search_provider.h b/components/omnibox/browser/contextual_search_provider.h index eafd703..9b9fab31 100644 --- a/components/omnibox/browser/contextual_search_provider.h +++ b/components/omnibox/browser/contextual_search_provider.h
@@ -9,6 +9,7 @@ #include <string> #include "base/callback_list.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/base_search_provider.h" @@ -34,7 +35,7 @@ // AutocompleteProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; void AddProviderInfo(ProvidersInfo* provider_info) const override; protected:
diff --git a/components/omnibox/browser/document_provider.cc b/components/omnibox/browser/document_provider.cc index 38f1973..134d80e 100644 --- a/components/omnibox/browser/document_provider.cc +++ b/components/omnibox/browser/document_provider.cc
@@ -31,6 +31,7 @@ #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" #include "base/values.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" @@ -478,8 +479,7 @@ void DocumentProvider::Start(const AutocompleteInput& input, bool minimal_changes) { TRACE_EVENT0("omnibox", "DocumentProvider::Start"); - Stop(true, false); - + Stop(AutocompleteStopReason::kClobbered); // Perform various checks - feature is enabled, user is allowed to use the // feature, we're not under backoff, etc. if (!IsDocumentProviderAllowed(input)) @@ -517,10 +517,9 @@ base::Unretained(this) /* this owns SimpleURLLoader */)); } -void DocumentProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { +void DocumentProvider::Stop(AutocompleteStopReason stop_reason) { TRACE_EVENT0("omnibox", "DocumentProvider::Stop"); - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); + AutocompleteProvider::Stop(stop_reason); debouncer_->CancelRequest();
diff --git a/components/omnibox/browser/document_provider.h b/components/omnibox/browser/document_provider.h index a99ac841..e683c47 100644 --- a/components/omnibox/browser/document_provider.h +++ b/components/omnibox/browser/document_provider.h
@@ -20,6 +20,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/time/time.h" #include "components/history/core/browser/history_types.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/autocomplete_provider_debouncer.h" #include "third_party/metrics_proto/omnibox_event.pb.h" @@ -48,7 +49,7 @@ // AutocompleteProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; void DeleteMatch(const AutocompleteMatch& match) override; void AddProviderInfo(ProvidersInfo* provider_info) const override;
diff --git a/components/omnibox/browser/document_provider_unittest.cc b/components/omnibox/browser/document_provider_unittest.cc index 1eadf43..85501d6 100644 --- a/components/omnibox/browser/document_provider_unittest.cc +++ b/components/omnibox/browser/document_provider_unittest.cc
@@ -24,6 +24,7 @@ #include "base/values.h" #include "build/blink_buildflags.h" #include "build/build_config.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match_type.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" @@ -1042,7 +1043,7 @@ { SCOPED_TRACE("Case: Stop() before Run()."); base::HistogramTester histogram_tester; - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kClobbered); histogram_tester.ExpectTotalCount("Omnibox.DocumentSuggest.Requests", 0); histogram_tester.ExpectTotalCount("Omnibox.DocumentSuggest.TotalTime", 0); histogram_tester.ExpectTotalCount( @@ -1060,7 +1061,7 @@ SCOPED_TRACE("Case: Stop() before request."); base::HistogramTester histogram_tester; provider_->time_run_invoked_ = base::TimeTicks::Now(); - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kClobbered); histogram_tester.ExpectTotalCount("Omnibox.DocumentSuggest.Requests", 0); histogram_tester.ExpectTotalCount("Omnibox.DocumentSuggest.TotalTime", 1); histogram_tester.ExpectTotalCount( @@ -1082,7 +1083,7 @@ network::SimpleURLLoader::Create( std::make_unique<network::ResourceRequest>(), net::DefineNetworkTrafficAnnotation("test", "test"))); - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kClobbered); histogram_tester.ExpectTotalCount("Omnibox.DocumentSuggest.Requests", 2); histogram_tester.ExpectBucketCount("Omnibox.DocumentSuggest.Requests", 1, 1);
diff --git a/components/omnibox/browser/enterprise_search_aggregator_provider.cc b/components/omnibox/browser/enterprise_search_aggregator_provider.cc index 34a38f8..11b1d42 100644 --- a/components/omnibox/browser/enterprise_search_aggregator_provider.cc +++ b/components/omnibox/browser/enterprise_search_aggregator_provider.cc
@@ -28,6 +28,7 @@ #include "base/time/time.h" #include "base/types/expected.h" #include "base/values.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" @@ -437,8 +438,7 @@ bool minimal_changes) { // Don't clear matches. Keep showing old matches until a new response comes. // This avoids flickering. - Stop(/*clear_cached_results=*/false, - /*due_to_user_inactivity=*/false); + Stop(AutocompleteStopReason::kInteraction); if (!IsProviderAllowed(input)) { // Clear old matches if provider is not allowed. @@ -480,24 +480,25 @@ &EnterpriseSearchAggregatorProvider::Run, base::Unretained(this))); } -void EnterpriseSearchAggregatorProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - // Ignore the stop timer since this provider is expected to take longer than - // 1500ms (the stop timer gets triggered due to user inactivity). - if (!due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); - debouncer_->CancelRequest(); +void EnterpriseSearchAggregatorProvider::Stop( + AutocompleteStopReason stop_reason) { + // Ignore the stop timer since this provider is expected to sometimes take + // longer than 1500ms. + if (stop_reason == AutocompleteStopReason::kInactivity) { + return; + } + AutocompleteProvider::Stop(stop_reason); + debouncer_->CancelRequest(); - if (auto* remote_suggestions_service = client_->GetRemoteSuggestionsService( - /*create_if_necessary=*/false)) { - remote_suggestions_service - ->StopCreatingEnterpriseSearchAggregatorSuggestionsRequest(); - } + if (auto* remote_suggestions_service = client_->GetRemoteSuggestionsService( + /*create_if_necessary=*/false)) { + remote_suggestions_service + ->StopCreatingEnterpriseSearchAggregatorSuggestionsRequest(); + } - if (loader_) { - LogResponseTime(true); - loader_.reset(); - } + if (loader_) { + LogResponseTime(true); + loader_.reset(); } }
diff --git a/components/omnibox/browser/enterprise_search_aggregator_provider.h b/components/omnibox/browser/enterprise_search_aggregator_provider.h index bb8d6559..ace7108 100644 --- a/components/omnibox/browser/enterprise_search_aggregator_provider.h +++ b/components/omnibox/browser/enterprise_search_aggregator_provider.h
@@ -16,6 +16,7 @@ #include "base/time/time.h" #include "base/types/expected.h" #include "base/values.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/autocomplete_provider_client.h" @@ -48,7 +49,7 @@ // AutocompleteProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; private: friend class FakeEnterpriseSearchAggregatorProvider;
diff --git a/components/omnibox/browser/enterprise_search_aggregator_provider_unittest.cc b/components/omnibox/browser/enterprise_search_aggregator_provider_unittest.cc index 9e5c8cb8..92168c1 100644 --- a/components/omnibox/browser/enterprise_search_aggregator_provider_unittest.cc +++ b/components/omnibox/browser/enterprise_search_aggregator_provider_unittest.cc
@@ -20,6 +20,7 @@ #include "base/test/task_environment.h" #include "base/test/test_future.h" #include "base/time/time.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_type.h" @@ -1669,7 +1670,7 @@ { SCOPED_TRACE("Case: Stop() before Run()."); base::HistogramTester histogram_tester; - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kClobbered); histogram_tester.ExpectTotalCount( "Omnibox.SuggestRequestsSent.ResponseTime2.RequestState." "EnterpriseSearchAggregatorSuggest.Interrupted", @@ -1687,7 +1688,7 @@ provider_->RequestStarted(network::SimpleURLLoader::Create( std::make_unique<network::ResourceRequest>(), net::DefineNetworkTrafficAnnotation("test", "test"))); - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kClobbered); histogram_tester.ExpectTotalCount( "Omnibox.SuggestRequestsSent.ResponseTime2.RequestState." "EnterpriseSearchAggregatorSuggest.Interrupted",
diff --git a/components/omnibox/browser/featured_search_provider_unittest.cc b/components/omnibox/browser/featured_search_provider_unittest.cc index cd7cb89..450f5df6 100644 --- a/components/omnibox/browser/featured_search_provider_unittest.cc +++ b/components/omnibox/browser/featured_search_provider_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/omnibox/browser/featured_search_provider.h"
diff --git a/components/omnibox/browser/history_cluster_provider.cc b/components/omnibox/browser/history_cluster_provider.cc index 1d834289..2f4d955f 100644 --- a/components/omnibox/browser/history_cluster_provider.cc +++ b/components/omnibox/browser/history_cluster_provider.cc
@@ -13,15 +13,15 @@ #include "components/history_clusters/core/url_constants.h" #include "components/omnibox/browser/actions/history_clusters_action.h" #include "components/omnibox/browser/autocomplete_controller.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" #include "components/omnibox/browser/autocomplete_match_type.h" #include "components/omnibox/browser/autocomplete_provider.h" -#include "third_party/metrics_proto/omnibox_event.pb.h" - #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" #include "components/strings/grit/components_strings.h" +#include "third_party/metrics_proto/omnibox_event.pb.h" #include "ui/base/l10n/l10n_util.h" HistoryClusterProvider::HistoryClusterProvider( @@ -63,8 +63,7 @@ void HistoryClusterProvider::Start(const AutocompleteInput& input, bool minimal_changes) { - Stop(true, false); - + Stop(AutocompleteStopReason::kClobbered); if (input.omit_asynchronous_matches()) return;
diff --git a/components/omnibox/browser/history_embeddings_provider.cc b/components/omnibox/browser/history_embeddings_provider.cc index 85117cd..28b6f062 100644 --- a/components/omnibox/browser/history_embeddings_provider.cc +++ b/components/omnibox/browser/history_embeddings_provider.cc
@@ -16,6 +16,7 @@ #include "components/history_clusters/core/history_clusters_util.h" #include "components/history_embeddings/history_embeddings_features.h" #include "components/history_embeddings/history_embeddings_service.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" @@ -97,16 +98,15 @@ weak_factory_.GetWeakPtr())); } -void HistoryEmbeddingsProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { +void HistoryEmbeddingsProvider::Stop(AutocompleteStopReason stop_reason) { // TODO(crbug.com/364303536): Ignore the stop timer since we know answers take - // longer than 1500ms to generate. This inadvertently also ignores stops - // caused by user action. A real fix is for providers to inform the - // controller that they expect a slow response and the controller to - // accommodate it by updating its stop, debounce, and cache timers' - // behaviors. - if (!due_to_user_inactivity && !done_) { - done_ = true; + // longer than 1500ms to generate. + if (stop_reason == AutocompleteStopReason::kInactivity) { + return; + } + + // Erase the abandoned placeholder answer. + if (!done_) { size_t erased_count = std::erase_if(matches_, [&](const auto& match) { return match.type == AutocompleteMatchType::HISTORY_EMBEDDINGS_ANSWER; }); @@ -115,6 +115,8 @@ NotifyListeners(!matches_.empty()); } + AutocompleteProvider::Stop(stop_reason); + // TODO(b/333770460): Once `HistoryEmbeddingsService` has a stop API, we // should call it here. }
diff --git a/components/omnibox/browser/history_embeddings_provider.h b/components/omnibox/browser/history_embeddings_provider.h index c663255..523696a 100644 --- a/components/omnibox/browser/history_embeddings_provider.h +++ b/components/omnibox/browser/history_embeddings_provider.h
@@ -10,6 +10,7 @@ #include "base/memory/raw_ptr.h" #include "components/history_embeddings/history_embeddings_service.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/history_provider.h" @@ -23,7 +24,7 @@ // AutocompleteProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; private: friend class FakeHistoryEmbeddingsProvider;
diff --git a/components/omnibox/browser/history_embeddings_provider_unittest.cc b/components/omnibox/browser/history_embeddings_provider_unittest.cc index 50b45f2..a658d38 100644 --- a/components/omnibox/browser/history_embeddings_provider_unittest.cc +++ b/components/omnibox/browser/history_embeddings_provider_unittest.cc
@@ -25,6 +25,7 @@ #include "components/history_embeddings/history_embeddings_features.h" #include "components/history_embeddings/history_embeddings_service.h" #include "components/history_embeddings/mock_history_embeddings_service.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" @@ -360,7 +361,7 @@ history_embeddings_provider_->Start(CreateAutocompleteInput(u"1 1 1"), false); EXPECT_TRUE(last_update_matches_.empty()); - history_embeddings_provider_->Stop(false, false); + history_embeddings_provider_->Stop(AutocompleteStopReason::kClobbered); // Results returned after `Stop()` should be discarded. std::move(search_callbacks_[0]).Run("1 1 1", u"1"); @@ -372,10 +373,10 @@ // TODO(crbug.com/364303536) Temporarily allow history embeddings provider to // ignore `Stop()`. - history_embeddings_provider_->Stop(false, true); + history_embeddings_provider_->Stop(AutocompleteStopReason::kInactivity); EXPECT_FALSE(history_embeddings_provider_->done_); - history_embeddings_provider_->Stop(false, false); + history_embeddings_provider_->Stop(AutocompleteStopReason::kClobbered); EXPECT_TRUE(history_embeddings_provider_->done_); }
diff --git a/components/omnibox/browser/history_fuzzy_provider_unittest.cc b/components/omnibox/browser/history_fuzzy_provider_unittest.cc index 8bf62afe..abc5f96d 100644 --- a/components/omnibox/browser/history_fuzzy_provider_unittest.cc +++ b/components/omnibox/browser/history_fuzzy_provider_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/omnibox/browser/history_fuzzy_provider.h"
diff --git a/components/omnibox/browser/history_quick_provider_performance_unittest.cc b/components/omnibox/browser/history_quick_provider_performance_unittest.cc index a2cbc0af..2e94eba 100644 --- a/components/omnibox/browser/history_quick_provider_performance_unittest.cc +++ b/components/omnibox/browser/history_quick_provider_performance_unittest.cc
@@ -4,10 +4,6 @@ #include <array> -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include <algorithm> #include <memory>
diff --git a/components/omnibox/browser/history_url_provider.cc b/components/omnibox/browser/history_url_provider.cc index 4175bc9..299dd6ba 100644 --- a/components/omnibox/browser/history_url_provider.cc +++ b/components/omnibox/browser/history_url_provider.cc
@@ -29,6 +29,7 @@ #include "components/history/core/browser/history_database.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_types.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" #include "components/omnibox/browser/autocomplete_provider.h" @@ -423,8 +424,7 @@ // re-run the query from scratch and ignore `minimal_changes`. // Cancel any in-progress query. - Stop(true, false); - + Stop(AutocompleteStopReason::kClobbered); if (input.IsZeroSuggest() || (input.type() == metrics::OmniboxInputType::EMPTY)) { return; @@ -543,10 +543,8 @@ } } -void HistoryURLProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); - +void HistoryURLProvider::Stop(AutocompleteStopReason stop_reason) { + AutocompleteProvider::Stop(stop_reason); if (params_) params_->cancel_flag.Set(); }
diff --git a/components/omnibox/browser/history_url_provider.h b/components/omnibox/browser/history_url_provider.h index 9d60570..ab94125bb 100644 --- a/components/omnibox/browser/history_url_provider.h +++ b/components/omnibox/browser/history_url_provider.h
@@ -17,6 +17,7 @@ #include "base/memory/ref_counted.h" #include "base/synchronization/atomic_flag.h" #include "base/threading/thread_checker.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/history_match.h" #include "components/omnibox/browser/history_provider.h" @@ -211,7 +212,7 @@ // HistoryProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; // Estimates dynamic memory usage. // See base/trace_event/memory_usage_estimator.h for more info.
diff --git a/components/omnibox/browser/history_url_provider_unittest.cc b/components/omnibox/browser/history_url_provider_unittest.cc index 155a308..3e93e06 100644 --- a/components/omnibox/browser/history_url_provider_unittest.cc +++ b/components/omnibox/browser/history_url_provider_unittest.cc
@@ -28,6 +28,7 @@ #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/url_database.h" #include "components/history/core/test/history_service_test_util.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" @@ -1167,9 +1168,9 @@ // clang-format on }; for (size_t i = 0; i < std::size(test_cases); ++i) { - SCOPED_TRACE(testing::Message() << "Index " << i << " input: " - << test_cases[i].input << ", trim_http: " - << test_cases[i].trim_http); + SCOPED_TRACE(testing::Message() + << "Index " << i << " input: " << test_cases[i].input + << ", trim_http: " << test_cases[i].trim_http); AutocompleteInput input(ASCIIToUTF16(test_cases[i].input), metrics::OmniboxEventProto::BLANK, @@ -1184,8 +1185,9 @@ EXPECT_EQ(test_cases[i].offsets[match_index], match.contents_class[match_index].offset); EXPECT_EQ(ACMatchClassification::URL | - (match_index == test_cases[i].match_classification_index ? - ACMatchClassification::MATCH : 0), + (match_index == test_cases[i].match_classification_index + ? ACMatchClassification::MATCH + : 0), match.contents_class[match_index].style); } EXPECT_EQ(npos, test_cases[i].offsets[match.contents_class.size()]); @@ -1408,7 +1410,7 @@ metrics::OmniboxEventProto_KeywordModeEntryMethod_TAB); } - provider_->Stop(true, false); + provider_->Stop(AutocompleteStopReason::kClobbered); provider_->Start(input, false); if (!provider_->done()) { base::RunLoop loop{base::RunLoop::Type::kNestableTasksAllowed};
diff --git a/components/omnibox/browser/in_memory_url_index_unittest.cc b/components/omnibox/browser/in_memory_url_index_unittest.cc index ca9af00..0757a93 100644 --- a/components/omnibox/browser/in_memory_url_index_unittest.cc +++ b/components/omnibox/browser/in_memory_url_index_unittest.cc
@@ -4,10 +4,6 @@ #include <array> -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/omnibox/browser/in_memory_url_index.h"
diff --git a/components/omnibox/browser/keyword_provider.cc b/components/omnibox/browser/keyword_provider.cc index f9943de..5cfe125 100644 --- a/components/omnibox/browser/keyword_provider.cc +++ b/components/omnibox/browser/keyword_provider.cc
@@ -15,6 +15,7 @@ #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/trace_event/trace_event.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_provider_client.h" @@ -320,15 +321,16 @@ } } -void KeywordProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); +void KeywordProvider::Stop(AutocompleteStopReason stop_reason) { + AutocompleteProvider::Stop(stop_reason); // Only end an extension's request if the user did something to explicitly // cancel it; mere inactivity shouldn't terminate long-running extension // operations since the user likely explicitly requested them. - if (extensions_delegate_ && !due_to_user_inactivity) + if (extensions_delegate_ && + stop_reason != AutocompleteStopReason::kInactivity) { extensions_delegate_->MaybeEndExtensionKeywordMode(); + } } KeywordProvider::~KeywordProvider() = default;
diff --git a/components/omnibox/browser/keyword_provider.h b/components/omnibox/browser/keyword_provider.h index 5eacf2c..7bc29c1f 100644 --- a/components/omnibox/browser/keyword_provider.h +++ b/components/omnibox/browser/keyword_provider.h
@@ -19,6 +19,7 @@ #include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/keyword_extensions_delegate.h" @@ -73,9 +74,7 @@ // AutocompleteProvider: void DeleteMatch(const AutocompleteMatch& match) override; void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; - - bool done() const { return done_; } + void Stop(AutocompleteStopReason stop_reason) override; private: friend class KeywordExtensionsDelegateImpl;
diff --git a/components/omnibox/browser/local_history_zero_suggest_provider.cc b/components/omnibox/browser/local_history_zero_suggest_provider.cc index 5f595b9..bf4a103 100644 --- a/components/omnibox/browser/local_history_zero_suggest_provider.cc +++ b/components/omnibox/browser/local_history_zero_suggest_provider.cc
@@ -26,6 +26,7 @@ #include "components/history/core/browser/keyword_search_term.h" #include "components/history/core/browser/keyword_search_term_util.h" #include "components/history/core/browser/url_database.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" @@ -104,8 +105,7 @@ void LocalHistoryZeroSuggestProvider::Start(const AutocompleteInput& input, bool minimal_changes) { TRACE_EVENT0("omnibox", "LocalHistoryZeroSuggestProvider::Start"); - Stop(true, false); - + Stop(AutocompleteStopReason::kClobbered); if (!AllowLocalHistoryZeroSuggestSuggestions(client_, input)) { return; }
diff --git a/components/omnibox/browser/most_visited_sites_provider.cc b/components/omnibox/browser/most_visited_sites_provider.cc index 8ec28e3..6915ef0 100644 --- a/components/omnibox/browser/most_visited_sites_provider.cc +++ b/components/omnibox/browser/most_visited_sites_provider.cc
@@ -17,6 +17,7 @@ #include "base/trace_event/trace_event.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/top_sites.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" @@ -293,8 +294,7 @@ void MostVisitedSitesProvider::Start(const AutocompleteInput& input, bool minimal_changes) { - Stop(true, false); - + Stop(AutocompleteStopReason::kClobbered); if (!AllowMostVisitedSitesSuggestions(client_, input)) { return; } @@ -360,9 +360,8 @@ } } -void MostVisitedSitesProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); +void MostVisitedSitesProvider::Stop(AutocompleteStopReason stop_reason) { + AutocompleteProvider::Stop(stop_reason); request_weak_ptr_factory_.InvalidateWeakPtrs(); cancelable_task_tracker_.TryCancelAll(); debouncer_->CancelRequest();
diff --git a/components/omnibox/browser/most_visited_sites_provider.h b/components/omnibox/browser/most_visited_sites_provider.h index 6569599..d1ee32d5 100644 --- a/components/omnibox/browser/most_visited_sites_provider.h +++ b/components/omnibox/browser/most_visited_sites_provider.h
@@ -12,6 +12,7 @@ #include "base/task/cancelable_task_tracker.h" #include "base/timer/elapsed_timer.h" #include "components/history/core/browser/history_types.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/autocomplete_provider_client.h" @@ -33,7 +34,7 @@ // AutocompleteProvider: void StartPrefetch(const AutocompleteInput& input) override; void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; void DeleteMatch(const AutocompleteMatch& match) override; void DeleteMatchElement(const AutocompleteMatch& match, size_t element) override;
diff --git a/components/omnibox/browser/most_visited_sites_provider_unittest.cc b/components/omnibox/browser/most_visited_sites_provider_unittest.cc index d96f641..4a32087 100644 --- a/components/omnibox/browser/most_visited_sites_provider_unittest.cc +++ b/components/omnibox/browser/most_visited_sites_provider_unittest.cc
@@ -14,6 +14,7 @@ #include "components/history/core/browser/features.h" #include "components/history/core/browser/top_sites.h" #include "components/history/core/browser/top_sites_impl.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" #include "components/omnibox/browser/fake_autocomplete_provider_client.h" #include "components/omnibox/browser/test_scheme_classifier.h" @@ -351,11 +352,11 @@ EXPECT_TRUE(top_sites_->EmitURLs(test_data)); CheckMatchesEquivalentTo(test_data, ExpectedUiType::kAggregateMatch); EXPECT_EQ(1, provider_update_count_); - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kClobbered); // Observe that subsequent request does not return stale data. provider_->Start(input, true); - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kClobbered); // Since this provider's async logic is still in-flight (`EmitURLs()` has not // been called yet), we should not be reporting anything from past runs. EXPECT_EQ(0ul, NumMostVisitedMatches()); @@ -372,7 +373,7 @@ EXPECT_EQ(1, provider_update_count_); provider_->Start(input, true); - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kClobbered); provider_->Start(input, true); // Stale results (reported for the first of the two Start() requests) should @@ -385,7 +386,7 @@ EXPECT_TRUE(top_sites_->EmitURLs(test_data)); CheckMatchesEquivalentTo(test_data, ExpectedUiType::kAggregateMatch); EXPECT_EQ(2, provider_update_count_); - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kClobbered); } TEST_F(MostVisitedSitesProviderTest, TestMostVisitedNavigateToSearchPage) {
diff --git a/components/omnibox/browser/omnibox_controller.cc b/components/omnibox/browser/omnibox_controller.cc index 420d0ea..590fec3 100644 --- a/components/omnibox/browser/omnibox_controller.cc +++ b/components/omnibox/browser/omnibox_controller.cc
@@ -10,6 +10,7 @@ #include "base/trace_event/trace_event.h" #include "components/omnibox/browser/autocomplete_classifier.h" #include "components/omnibox/browser/autocomplete_controller_emitter.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_type.h" #include "components/omnibox/browser/omnibox_client.h" @@ -74,7 +75,9 @@ void OmniboxController::StopAutocomplete(bool clear_result) const { TRACE_EVENT0("omnibox", "OmniboxController::StopAutocomplete"); - autocomplete_controller_->Stop(clear_result); + autocomplete_controller_->Stop(clear_result + ? AutocompleteStopReason::kClobbered + : AutocompleteStopReason::kInteraction); } void OmniboxController::StartZeroSuggestPrefetch() {
diff --git a/components/omnibox/browser/on_device_head_provider.cc b/components/omnibox/browser/on_device_head_provider.cc index 543d59d..fe439a9 100644 --- a/components/omnibox/browser/on_device_head_provider.cc +++ b/components/omnibox/browser/on_device_head_provider.cc
@@ -18,6 +18,7 @@ #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" #include "base/trace_event/trace_event.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" #include "components/omnibox/browser/base_search_provider.h" #include "components/omnibox/browser/omnibox_field_trial.h" @@ -152,7 +153,8 @@ TRACE_EVENT0("omnibox", "OnDeviceHeadProvider::Start"); // Cancel any in-progress request. - Stop(!minimal_changes, false); + Stop(minimal_changes ? AutocompleteStopReason::kInteraction + : AutocompleteStopReason::kClobbered); if (!IsOnDeviceHeadProviderAllowed(input)) { matches_.clear(); @@ -180,10 +182,8 @@ weak_ptr_factory_.GetWeakPtr(), std::move(params))); } -void OnDeviceHeadProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); - +void OnDeviceHeadProvider::Stop(AutocompleteStopReason stop_reason) { + AutocompleteProvider::Stop(stop_reason); // Increase the request_id so that any in-progress requests will become // obsolete. on_device_search_request_id_ =
diff --git a/components/omnibox/browser/on_device_head_provider.h b/components/omnibox/browser/on_device_head_provider.h index ed3e4c7..022440b3 100644 --- a/components/omnibox/browser/on_device_head_provider.h +++ b/components/omnibox/browser/on_device_head_provider.h
@@ -11,6 +11,7 @@ #include "base/memory/raw_ptr.h" #include "base/sequence_checker.h" #include "base/task/sequenced_task_runner.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/on_device_head_model.h" @@ -38,7 +39,7 @@ AutocompleteProviderListener* listener); void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; void AddProviderInfo(ProvidersInfo* provider_info) const override; AutocompleteProviderClient* client() { return client_; }
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc index bfcf964..8eab016 100644 --- a/components/omnibox/browser/search_provider.cc +++ b/components/omnibox/browser/search_provider.cc
@@ -32,6 +32,7 @@ #include "components/history/core/browser/keyword_search_term.h" #include "components/history/core/browser/keyword_search_term_util.h" #include "components/lens/lens_features.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" @@ -232,7 +233,7 @@ if (base::FeatureList::IsEnabled(omnibox::kAblateSearchProviderWarmup) && (input.IsZeroSuggest() || input.type() == metrics::OmniboxInputType::EMPTY)) { - Stop(true, false); + Stop(AutocompleteStopReason::kClobbered); return; } @@ -255,7 +256,7 @@ if (!default_provider && !keyword_provider) { // No valid providers. - Stop(true, false); + Stop(AutocompleteStopReason::kClobbered); return; } @@ -269,7 +270,7 @@ !providers_.equal(default_provider_keyword, keyword_provider_keyword)) { // Cancel any in-flight suggest requests. if (!done_) - Stop(false, false); + Stop(AutocompleteStopReason::kInteraction); } providers_.set(default_provider_keyword, keyword_provider_keyword); @@ -290,7 +291,7 @@ match.allowed_to_be_default_match = true; matches_.push_back(match); } - Stop(true, false); + Stop(AutocompleteStopReason::kClobbered); return; } @@ -320,12 +321,10 @@ UpdateMatches(); } -void SearchProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); - +void SearchProvider::Stop(AutocompleteStopReason stop_reason) { + AutocompleteProvider::Stop(stop_reason); StopSuggest(); - if (clear_cached_results) + if (stop_reason == AutocompleteStopReason::kClobbered) ClearAllResults(); }
diff --git a/components/omnibox/browser/search_provider.h b/components/omnibox/browser/search_provider.h index a2d9702..faef1c03 100644 --- a/components/omnibox/browser/search_provider.h +++ b/components/omnibox/browser/search_provider.h
@@ -22,6 +22,7 @@ #include "base/time/time.h" #include "base/timer/timer.h" #include "components/omnibox/browser/answers_cache.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/base_search_provider.h" #include "components/search_engines/template_url.h" #include "components/search_engines/template_url_service.h" @@ -131,8 +132,8 @@ // by this class. bool equal(const std::u16string& default_provider, const std::u16string& keyword_provider) const { - return (default_provider == default_provider_) && - (keyword_provider == keyword_provider_); + return default_provider == default_provider_ && + keyword_provider == keyword_provider_; } // Resets the cached providers. @@ -172,8 +173,7 @@ // AutocompleteProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, - bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; // BaseSearchProvider: bool ShouldAppendExtraParams( @@ -424,7 +424,7 @@ GURL top_navigation_suggestion_; // Answers prefetch management. - AnswersCache answers_cache_; // Cache for last answers seen. + AnswersCache answers_cache_; // Cache for last answers seen. AnswersQueryData prefetch_data_; // Data to use for query prefetching. base::ScopedObservation<TemplateURLService, TemplateURLServiceObserver>
diff --git a/components/omnibox/browser/shortcuts_database_unittest.cc b/components/omnibox/browser/shortcuts_database_unittest.cc index f39fc5c5..48b4ae85 100644 --- a/components/omnibox/browser/shortcuts_database_unittest.cc +++ b/components/omnibox/browser/shortcuts_database_unittest.cc
@@ -4,10 +4,6 @@ #include <array> -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/omnibox/browser/shortcuts_database.h"
diff --git a/components/omnibox/browser/tab_group_provider.cc b/components/omnibox/browser/tab_group_provider.cc index 9450da11..0543f91 100644 --- a/components/omnibox/browser/tab_group_provider.cc +++ b/components/omnibox/browser/tab_group_provider.cc
@@ -16,6 +16,7 @@ #if BUILDFLAG(IS_ANDROID) #include "components/browser_ui/util/android/url_constants.h" #endif +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" @@ -82,7 +83,7 @@ // TODO(crbug.com/412433887): Make the TabGroupProvider async. void TabGroupProvider::Start(const AutocompleteInput& input, bool minimal_changes) { - Stop(true, false); + Stop(AutocompleteStopReason::kClobbered); if (input.current_page_classification() != ::metrics::OmniboxEventProto::ANDROID_HUB) { return;
diff --git a/components/omnibox/browser/unscoped_extension_provider.cc b/components/omnibox/browser/unscoped_extension_provider.cc index 4d7dfcd..f48c5ca 100644 --- a/components/omnibox/browser/unscoped_extension_provider.cc +++ b/components/omnibox/browser/unscoped_extension_provider.cc
@@ -8,6 +8,7 @@ #include "base/check_is_test.h" #include "base/memory/raw_ptr.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" @@ -33,8 +34,8 @@ // matches and suggestion group information and increment the current request // ID to discard any suggestions that may be incoming later with a stale // request ID. - Stop(/*clear_cached_results=*/!minimal_changes, - /*due_to_user_inactivity=*/false); + Stop(minimal_changes ? AutocompleteStopReason::kInteraction + : AutocompleteStopReason::kClobbered); // Unscoped mode input should not be redirected to an extension in incognito. if (client_->IsOffTheRecord()) { @@ -82,14 +83,14 @@ delegate_->Start(input, minimal_changes, unscoped_extensions); } -void UnscopedExtensionProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { +void UnscopedExtensionProvider::Stop(AutocompleteStopReason stop_reason) { // Ignore the stop timer since extension suggestions might take longer than // 1500ms to generate (the stop timer gets triggered due to user inactivity). - if (!due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); - delegate_->Stop(clear_cached_results); + if (stop_reason == AutocompleteStopReason::kInactivity) { + return; } + AutocompleteProvider::Stop(stop_reason); + delegate_->Stop(stop_reason == AutocompleteStopReason::kClobbered); } void UnscopedExtensionProvider::DeleteMatch(const AutocompleteMatch& match) {
diff --git a/components/omnibox/browser/unscoped_extension_provider.h b/components/omnibox/browser/unscoped_extension_provider.h index d4231b7..ead3999 100644 --- a/components/omnibox/browser/unscoped_extension_provider.h +++ b/components/omnibox/browser/unscoped_extension_provider.h
@@ -9,6 +9,7 @@ #include <string> #include "base/memory/raw_ptr.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/omnibox_suggestions_watcher.h" @@ -32,7 +33,7 @@ // AutocompleteProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; void DeleteMatch(const AutocompleteMatch& match) override; // Used by UnscopedExtensionProviderDelegateImpl. @@ -40,7 +41,6 @@ void AddToSuggestionGroupsMap(omnibox::GroupId group_id, omnibox::GroupConfig group_config); void set_done(bool done) { done_ = done; } - bool done() const { return done_; } ACMatches* matches() { return &matches_; } private:
diff --git a/components/omnibox/browser/voice_suggest_provider.cc b/components/omnibox/browser/voice_suggest_provider.cc index 1f6481e1..f50075ea 100644 --- a/components/omnibox/browser/voice_suggest_provider.cc +++ b/components/omnibox/browser/voice_suggest_provider.cc
@@ -6,10 +6,9 @@ #include <string> +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" -#include "components/omnibox/browser/autocomplete_match_classification.h" -#include "components/search_engines/template_url.h" #include "components/search_engines/template_url_service.h" #include "third_party/omnibox_proto/navigational_intent.pb.h" #include "third_party/omnibox_proto/types.pb.h" @@ -79,11 +78,9 @@ void VoiceSuggestProvider::RecordDeletionResult(bool success) {} -void VoiceSuggestProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); - - if (clear_cached_results) { +void VoiceSuggestProvider::Stop(AutocompleteStopReason stop_reason) { + AutocompleteProvider::Stop(stop_reason); + if (stop_reason == AutocompleteStopReason::kClobbered) { ClearCache(); } }
diff --git a/components/omnibox/browser/voice_suggest_provider.h b/components/omnibox/browser/voice_suggest_provider.h index 1eb6290..4a7536a0 100644 --- a/components/omnibox/browser/voice_suggest_provider.h +++ b/components/omnibox/browser/voice_suggest_provider.h
@@ -11,6 +11,7 @@ #include "base/compiler_specific.h" #include "base/memory/raw_ptr.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/base_search_provider.h" @@ -22,7 +23,7 @@ explicit VoiceSuggestProvider(AutocompleteProviderClient* client); void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; // Adds voice suggestion to the list of reported AutocompleteMatches. // The voice suggestion is next converted to a proper Search suggestion
diff --git a/components/omnibox/browser/voice_suggest_provider_unittest.cc b/components/omnibox/browser/voice_suggest_provider_unittest.cc index 1462707..9763c10 100644 --- a/components/omnibox/browser/voice_suggest_provider_unittest.cc +++ b/components/omnibox/browser/voice_suggest_provider_unittest.cc
@@ -8,6 +8,7 @@ #include "base/test/task_environment.h" #include "build/build_config.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/fake_autocomplete_provider_client.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -19,7 +20,6 @@ VoiceSuggestProviderTest& operator=(const VoiceSuggestProviderTest&) = delete; void SetUp() override; - void TearDown() override; protected: base::test::TaskEnvironment environment_; @@ -35,10 +35,6 @@ TestSchemeClassifier()); } -void VoiceSuggestProviderTest::TearDown() { - provider_->Stop(true, true); -} - TEST_F(VoiceSuggestProviderTest, ServesNoSuggestionsByDefault) { provider_->Start(*input_, false); EXPECT_TRUE(provider_->matches().empty()); @@ -74,7 +70,7 @@ provider_->AddVoiceSuggestion(u"Bob", 0.5f); provider_->AddVoiceSuggestion(u"Carol", 0.4f); provider_->Start(*input_, false); - provider_->Stop(true, false); + provider_->Stop(AutocompleteStopReason::kClobbered); provider_->Start(*input_, false); EXPECT_TRUE(provider_->matches().empty());
diff --git a/components/omnibox/browser/zero_suggest_provider.cc b/components/omnibox/browser/zero_suggest_provider.cc index e8b449f..0c8bc96 100644 --- a/components/omnibox/browser/zero_suggest_provider.cc +++ b/components/omnibox/browser/zero_suggest_provider.cc
@@ -20,6 +20,7 @@ #include "base/time/time.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match_classification.h" @@ -327,13 +328,15 @@ match.contents = url_formatter::FormatUrl(navigation.url(), format_types, base::UnescapeRule::SPACES, nullptr, nullptr, nullptr); - match.contents_class = ClassifyTermMatches({}, match.contents.length(), 0, + match.contents_class = ClassifyTermMatches({}, match.contents.length(), + ACMatchClassification::NONE, ACMatchClassification::URL); match.description = AutocompleteMatch::SanitizeString(navigation.description()); match.description_class = ClassifyTermMatches({}, match.description.length(), - 0, ACMatchClassification::NONE); + ACMatchClassification::NONE, + ACMatchClassification::NONE); match.suggest_type = navigation.suggest_type(); for (const int subtype : navigation.subtypes()) { match.subtypes.insert(SuggestSubtypeForNumber(subtype)); @@ -471,7 +474,7 @@ void ZeroSuggestProvider::Start(const AutocompleteInput& input, bool minimal_changes) { TRACE_EVENT0("omnibox", "ZeroSuggestProvider::Start"); - Stop(true, false); + Stop(AutocompleteStopReason::kClobbered); auto [result_type, eligible] = GetResultTypeAndEligibility(client(), input); LogOmniboxZeroSuggestEligibility(result_type, eligible); @@ -532,9 +535,8 @@ /*is_prefetch=*/false); } -void ZeroSuggestProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); +void ZeroSuggestProvider::Stop(AutocompleteStopReason stop_reason) { + AutocompleteProvider::Stop(stop_reason); if (base::FeatureList::IsEnabled(omnibox::kZeroSuggestPrefetchDebouncing)) { debouncer_->CancelRequest(); @@ -548,7 +550,7 @@ } result_type_running_ = ResultType::kNone; - if (clear_cached_results) { + if (stop_reason == AutocompleteStopReason::kClobbered) { experiment_stats_v2s_.clear(); gws_event_id_hashes_.clear(); }
diff --git a/components/omnibox/browser/zero_suggest_provider.h b/components/omnibox/browser/zero_suggest_provider.h index e09407e0..a3a5dde 100644 --- a/components/omnibox/browser/zero_suggest_provider.h +++ b/components/omnibox/browser/zero_suggest_provider.h
@@ -13,6 +13,7 @@ #include <string> #include "base/gtest_prod_util.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_provider_debouncer.h" #include "components/omnibox/browser/base_search_provider.h" @@ -72,8 +73,7 @@ // AutocompleteProvider: void StartPrefetch(const AutocompleteInput& input) override; void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, - bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; void DeleteMatch(const AutocompleteMatch& match) override; void AddProviderInfo(ProvidersInfo* provider_info) const override;
diff --git a/components/omnibox/browser/zero_suggest_verbatim_match_provider.cc b/components/omnibox/browser/zero_suggest_verbatim_match_provider.cc index 5ae5bda..c732fbc 100644 --- a/components/omnibox/browser/zero_suggest_verbatim_match_provider.cc +++ b/components/omnibox/browser/zero_suggest_verbatim_match_provider.cc
@@ -12,6 +12,7 @@ #include "components/history/core/browser/history_types.h" #include "components/history/core/browser/url_database.h" #include "components/history/core/browser/url_row.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_match_classification.h" #include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/autocomplete_provider_listener.h" @@ -54,7 +55,7 @@ void ZeroSuggestVerbatimMatchProvider::Start(const AutocompleteInput& input, bool minimal_changes) { - Stop(true, false); + Stop(AutocompleteStopReason::kClobbered); if (!IsVerbatimMatchEligible(input.current_page_classification())) return; @@ -100,9 +101,9 @@ &task_tracker_); } -void ZeroSuggestVerbatimMatchProvider::Stop(bool clear_cached_results, - bool due_to_user_inactivity) { - AutocompleteProvider::Stop(clear_cached_results, due_to_user_inactivity); +void ZeroSuggestVerbatimMatchProvider::Stop( + AutocompleteStopReason stop_reason) { + AutocompleteProvider::Stop(stop_reason); request_weak_ptr_factory_.InvalidateWeakPtrs(); }
diff --git a/components/omnibox/browser/zero_suggest_verbatim_match_provider.h b/components/omnibox/browser/zero_suggest_verbatim_match_provider.h index 826e905..d4a48b4e 100644 --- a/components/omnibox/browser/zero_suggest_verbatim_match_provider.h +++ b/components/omnibox/browser/zero_suggest_verbatim_match_provider.h
@@ -7,6 +7,7 @@ #include "base/memory/raw_ptr.h" #include "base/task/cancelable_task_tracker.h" #include "components/history/core/browser/history_types.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_provider.h" #include "components/omnibox/browser/history_url_provider.h" @@ -27,7 +28,7 @@ // AutocompleteProvider: void Start(const AutocompleteInput& input, bool minimal_changes) override; - void Stop(bool clear_cached_results, bool due_to_user_inactivity) override; + void Stop(AutocompleteStopReason stop_reason) override; private: void OnPageTitleRetrieved(const AutocompleteInput& input,
diff --git a/components/omnibox/browser/zero_suggest_verbatim_match_provider_unittest.cc b/components/omnibox/browser/zero_suggest_verbatim_match_provider_unittest.cc index 776eb95..d78f614 100644 --- a/components/omnibox/browser/zero_suggest_verbatim_match_provider_unittest.cc +++ b/components/omnibox/browser/zero_suggest_verbatim_match_provider_unittest.cc
@@ -13,6 +13,7 @@ #include "base/test/task_environment.h" #include "components/history/core/browser/history_service.h" #include "components/history/core/browser/history_types.h" +#include "components/omnibox/browser/autocomplete_enums.h" #include "components/omnibox/browser/fake_autocomplete_provider_client.h" #include "components/omnibox/browser/mock_autocomplete_provider_client.h" #include "components/omnibox/browser/test_scheme_classifier.h" @@ -456,7 +457,7 @@ } // Cancel action. - provider_->Stop(false, false); + provider_->Stop(AutocompleteStopReason::kInteraction); { // Resolve history service.
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal index 28300a0..976b8f4 160000 --- a/components/optimization_guide/internal +++ b/components/optimization_guide/internal
@@ -1 +1 @@ -Subproject commit 28300a0a975163d53866dc59929e600f3a9917bc +Subproject commit 976b8f41d35f356dd01e2dc99e317dbafb032477
diff --git a/components/os_crypt/sync/kwallet_dbus.cc b/components/os_crypt/sync/kwallet_dbus.cc index 7e4f428..20cf5519 100644 --- a/components/os_crypt/sync/kwallet_dbus.cc +++ b/components/os_crypt/sync/kwallet_dbus.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/os_crypt/sync/kwallet_dbus.h"
diff --git a/components/os_crypt/sync/kwallet_dbus_unittest.cc b/components/os_crypt/sync/kwallet_dbus_unittest.cc index 8d69d4b..4ae8e8b 100644 --- a/components/os_crypt/sync/kwallet_dbus_unittest.cc +++ b/components/os_crypt/sync/kwallet_dbus_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/os_crypt/sync/kwallet_dbus.h"
diff --git a/components/page_load_metrics/common/page_load_metrics.mojom b/components/page_load_metrics/common/page_load_metrics.mojom index 6dddf5c..31c7dfe 100644 --- a/components/page_load_metrics/common/page_load_metrics.mojom +++ b/components/page_load_metrics/common/page_load_metrics.mojom
@@ -447,6 +447,11 @@ // Routing API, from navigation start till onload event. uint32 matched_race_network_and_fetch_router_source_count = 0; + // Total number of sub-resources which were matched to the + // `RouterSourceEnum.race-network-and-cache` in ServiceWorker Static + // Routing API, from navigation start till onload event. + uint32 matched_race_network_and_cache_router_source_count = 0; + // Total router evaluation time of ServiceWorker Static Routing API for // sub-resources. mojo_base.mojom.TimeDelta total_router_evaluation_time_for_subresources;
diff --git a/components/page_load_metrics/common/page_load_metrics_mojom_traits.cc b/components/page_load_metrics/common/page_load_metrics_mojom_traits.cc index d00ca978..b873cbdd 100644 --- a/components/page_load_metrics/common/page_load_metrics_mojom_traits.cc +++ b/components/page_load_metrics/common/page_load_metrics_mojom_traits.cc
@@ -65,6 +65,8 @@ data.matched_network_router_source_count(); out->matched_race_network_and_fetch_router_source_count = data.matched_race_network_and_fetch_router_source_count(); + out->matched_race_network_and_cache_router_source_count = + data.matched_race_network_and_cache_router_source_count(); if (!data.ReadTotalRouterEvaluationTimeForSubresources( &out->total_router_evaluation_time_for_subresources)) { return false;
diff --git a/components/page_load_metrics/common/page_load_metrics_mojom_traits.h b/components/page_load_metrics/common/page_load_metrics_mojom_traits.h index 46fff08..601bd58b 100644 --- a/components/page_load_metrics/common/page_load_metrics_mojom_traits.h +++ b/components/page_load_metrics/common/page_load_metrics_mojom_traits.h
@@ -179,6 +179,11 @@ return d.matched_race_network_and_fetch_router_source_count; } + static uint32_t matched_race_network_and_cache_router_source_count( + const blink::ServiceWorkerSubresourceLoadMetrics& d) { + return d.matched_race_network_and_cache_router_source_count; + } + static base::TimeDelta total_router_evaluation_time_for_subresources( const blink::ServiceWorkerSubresourceLoadMetrics& d) { return d.total_router_evaluation_time_for_subresources;
diff --git a/components/paint_preview/common/serialized_recording.cc b/components/paint_preview/common/serialized_recording.cc index c007349..2e65a31 100644 --- a/components/paint_preview/common/serialized_recording.cc +++ b/components/paint_preview/common/serialized_recording.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/paint_preview/common/serialized_recording.h"
diff --git a/components/policy/core/common/cloud/resource_cache.cc b/components/policy/core/common/cloud/resource_cache.cc index e2aeb05a..08e3296c 100644 --- a/components/policy/core/common/cloud/resource_cache.cc +++ b/components/policy/core/common/cloud/resource_cache.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/policy/core/common/cloud/resource_cache.h"
diff --git a/components/policy/core/common/policy_proto_decoders_unittest.cc b/components/policy/core/common/policy_proto_decoders_unittest.cc index 9d3b619..8fab36c 100644 --- a/components/policy/core/common/policy_proto_decoders_unittest.cc +++ b/components/policy/core/common/policy_proto_decoders_unittest.cc
@@ -4,6 +4,7 @@ #include "components/policy/core/common/policy_proto_decoders.h" +#include "base/json/json_reader.h" #include "base/strings/string_number_conversions.h" #include "components/policy/core/common/cloud/cloud_policy_constants.h" #include "components/policy/core/common/cloud/test/policy_builder.h" @@ -195,8 +196,10 @@ expected_policy_map_.Set(key::kManagedBookmarks, POLICY_LEVEL_MANDATORY, POLICY_SCOPE_USER, POLICY_SOURCE_CLOUD, base::Value(invalidDummyJson), nullptr); - const std::u16string kExpectedMessage = - u"EOF while parsing an object at line 3 column 2"; + std::u16string kExpectedMessage = + base::JSONReader::UsingRust() + ? u"EOF while parsing an object at line 3 column 2" + : u"Line: 3, column: 3, Syntax error."; expected_policy_map_.AddMessage( key::kManagedBookmarks, PolicyMap::MessageType::kError, IDS_POLICY_PROTO_PARSING_ERROR, {kExpectedMessage});
diff --git a/components/policy/core/common/policy_service_impl.cc b/components/policy/core/common/policy_service_impl.cc index 9ca5608..93fb9a88 100644 --- a/components/policy/core/common/policy_service_impl.cc +++ b/components/policy/core/common/policy_service_impl.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/policy/core/common/policy_service_impl.h"
diff --git a/components/policy/core/common/schema_registry.cc b/components/policy/core/common/schema_registry.cc index c0e9585d..670895f 100644 --- a/components/policy/core/common/schema_registry.cc +++ b/components/policy/core/common/schema_registry.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/policy/core/common/schema_registry.h"
diff --git a/components/power_metrics/energy_metrics_provider_linux.cc b/components/power_metrics/energy_metrics_provider_linux.cc index 219ad14..716bce9 100644 --- a/components/power_metrics/energy_metrics_provider_linux.cc +++ b/components/power_metrics/energy_metrics_provider_linux.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/power_metrics/energy_metrics_provider_linux.h"
diff --git a/components/services/storage/indexed_db/scopes/varint_coding.cc b/components/services/storage/indexed_db/scopes/varint_coding.cc index d957520a..8b0ef3d 100644 --- a/components/services/storage/indexed_db/scopes/varint_coding.cc +++ b/components/services/storage/indexed_db/scopes/varint_coding.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/services/storage/indexed_db/scopes/varint_coding.h"
diff --git a/components/services/storage/indexed_db/scopes/varint_coding_unittest.cc b/components/services/storage/indexed_db/scopes/varint_coding_unittest.cc index fe925e75..6dfb1c6 100644 --- a/components/services/storage/indexed_db/scopes/varint_coding_unittest.cc +++ b/components/services/storage/indexed_db/scopes/varint_coding_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/services/storage/indexed_db/scopes/varint_coding.h"
diff --git a/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc b/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc index 00306ff..4a6601275 100644 --- a/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc +++ b/components/sync_bookmarks/bookmark_model_observer_impl_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/sync_bookmarks/bookmark_model_observer_impl.h"
diff --git a/components/update_client/net/network_impl.cc b/components/update_client/net/network_impl.cc index 9789398b..01c38e6 100644 --- a/components/update_client/net/network_impl.cc +++ b/components/update_client/net/network_impl.cc
@@ -150,6 +150,7 @@ GetStringHeader(simple_url_loader.get(), kHeaderEtag), GetStringHeader(simple_url_loader.get(), kHeaderXCupServerProof), + GetStringHeader(simple_url_loader.get(), kHeaderCookie), GetInt64Header(simple_url_loader.get(), kHeaderXRetryAfter)); },
diff --git a/components/update_client/network.h b/components/update_client/network.h index 5295154..01b59d1 100644 --- a/components/update_client/network.h +++ b/components/update_client/network.h
@@ -32,6 +32,7 @@ int net_error, const std::string& header_etag, const std::string& header_x_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec)>; using DownloadToFileCompleteCallback = base::OnceCallback<void(int net_error, int64_t content_size)>; @@ -57,6 +58,11 @@ // trusted. static constexpr char kHeaderXRetryAfter[] = "X-Retry-After"; + // The HTTP 'Cookie' header to pass through to the + // `PostRequestCompleteCallback`. This header isn't used by the Omaha update + // protocol but is necessary for other uses of `NetworkFetcher`. + static constexpr char kHeaderCookie[] = "Cookie"; + NetworkFetcher(const NetworkFetcher&) = delete; NetworkFetcher& operator=(const NetworkFetcher&) = delete;
diff --git a/components/update_client/request_sender.cc b/components/update_client/request_sender.cc index a3d55bc..1915035 100644 --- a/components/update_client/request_sender.cc +++ b/components/update_client/request_sender.cc
@@ -114,7 +114,8 @@ FROM_HERE, base::BindOnce(&RequestSender::SendInternalComplete, this, static_cast<int>(ProtocolError::URL_FETCHER_FAILED), - std::string(), std::string(), std::string(), 0)); + std::string(), std::string(), std::string(), + std::string(), 0)); return; } network_fetcher_->PostRequest( @@ -129,6 +130,7 @@ const std::string& response_body, const std::string& response_etag, const std::string& response_cup_server_proof, + const std::string& response_cookie, int retry_after_sec) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); VLOG(2) << "Omaha response received: " << response_body; @@ -179,6 +181,7 @@ int net_error, const std::string& header_etag, const std::string& xheader_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -202,7 +205,8 @@ FROM_HERE, base::BindOnce(&RequestSender::SendInternalComplete, this, error, std::move(response_body).value_or(std::string()), - header_etag, xheader_cup_server_proof, retry_after_sec)); + header_etag, xheader_cup_server_proof, header_cookie, + retry_after_sec)); } void RequestSender::HandleSendError(int error, int retry_after_sec) {
diff --git a/components/update_client/request_sender.h b/components/update_client/request_sender.h index 4cded1d7..340bba3 100644 --- a/components/update_client/request_sender.h +++ b/components/update_client/request_sender.h
@@ -72,6 +72,7 @@ int net_error, const std::string& header_etag, const std::string& xheader_cup_server_proof, + const std::string& header_cookie, int64_t xheader_retry_after_sec); // Implements the error handling and url fallback mechanism. @@ -83,6 +84,7 @@ const std::string& response_body, const std::string& response_etag, const std::string& response_cup_server_proof, + const std::string& response_cookie, int retry_after_sec); // Helper function to handle a non-continuable error in Send.
diff --git a/components/url_formatter/spoof_checks/common_words/common_words_util.cc b/components/url_formatter/spoof_checks/common_words/common_words_util.cc index fa1f0935..d3d4141d4 100644 --- a/components/url_formatter/spoof_checks/common_words/common_words_util.cc +++ b/components/url_formatter/spoof_checks/common_words/common_words_util.cc
@@ -21,8 +21,8 @@ } // namespace bool IsCommonWord(std::string_view word) { - return net::LookupStringInFixedSet(g_dafsa_params, word.data(), - word.size()) != net::kDafsaNotFound; + return net::LookupStringInFixedSet(g_dafsa_params, word) != + net::kDafsaNotFound; } void SetCommonWordDAFSAForTesting(base::span<const uint8_t> dafsa) {
diff --git a/components/url_formatter/url_fixer_unittest.cc b/components/url_formatter/url_fixer_unittest.cc index 39307c26..6f14361 100644 --- a/components/url_formatter/url_fixer_unittest.cc +++ b/components/url_formatter/url_fixer_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/url_formatter/url_fixer.h"
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn index e522423..1529754 100644 --- a/components/viz/service/BUILD.gn +++ b/components/viz/service/BUILD.gn
@@ -705,7 +705,10 @@ sources += [ "display/overlay_dc_unittest.cc", "display_embedder/output_device_backing_unittest.cc", + "display_embedder/software_output_device_win_swapchain_unittest.cc", "display_embedder/software_output_device_win_unittest.cc", + "display_embedder/test_support/dcomp_mocks.cc", + "display_embedder/test_support/dcomp_mocks.h", ] deps += [
diff --git a/components/viz/service/display/display_unittest.cc b/components/viz/service/display/display_unittest.cc index fb14a82..40dbe97 100644 --- a/components/viz/service/display/display_unittest.cc +++ b/components/viz/service/display/display_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "components/viz/service/display/display.h"
diff --git a/components/viz/service/display/renderer_perftest.cc b/components/viz/service/display/renderer_perftest.cc index b7f06af..ff578be 100644 --- a/components/viz/service/display/renderer_perftest.cc +++ b/components/viz/service/display/renderer_perftest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include <array>
diff --git a/components/viz/service/display_embedder/DEPS b/components/viz/service/display_embedder/DEPS index 32b3ac4..028e4e5 100644 --- a/components/viz/service/display_embedder/DEPS +++ b/components/viz/service/display_embedder/DEPS
@@ -31,6 +31,7 @@ "+gpu/ipc", "+gpu/skia_bindings", "+gpu/vulkan", + "+media/base/win/test_utils.h", "+media/gpu/chromeos/vulkan_overlay_adaptor.h", "+media/gpu/buildflags.h", "+mojo/public/cpp/bindings", @@ -68,4 +69,7 @@ "+ui/gl", "+ui/platform_window", ], + "software_output_device_win_swapchain_unittest.cc": [ + "+media/base/win/d3d11_mocks.h", + ] }
diff --git a/components/viz/service/display_embedder/output_device_backing.h b/components/viz/service/display_embedder/output_device_backing.h index d8763a8..f218f93 100644 --- a/components/viz/service/display_embedder/output_device_backing.h +++ b/components/viz/service/display_embedder/output_device_backing.h
@@ -43,7 +43,7 @@ OutputDeviceBacking(const OutputDeviceBacking&) = delete; OutputDeviceBacking& operator=(const OutputDeviceBacking&) = delete; - ~OutputDeviceBacking(); + virtual ~OutputDeviceBacking(); void RegisterClient(Client* client); void UnregisterClient(Client* client); @@ -64,13 +64,13 @@ size_t GetMaxViewportBytes(); // Retrieve the ID3D11Device and IDCompositionDevice to use for presentation. - HRESULT GetOrCreateDXObjects( + virtual HRESULT GetOrCreateDXObjects( Microsoft::WRL::ComPtr<ID3D11Device>* d3d11_device, Microsoft::WRL::ComPtr<IDXGIFactory2>* dxgi_factory, Microsoft::WRL::ComPtr<IDCompositionDevice>* dcomp_device); // Returns the D3D11 staging texture or creates one if it doesn't exist. - Microsoft::WRL::ComPtr<ID3D11Texture2D> GetOrCreateStagingTexture(); + virtual Microsoft::WRL::ComPtr<ID3D11Texture2D> GetOrCreateStagingTexture(); // Returns the size needed for the largest viewport from registered clients, // in pixels.
diff --git a/components/viz/service/display_embedder/software_output_device_win_swapchain.cc b/components/viz/service/display_embedder/software_output_device_win_swapchain.cc index acd4424..4c13c41 100644 --- a/components/viz/service/display_embedder/software_output_device_win_swapchain.cc +++ b/components/viz/service/display_embedder/software_output_device_win_swapchain.cc
@@ -68,13 +68,19 @@ } } +bool SoftwareOutputDeviceWinSwapChain::UpdateWindowSize( + const gfx::Size& viewport_pixel_size) { + // Update the size of the child window. + return SetWindowPos(child_window_.window(), nullptr, 0, 0, + viewport_pixel_size.width(), viewport_pixel_size.height(), + SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS | + SWP_NOOWNERZORDER | SWP_NOZORDER); +} + bool SoftwareOutputDeviceWinSwapChain::ResizeDelegated( const gfx::Size& viewport_pixel_size) { // Update window size. - if (!SetWindowPos(child_window_.window(), nullptr, 0, 0, - viewport_pixel_size.width(), viewport_pixel_size.height(), - SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS | - SWP_NOOWNERZORDER | SWP_NOZORDER)) { + if (!UpdateWindowSize(viewport_pixel_size)) { return false; }
diff --git a/components/viz/service/display_embedder/software_output_device_win_swapchain.h b/components/viz/service/display_embedder/software_output_device_win_swapchain.h index 1b234ca..63520b70 100644 --- a/components/viz/service/display_embedder/software_output_device_win_swapchain.h +++ b/components/viz/service/display_embedder/software_output_device_win_swapchain.h
@@ -43,6 +43,13 @@ const gfx::Size& GetViewportPixelSize() const override; void ReleaseCanvas() override; + bool HasSwapChainForTesting() const { return !!dxgi_swapchain_; } + + bool HasDeviceContextForTesting() const { return !!d3d11_device_context_; } + + protected: + virtual bool UpdateWindowSize(const gfx::Size& viewport_pixel_size); + private: raw_ptr<OutputDeviceBacking> const output_backing_; gl::ChildWindowWin child_window_;
diff --git a/components/viz/service/display_embedder/software_output_device_win_swapchain_unittest.cc b/components/viz/service/display_embedder/software_output_device_win_swapchain_unittest.cc new file mode 100644 index 0000000..643f57ca --- /dev/null +++ b/components/viz/service/display_embedder/software_output_device_win_swapchain_unittest.cc
@@ -0,0 +1,311 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/service/display_embedder/software_output_device_win_swapchain.h" + +#include <windows.h> + +#include <dcomp.h> +#include <dxgi1_2.h> +#include <wrl/client.h> + +#include "base/win/scoped_gdi_object.h" +#include "base/win/windows_types.h" +#include "components/viz/service/display_embedder/output_device_backing.h" +#include "components/viz/service/display_embedder/test_support/dcomp_mocks.h" +#include "media/base/win/d3d11_mocks.h" +#include "media/base/win/test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "ui/gfx/geometry/size.h" + +namespace viz { +namespace { + +constexpr gfx::Size kTestSize(1024, 768); + +class MockOutputDeviceBacking : public OutputDeviceBacking { + public: + MockOutputDeviceBacking() = default; + ~MockOutputDeviceBacking() override = default; + + MOCK_METHOD(Microsoft::WRL::ComPtr<ID3D11Texture2D>, + GetOrCreateStagingTexture, + (), + (override)); + MOCK_METHOD(HRESULT, + GetOrCreateDXObjects, + (Microsoft::WRL::ComPtr<ID3D11Device> * d3d11_device, + Microsoft::WRL::ComPtr<IDXGIFactory2>* dxgi_factory, + Microsoft::WRL::ComPtr<IDCompositionDevice>* dcomp_device), + (override)); +}; + +class TestSoftwareOutputDeviceWinSwapChain + : public SoftwareOutputDeviceWinSwapChain { + public: + TestSoftwareOutputDeviceWinSwapChain(HWND hwnd, + HWND& child_hwnd, + OutputDeviceBacking* output_backing) + : SoftwareOutputDeviceWinSwapChain(hwnd, child_hwnd, output_backing) {} + + // Override to avoid actual window operations. + bool UpdateWindowSize(const gfx::Size& viewport_pixel_size) override { + return resize_result_; + } + + void set_resize_result(bool result) { resize_result_ = result; } + + private: + bool resize_result_ = true; +}; + +class TestWindowClass { + public: + TestWindowClass() : window_(nullptr), child_window_(nullptr) { + // Create a temporary window for testing + window_ = CreateWindowEx(0, L"STATIC", L"Test Window", WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, nullptr, + nullptr, GetModuleHandle(nullptr), nullptr); + } + + ~TestWindowClass() { DestroyWindow(window_); } + + HWND window() const { return window_; } + HWND child_window() const { return child_window_; } + void set_child_window(HWND hwnd) { child_window_ = hwnd; } + + private: + HWND window_; + HWND child_window_; +}; + +class SoftwareOutputDeviceWinSwapChainTest : public testing::Test { + protected: + void SetUp() override { + mock_output_backing_ = + std::make_unique<testing::NiceMock<MockOutputDeviceBacking>>(); + mock_d3d11_device_ = + media::MakeComPtr<testing::NiceMock<media::D3D11DeviceMock>>(); + mock_dxgi_factory_ = + media::MakeComPtr<testing::NiceMock<media::DXGIFactory2Mock>>(); + mock_dcomp_device_ = + media::MakeComPtr<testing::NiceMock<media::DCompositionDeviceMock>>(); + mock_dxgi_swapchain_ = + media::MakeComPtr<testing::NiceMock<media::DXGISwapChain1Mock>>(); + mock_d3d11_device_context_ = + media::MakeComPtr<testing::NiceMock<media::D3D11DeviceContextMock>>(); + mock_dcomp_visual_ = + media::MakeComPtr<testing::NiceMock<media::DCompositionVisualMock>>(); + mock_dcomp_target_ = + media::MakeComPtr<testing::NiceMock<media::DCompositionTargetMock>>(); + + // Allow leak for the mock DCompositionDevice since it is prevented from + // being reset in the event of unexpected gpu process exit to allow for a + // final commit. Also allow leak for the mock DXGISwapChain because the + // DCompositionDevice maintains a reference to it via the root visual. + testing::Mock::AllowLeak(mock_dcomp_device_.Get()); + testing::Mock::AllowLeak(mock_dxgi_swapchain_.Get()); + + ON_CALL(*mock_output_backing_, GetOrCreateDXObjects) + .WillByDefault( + [this](Microsoft::WRL::ComPtr<ID3D11Device>* d3d11_device, + Microsoft::WRL::ComPtr<IDXGIFactory2>* dxgi_factory, + Microsoft::WRL::ComPtr<IDCompositionDevice>* dcomp_device) { + *d3d11_device = mock_d3d11_device_; + *dxgi_factory = mock_dxgi_factory_; + *dcomp_device = mock_dcomp_device_; + return S_OK; + }); + HWND child_hwnd = nullptr; + device_ = std::make_unique<TestSoftwareOutputDeviceWinSwapChain>( + window_class_.window(), child_hwnd, mock_output_backing_.get()); + } + + void TearDown() override { + testing::Mock::VerifyAndClearExpectations(mock_dxgi_swapchain_.Get()); + } + + void SetSwapChainExpectations() { + ON_CALL(*mock_dcomp_device_.Get(), CreateTargetForHwnd) + .WillByDefault( + media::SetComPointeeAndReturnOk<2>(mock_dcomp_target_.Get())); + ON_CALL(*mock_dcomp_device_.Get(), CreateVisual) + .WillByDefault( + media::SetComPointeeAndReturnOk<0>(mock_dcomp_visual_.Get())); + ON_CALL(*mock_d3d11_device_.Get(), GetImmediateContext) + .WillByDefault( + media::SetComPointee<0>(mock_d3d11_device_context_.Get())); + ON_CALL(*mock_dxgi_factory_.Get(), CreateSwapChainForComposition) + .WillByDefault( + media::SetComPointeeAndReturnOk<3>(mock_dxgi_swapchain_.Get())); + + // Device should start with no D3D resources. + EXPECT_FALSE(device_->HasSwapChainForTesting()); + EXPECT_FALSE(device_->HasDeviceContextForTesting()); + EXPECT_CALL(*mock_output_backing_, GetOrCreateDXObjects).Times(1); + EXPECT_EQ(device_->GetViewportPixelSize(), gfx::Size(0, 0)); + } + + void DoResize(gfx::Size size) { + device_->Resize(size, 1.f); + EXPECT_EQ(device_->GetViewportPixelSize(), size); + EXPECT_TRUE(device_->HasSwapChainForTesting()); + EXPECT_TRUE(device_->HasDeviceContextForTesting()); + } + + void DoBeginPaint(gfx::Size size) { + Microsoft::WRL::ComPtr<media::D3D11Texture2DMock> + mock_d3d11_staging_texture = + media::MakeComPtr<testing::NiceMock<media::D3D11Texture2DMock>>(); + EXPECT_CALL(*mock_output_backing_, GetOrCreateStagingTexture) + .WillOnce(testing::Return(mock_d3d11_staging_texture)); + auto desc = D3D11_TEXTURE2D_DESC{ + .Width = static_cast<UINT>(size.width()), + .Height = static_cast<UINT>(size.height()), + .Format = DXGI_FORMAT_B8G8R8A8_UNORM, + .SampleDesc = {.Count = 1, .Quality = 0}, + .Usage = D3D11_USAGE_STAGING, + .BindFlags = 0, + .CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE}; + EXPECT_CALL(*mock_d3d11_staging_texture.Get(), GetDesc) + .WillOnce( + [desc](D3D11_TEXTURE2D_DESC* descriptor) { *descriptor = desc; }); + EXPECT_CALL(*mock_d3d11_device_context_.Get(), Map) + .WillOnce(testing::Return(S_OK)); + SkCanvas* canvas = device_->BeginPaintDelegated(); + auto image_info = canvas->imageInfo(); + EXPECT_EQ(image_info.width(), size.width()); + EXPECT_EQ(image_info.height(), size.height()); + } + + TestWindowClass window_class_; + std::unique_ptr<testing::NiceMock<MockOutputDeviceBacking>> + mock_output_backing_; + std::unique_ptr<TestSoftwareOutputDeviceWinSwapChain> device_; + + Microsoft::WRL::ComPtr<media::DXGIFactory2Mock> mock_dxgi_factory_; + Microsoft::WRL::ComPtr<media::D3D11DeviceMock> mock_d3d11_device_; + Microsoft::WRL::ComPtr<media::DCompositionDeviceMock> mock_dcomp_device_; + Microsoft::WRL::ComPtr<IDCompositionTarget> mock_dcomp_target_; + Microsoft::WRL::ComPtr<media::D3D11DeviceContextMock> + mock_d3d11_device_context_; + Microsoft::WRL::ComPtr<IDCompositionVisual> mock_dcomp_visual_; + Microsoft::WRL::ComPtr<media::DXGISwapChain1Mock> mock_dxgi_swapchain_; +}; + +} // namespace + +// Test that ResizeDelegated creates D3D resources when none exist. +TEST_F(SoftwareOutputDeviceWinSwapChainTest, + ResizeDelegatedCreatesD3DResources) { + SetSwapChainExpectations(); + DoResize(kTestSize); +} + +// Test that ResizeDelegated handles SetWindowPos failure. +TEST_F(SoftwareOutputDeviceWinSwapChainTest, SetWindowPosFailure) { + // Set the resize to fail + device_->set_resize_result(false); + EXPECT_EQ(device_->GetViewportPixelSize(), gfx::Size(0, 0)); + device_->Resize(kTestSize, 1.f); + EXPECT_EQ(device_->GetViewportPixelSize(), gfx::Size(0, 0)); +} + +// Test that ResizeDelegated fails without process crash if CreateTargetForHwnd +// fails due to E_INVALIDARG. Such a scenario can occur if the window is deleted +// before the resize is complete. +TEST_F(SoftwareOutputDeviceWinSwapChainTest, CreateTargetForHwndInvalidArg) { + EXPECT_CALL(*mock_dcomp_device_.Get(), CreateTargetForHwnd) + .WillOnce(testing::Return(E_INVALIDARG)); + EXPECT_EQ(device_->GetViewportPixelSize(), gfx::Size(0, 0)); + device_->Resize(kTestSize, 1.f); + EXPECT_EQ(device_->GetViewportPixelSize(), gfx::Size(0, 0)); +} + +// Test the entire paint pipeline. +TEST_F(SoftwareOutputDeviceWinSwapChainTest, Paint) { + SetSwapChainExpectations(); + // Ensure present gets called in EndPaint. + ON_CALL(*mock_dxgi_swapchain_.Get(), Present1) + .WillByDefault(testing::Return(S_OK)); + + DoResize(kTestSize); + DoBeginPaint(kTestSize); + device_->EndPaintDelegated( + gfx::Rect(0, 0, kTestSize.width(), kTestSize.height())); +} + +// Test that Map fails without process crash if the device is removed. +TEST_F(SoftwareOutputDeviceWinSwapChainTest, FailedMapDueToDeviceRemoved) { + SetSwapChainExpectations(); + EXPECT_CALL(*mock_d3d11_device_context_.Get(), Map) + .WillOnce(testing::Return(DXGI_ERROR_DEVICE_REMOVED)); + EXPECT_CALL(*mock_d3d11_device_.Get(), GetDeviceRemovedReason) + .WillOnce(testing::Return(DXGI_ERROR_DEVICE_REMOVED)); + + DoResize(kTestSize); + + Microsoft::WRL::ComPtr<media::D3D11Texture2DMock> mock_d3d11_staging_texture = + media::MakeComPtr<testing::NiceMock<media::D3D11Texture2DMock>>(); + EXPECT_CALL(*mock_output_backing_, GetOrCreateStagingTexture) + .WillOnce(testing::Return(mock_d3d11_staging_texture)); + // There should be no GPU process termination. + SkCanvas* canvas = device_->BeginPaintDelegated(); + EXPECT_FALSE(!!canvas); +} + +TEST_F(SoftwareOutputDeviceWinSwapChainTest, FailedPresentDueToDeviceRemoved) { + SetSwapChainExpectations(); + EXPECT_CALL(*mock_dxgi_swapchain_.Get(), Present1) + .WillOnce(testing::Return(DXGI_ERROR_DEVICE_REMOVED)); + EXPECT_CALL(*mock_d3d11_device_.Get(), GetDeviceRemovedReason) + .WillOnce(testing::Return(DXGI_ERROR_DEVICE_REMOVED)); + + DoResize(kTestSize); + DoBeginPaint(kTestSize); + + // There should be no GPU process termination. + device_->EndPaintDelegated( + gfx::Rect(0, 0, kTestSize.width(), kTestSize.height())); +} + +using SoftwareOutputDeviceWinSwapChainDeathTest = + SoftwareOutputDeviceWinSwapChainTest; + +// Ensure the GPU process is terminated if ResizeBuffers fails. +TEST_F(SoftwareOutputDeviceWinSwapChainDeathTest, ResizeBuffersFailure) { + SetSwapChainExpectations(); + ON_CALL(*mock_dxgi_swapchain_.Get(), + ResizeBuffers(/*BufferCount=*/2, /*Width=*/1180, /*Height=*/620, + /*NewFormat=*/testing::_, /*SwapChainFlags=*/0)) + .WillByDefault(testing::Return(E_FAIL)); + + // Do first resize and ensure it is successful. We don't expect ResizeBuffers + // to be called here as it's the first Resize and the SwapChain will be + // initialized in the scall. + DoResize(kTestSize); + + // SwapChain should be initialized, resulting in a ResizeBuffers call; which + // should fail triggering a crash. + EXPECT_DEATH(device_->Resize(gfx::Size(1180, 620), 1.f), ""); +} + +// Test that ResizeDelegated results in a process crash if +// CreateSwapChainForComposition fails. +TEST_F(SoftwareOutputDeviceWinSwapChainDeathTest, + CreateSwapSchainForCompositionFailure) { + ON_CALL(*mock_dcomp_device_.Get(), CreateTargetForHwnd) + .WillByDefault( + media::SetComPointeeAndReturnOk<2>(mock_dcomp_target_.Get())); + ON_CALL(*mock_dcomp_device_.Get(), CreateVisual) + .WillByDefault( + media::SetComPointeeAndReturnOk<0>(mock_dcomp_visual_.Get())); + ON_CALL(*mock_dxgi_factory_.Get(), CreateSwapChainForComposition) + .WillByDefault(testing::Return(E_OUTOFMEMORY)); + EXPECT_DEATH(device_->Resize(kTestSize, 1.f), ""); +} + +} // namespace viz
diff --git a/components/viz/service/display_embedder/test_support/dcomp_mocks.cc b/components/viz/service/display_embedder/test_support/dcomp_mocks.cc new file mode 100644 index 0000000..0c7bbb5d --- /dev/null +++ b/components/viz/service/display_embedder/test_support/dcomp_mocks.cc
@@ -0,0 +1,18 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "components/viz/service/display_embedder/test_support/dcomp_mocks.h" + +namespace media { + +DCompositionDeviceMock::DCompositionDeviceMock() = default; +DCompositionDeviceMock::~DCompositionDeviceMock() = default; + +DCompositionTargetMock::DCompositionTargetMock() = default; +DCompositionTargetMock::~DCompositionTargetMock() = default; + +DCompositionVisualMock::DCompositionVisualMock() = default; +DCompositionVisualMock::~DCompositionVisualMock() = default; + +} // namespace media
diff --git a/components/viz/service/display_embedder/test_support/dcomp_mocks.h b/components/viz/service/display_embedder/test_support/dcomp_mocks.h new file mode 100644 index 0000000..21ad2a36d --- /dev/null +++ b/components/viz/service/display_embedder/test_support/dcomp_mocks.h
@@ -0,0 +1,153 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_TEST_SUPPORT_DCOMP_MOCKS_H_ +#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_TEST_SUPPORT_DCOMP_MOCKS_H_ + +#include <dcomp.h> +#include <wrl.h> + +#include "media/base/win/test_utils.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace media { + +// Example mock for IDCompositionDevice, modeled after D3D11DeviceMock. +class DCompositionDeviceMock + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, + IDCompositionDevice> { + public: + DCompositionDeviceMock(); + ~DCompositionDeviceMock() override; + + // IUnknown + MOCK_STDCALL_METHOD2(QueryInterface, HRESULT(REFIID, void**)); + MOCK_STDCALL_METHOD0(AddRef, ULONG()); + MOCK_STDCALL_METHOD0(Release, ULONG()); + + // IDCompositionDevice + MOCK_STDCALL_METHOD0(Commit, HRESULT()); + MOCK_STDCALL_METHOD0(WaitForCommitCompletion, HRESULT()); + MOCK_STDCALL_METHOD1(GetFrameStatistics, + HRESULT(DCOMPOSITION_FRAME_STATISTICS*)); + MOCK_STDCALL_METHOD3(CreateTargetForHwnd, + HRESULT(HWND, BOOL, IDCompositionTarget**)); + MOCK_STDCALL_METHOD1(CreateVisual, HRESULT(IDCompositionVisual**)); + MOCK_STDCALL_METHOD5(CreateSurface, + HRESULT(UINT, + UINT, + DXGI_FORMAT, + DXGI_ALPHA_MODE, + IDCompositionSurface**)); + MOCK_STDCALL_METHOD5(CreateVirtualSurface, + HRESULT(UINT, + UINT, + DXGI_FORMAT, + DXGI_ALPHA_MODE, + IDCompositionVirtualSurface**)); + MOCK_STDCALL_METHOD2(CreateSurfaceFromHandle, HRESULT(HANDLE, IUnknown**)); + MOCK_STDCALL_METHOD2(CreateSurfaceFromHwnd, HRESULT(HWND, IUnknown**)); + MOCK_STDCALL_METHOD1(CreateTranslateTransform, + HRESULT(IDCompositionTranslateTransform**)); + MOCK_STDCALL_METHOD1(CreateScaleTransform, + HRESULT(IDCompositionScaleTransform**)); + MOCK_STDCALL_METHOD1(CreateRotateTransform, + HRESULT(IDCompositionRotateTransform**)); + MOCK_STDCALL_METHOD1(CreateSkewTransform, + HRESULT(IDCompositionSkewTransform**)); + MOCK_STDCALL_METHOD1(CreateMatrixTransform, + HRESULT(IDCompositionMatrixTransform**)); + MOCK_STDCALL_METHOD3(CreateTransformGroup, + HRESULT(IDCompositionTransform**, + UINT, + IDCompositionTransform**)); + MOCK_STDCALL_METHOD1(CreateTranslateTransform3D, + HRESULT(IDCompositionTranslateTransform3D**)); + MOCK_STDCALL_METHOD1(CreateScaleTransform3D, + HRESULT(IDCompositionScaleTransform3D**)); + MOCK_STDCALL_METHOD1(CreateRotateTransform3D, + HRESULT(IDCompositionRotateTransform3D**)); + MOCK_STDCALL_METHOD1(CreateMatrixTransform3D, + HRESULT(IDCompositionMatrixTransform3D**)); + MOCK_STDCALL_METHOD3(CreateTransform3DGroup, + HRESULT(IDCompositionTransform3D**, + UINT, + IDCompositionTransform3D**)); + MOCK_STDCALL_METHOD1(CreateEffectGroup, HRESULT(IDCompositionEffectGroup**)); + MOCK_STDCALL_METHOD1(CreateRectangleClip, + HRESULT(IDCompositionRectangleClip**)); + MOCK_STDCALL_METHOD1(CreateAnimation, HRESULT(IDCompositionAnimation**)); + MOCK_STDCALL_METHOD1(CheckDeviceState, HRESULT(BOOL*)); +}; + +class DCompositionTargetMock + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, + IDCompositionTarget> { + public: + DCompositionTargetMock(); + ~DCompositionTargetMock() override; + + // IUnknown + MOCK_STDCALL_METHOD2(QueryInterface, HRESULT(REFIID, void**)); + MOCK_STDCALL_METHOD0(AddRef, ULONG()); + MOCK_STDCALL_METHOD0(Release, ULONG()); + + // IDCompositionTarget + MOCK_STDCALL_METHOD1(SetRoot, HRESULT(IDCompositionVisual*)); +}; + +class DCompositionVisualMock + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, + IDCompositionVisual> { + public: + DCompositionVisualMock(); + ~DCompositionVisualMock() override; + + // IUnknown + MOCK_STDCALL_METHOD2(QueryInterface, HRESULT(REFIID riid, void** ppvObject)); + MOCK_STDCALL_METHOD0(AddRef, ULONG()); + MOCK_STDCALL_METHOD0(Release, ULONG()); + + // IDCompositionVisual (with all overloaded methods left as-is) + MOCK_STDCALL_METHOD1(SetOffsetX, HRESULT(float offsetX)); + MOCK_STDCALL_METHOD1(SetOffsetX, HRESULT(IDCompositionAnimation* animation)); + + MOCK_STDCALL_METHOD1(SetOffsetY, HRESULT(float offsetY)); + MOCK_STDCALL_METHOD1(SetOffsetY, HRESULT(IDCompositionAnimation* animation)); + + MOCK_STDCALL_METHOD1(SetTransform, HRESULT(const D2D_MATRIX_3X2_F& matrix)); + MOCK_STDCALL_METHOD1(SetTransform, + HRESULT(IDCompositionTransform* transform)); + + MOCK_STDCALL_METHOD1(SetTransformParent, + HRESULT(IDCompositionVisual* visual)); + MOCK_STDCALL_METHOD1(SetEffect, HRESULT(IDCompositionEffect* effect)); + + MOCK_STDCALL_METHOD1(SetBitmapInterpolationMode, + HRESULT(DCOMPOSITION_BITMAP_INTERPOLATION_MODE mode)); + MOCK_STDCALL_METHOD1(SetBorderMode, HRESULT(DCOMPOSITION_BORDER_MODE mode)); + + // The interface calls these "SetClip", so we keep them as such: + MOCK_STDCALL_METHOD1(SetClip, HRESULT(const D2D_RECT_F& rect)); + MOCK_STDCALL_METHOD1(SetClip, HRESULT(IDCompositionClip* clip)); + + MOCK_STDCALL_METHOD1(SetContent, HRESULT(IUnknown* content)); + + MOCK_STDCALL_METHOD3(AddVisual, + HRESULT(IDCompositionVisual* visual, + BOOL insertAbove, + IDCompositionVisual* referenceVisual)); + MOCK_STDCALL_METHOD1(RemoveVisual, HRESULT(IDCompositionVisual* visual)); + MOCK_STDCALL_METHOD0(RemoveAllVisuals, HRESULT()); + + MOCK_STDCALL_METHOD1(SetCompositeMode, + HRESULT(DCOMPOSITION_COMPOSITE_MODE mode)); +}; + +} // namespace media + +#endif // COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_TEST_SUPPORT_DCOMP_MOCKS_H_
diff --git a/components/webapps/services/web_app_origin_association/web_app_origin_association_parser_impl_unittest.cc b/components/webapps/services/web_app_origin_association/web_app_origin_association_parser_impl_unittest.cc index 28dec86d..a8e2421 100644 --- a/components/webapps/services/web_app_origin_association/web_app_origin_association_parser_impl_unittest.cc +++ b/components/webapps/services/web_app_origin_association/web_app_origin_association_parser_impl_unittest.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "base/json/json_reader.h" #include "base/run_loop.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" @@ -117,7 +118,12 @@ ASSERT_TRUE(!association); ASSERT_FALSE(errors.empty()); ASSERT_EQ(1u, errors.size()); - EXPECT_EQ(errors[0]->message, "EOF while parsing a list at line 1 column 5"); + if (base::JSONReader::UsingRust()) { + EXPECT_EQ(errors[0]->message, + "EOF while parsing a list at line 1 column 5"); + } else { + EXPECT_EQ(errors[0]->message, "Line: 1, column: 6, Syntax error."); + } histogram_tester_.ExpectBucketCount( kParseResultHistogram,
diff --git a/components/webapps/services/web_app_origin_association/web_app_origin_association_parser_unittest.cc b/components/webapps/services/web_app_origin_association/web_app_origin_association_parser_unittest.cc index 5ad3b20..afa40c9 100644 --- a/components/webapps/services/web_app_origin_association/web_app_origin_association_parser_unittest.cc +++ b/components/webapps/services/web_app_origin_association/web_app_origin_association_parser_unittest.cc
@@ -4,6 +4,7 @@ #include "components/webapps/services/web_app_origin_association/web_app_origin_association_parser.h" +#include "base/json/json_reader.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" #include "url/origin.h" @@ -64,7 +65,11 @@ EXPECT_TRUE(IsAssociationNull(association)); EXPECT_EQ(1u, GetErrorCount()); - EXPECT_EQ(errors()[0], "EOF while parsing a value at line 1 column 0"); + if (base::JSONReader::UsingRust()) { + EXPECT_EQ(errors()[0], "EOF while parsing a value at line 1 column 0"); + } else { + EXPECT_EQ(errors()[0], "Line: 1, column: 1, Unexpected token."); + } } TEST_F(WebAppOriginAssociationParserTest, NoContentParses) {
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index bdc48f4..cf87c47 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -2072,9 +2072,6 @@ "screenlock_monitor/screenlock_monitor_device_source.h", "screenlock_monitor/screenlock_monitor_source.cc", "screenlock_monitor/screenlock_monitor_source.h", - "security/coop/coop_related_group.cc", - "security/coop/coop_related_group.h", - "security/coop/coop_swap_result.h", "security/coop/cross_origin_isolation_mode.h", "security/coop/cross_origin_opener_policy_access_report_manager.cc", "security/coop/cross_origin_opener_policy_access_report_manager.h",
diff --git a/content/browser/browsing_instance.cc b/content/browser/browsing_instance.cc index 88a4025..3d6bc8e 100644 --- a/content/browser/browsing_instance.cc +++ b/content/browser/browsing_instance.cc
@@ -9,7 +9,6 @@ #include "base/containers/contains.h" #include "content/browser/child_process_security_policy_impl.h" #include "content/browser/origin_agent_cluster_isolation_state.h" -#include "content/browser/security/coop/coop_related_group.h" #include "content/browser/site_info.h" #include "content/browser/site_instance_group.h" #include "content/browser/site_instance_impl.h" @@ -32,9 +31,7 @@ const WebExposedIsolationInfo& web_exposed_isolation_info, bool is_guest, bool is_fenced, - bool is_fixed_storage_partition, - const scoped_refptr<CoopRelatedGroup>& coop_related_group, - std::optional<url::Origin> common_coop_origin) + bool is_fixed_storage_partition) : isolation_context_( BrowsingInstanceId::FromUnsafeValue(next_browsing_instance_id_++), BrowserOrResourceContext(browser_context), @@ -45,23 +42,11 @@ active_contents_count_(0u), default_site_instance_(nullptr), web_exposed_isolation_info_(web_exposed_isolation_info), - coop_related_group_(coop_related_group), - common_coop_origin_(common_coop_origin), is_fixed_storage_partition_(is_fixed_storage_partition) { DCHECK(browser_context); if (is_guest) { CHECK(is_fixed_storage_partition); } - - // If we get passed an empty group, build a new one. This is the common case. - if (!coop_related_group_) { - coop_related_group_ = - base::WrapRefCounted<CoopRelatedGroup>(new CoopRelatedGroup( - browser_context, is_guest, is_fenced, is_fixed_storage_partition_)); - } - DCHECK(coop_related_group_); - - coop_related_group_->RegisterBrowsingInstance(this); } BrowserContext* BrowsingInstance::GetBrowserContext() const { @@ -142,14 +127,6 @@ return instance; } -scoped_refptr<SiteInstanceImpl> -BrowsingInstance::GetCoopRelatedSiteInstanceForURL( - const UrlInfo& url_info, - bool allow_default_instance) { - return coop_related_group_->GetCoopRelatedSiteInstanceForURL( - url_info, allow_default_instance); -} - scoped_refptr<SiteInstanceImpl> BrowsingInstance::GetSiteInstanceForURLHelper( const UrlInfo& url_info, bool allow_default_instance) { @@ -260,8 +237,6 @@ ChildProcessSecurityPolicyImpl::GetInstance(); policy->RemoveOptInIsolatedOriginsForBrowsingInstance( isolation_context_.browsing_instance_id()); - - coop_related_group_->UnregisterBrowsingInstance(this); } SiteInfo BrowsingInstance::ComputeSiteInfoForURL( @@ -339,21 +314,13 @@ return result; } -size_t BrowsingInstance::GetCoopRelatedGroupActiveContentsCount() { - return coop_related_group_->active_contents_count(); -} - void BrowsingInstance::IncrementActiveContentsCount() { active_contents_count_++; - - coop_related_group_->increment_active_contents_count(); } void BrowsingInstance::DecrementActiveContentsCount() { DCHECK_LT(0u, active_contents_count_); active_contents_count_--; - - coop_related_group_->decrement_active_contents_count(); } } // namespace content
diff --git a/content/browser/browsing_instance.h b/content/browser/browsing_instance.h index ad176257..e8b90bf1 100644 --- a/content/browser/browsing_instance.h +++ b/content/browser/browsing_instance.h
@@ -15,7 +15,6 @@ #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "content/browser/isolation_context.h" -#include "content/browser/security/coop/coop_related_group.h" #include "content/browser/web_exposed_isolation_info.h" #include "content/common/content_export.h" #include "content/public/browser/browser_context.h" @@ -59,10 +58,10 @@ // be manually deleted. // // BrowsingInstance has no public members, as it is designed to be -// visible only from the SiteInstance and CoopRelatedGroup classes. To get a new -// SiteInstance that is part of the same BrowsingInstance, use -// SiteInstance::GetRelatedSiteInstance. Because of this, BrowsingInstances and -// SiteInstances are tested together in site_instance_unittest.cc. +// visible only from the SiteInstance class. To get a new SiteInstance that is +// part of the same BrowsingInstance, use SiteInstance::GetRelatedSiteInstance. +// Because of this, BrowsingInstances and SiteInstances are tested together in +// site_instance_unittest.cc. // // Note that a browsing instance in the browser is independently tracked in // the renderer inside blink::Page::RelatedPages() method (in theory the browser @@ -79,7 +78,6 @@ friend class base::RefCounted<BrowsingInstance>; friend class SiteInstanceGroup; friend class SiteInstanceImpl; - friend class CoopRelatedGroup; FRIEND_TEST_ALL_PREFIXES(SiteInstanceGroupTest, BrowsingInstanceLifetime); FRIEND_TEST_ALL_PREFIXES(SiteInstanceTest, OneSiteInstancePerSite); FRIEND_TEST_ALL_PREFIXES(SiteInstanceTest, @@ -108,23 +106,12 @@ // if `is_guest` is true. Note that `is_guest`, `is_fenced`, and // `is_fixed_storage_partition` cannot change over the lifetime of the // BrowsingInstance. - // - // `coop_related_group` represents the CoopRelatedGroup to which this - // BrowsingInstance belongs. Pages that live in BrowsingInstances in the same - // group can communicate with each other through a subset of the WindowProxy - // APIs. This is only used for COOP logic and for all other cases should - // simply be nullptr. The constructor will take care of building a new group. - // - // If `common_coop_origin` is set, it indicates that all documents hosted by - // the BrowsingInstance have the same COOP value defined by the given origin. explicit BrowsingInstance( BrowserContext* context, const WebExposedIsolationInfo& web_exposed_isolation_info, bool is_guest, bool is_fenced, - bool is_fixed_storage_partition, - const scoped_refptr<CoopRelatedGroup>& coop_related_group, - std::optional<url::Origin> common_coop_origin); + bool is_fixed_storage_partition); ~BrowsingInstance(); @@ -183,14 +170,6 @@ scoped_refptr<SiteInstanceImpl> GetSiteInstanceForSiteInfo( const SiteInfo& site_info); - // Return a SiteInstance in the same CoopRelatedGroup as this - // BrowsingInstance. It might or might not be in a new BrowsingInstance, and - // if it reuses an existing BrowsingInstance of the group, it might reuse an - // appropriate SiteInstance as well. - scoped_refptr<SiteInstanceImpl> GetCoopRelatedSiteInstanceForURL( - const UrlInfo& url_info, - bool allow_default_instance); - // Returns a SiteInfo with site and process-lock URLs for |url_info| that are // identical with what these values would be if we called // GetSiteInstanceForURL() with the same `url_info` and @@ -230,21 +209,10 @@ // BrowsingInstance. void UnregisterSiteInstance(SiteInstanceImpl* site_instance); - // Returns the token uniquely identifying the CoopRelatedGroup this - // BrowsingInstance belongs to. This might be used in the renderer, as opposed - // to IDs. - base::UnguessableToken coop_related_group_token() const { - return coop_related_group_->token(); - } - // Returns the token uniquely identifying this BrowsingInstance. See member // declaration for more context. base::UnguessableToken token() const { return token_; } - // Returns the total number of WebContents either living in this - // BrowsingInstance or that can communicate with it via the CoopRelatedGroup. - size_t GetCoopRelatedGroupActiveContentsCount(); - // Tracks the number of WebContents currently in this BrowsingInstance. // Note: We also separately track the number of WebContents in the entire // CoopRelatedGroup, and keep the per-BrowsingInstance counts for validity @@ -281,9 +249,7 @@ SiteInstanceImpl* default_site_instance() { return default_site_instance_; } - const std::optional<url::Origin>& common_coop_origin() const { - return common_coop_origin_; - } + size_t active_contents_count() { return active_contents_count_; } // The next available browser-global BrowsingInstance ID. static int next_browsing_instance_id_; @@ -334,34 +300,6 @@ // StoragePartitionConfig here. std::optional<StoragePartitionConfig> storage_partition_config_; - // The CoopRelatedGroup this BrowsingInstance belongs to. BrowsingInstances in - // the same CoopRelatedGroup have limited window proxy access to each other. - // In most cases, a CoopRelatedGroup will only contain a single - // BrowsingInstance, unless pages that use COOP: restrict-properties headers - // are involved. - scoped_refptr<CoopRelatedGroup> coop_related_group_; - - // If set, indicates that all documents in this BrowsingInstance share the - // same COOP value defined by the given origin. In practice, this can only be - // the case for COOP: same-origin and COOP: restrict-properties. - // - // For COOP: same-origin, this will be enforced by COOP swap rules and the - // value is recorded for invariant checking. - // - // For COOP: restrict-properties, this is also used to make sure that the - // BrowsingInstance is suitable when we're trying to put a new document into - // an existing BrowsingInstance that is part of the CoopRelatedGroup. To - // prevent unwanted access, a document with COOP: restrict-properties set from - // origin a.com should only be put in a BrowsingInstance that holds such - // documents. This would otherwise break the access guarantees that we have - // given, of only being able to DOM script same-origin same-COOP documents, - // and to have limited cross-origin communication with all other pages. - // - // TODO(crbug.com/40879437): This assumes that popups opened from - // cross-origin iframes are opened with no-opener. Once COOP inheritance for - // those cases is figured out, change the mentions of origin to "COOP origin". - std::optional<url::Origin> common_coop_origin_; - // Set to true if the StoragePartition should be preserved across future // navigations in the frames belonging to this BrowsingInstance. For <webview> // tags, this is always true.
diff --git a/content/browser/interest_group/ad_auction_service_impl_unittest.cc b/content/browser/interest_group/ad_auction_service_impl_unittest.cc index af556d8..04a31b97 100644 --- a/content/browser/interest_group/ad_auction_service_impl_unittest.cc +++ b/content/browser/interest_group/ad_auction_service_impl_unittest.cc
@@ -4224,6 +4224,78 @@ EXPECT_EQ(group.ads.value()[0].render_url(), "https://example.com/render"); } +// UpdateJSONParserCrash fails on Android or with the Rust parser because in +// those conditions the data decoder doesn't use a separate process to parse +// JSON. On other platforms, the C++ parser runs out-of-proc for safety. +#if !BUILDFLAG(IS_ANDROID) + +// The server response is valid, but we simulate the JSON parser (which may +// run in a separate process) crashing, so the update doesn't happen. +TEST_F(AdAuctionServiceImplTest, UpdateJSONParserCrash) { + // Disable the Rust JSON parser, as it is in-process and cannot crash. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatureState(base::features::kUseRustJsonParser, false); + + network_responder_->RegisterUpdateResponse(kUpdateUrlPath, R"({ +"ads": [{"renderURL": "https://example.com/new_render" + }] +})"); + + blink::InterestGroup interest_group = CreateInterestGroup(); + // Set a long expiration delta so that we can advance to the next rate limit + // period without the interest group expiring. + interest_group.expiry = base::Time::Now() + base::Days(30); + interest_group.update_url = kUpdateUrlA; + interest_group.bidding_url = kBiddingLogicUrlA; + interest_group.trusted_bidding_signals_url = kTrustedBiddingSignalsUrlA; + interest_group.trusted_bidding_signals_keys.emplace(); + interest_group.trusted_bidding_signals_keys->push_back("key1"); + interest_group.ads.emplace(); + blink::InterestGroup::Ad ad( + /*render_gurl=*/GURL("https://example.com/render"), + /*metadata=*/std::nullopt); + interest_group.ads->emplace_back(std::move(ad)); + JoinInterestGroupAndFlush(interest_group); + EXPECT_EQ(1, GetJoinCount(kOriginA, kInterestGroupName)); + + // Simulate the JSON service crashing instead of returning a result. + data_decoder::test::InProcessDataDecoder in_process_data_decoder; + in_process_data_decoder.SimulateJsonParserCrash( + /*drop=*/true); + + UpdateInterestGroupNoFlush(); + task_environment()->RunUntilIdle(); + + // Check that the ads didn't change. + scoped_refptr<StorageInterestGroups> groups = + GetInterestGroupsForOwner(kOriginA); + ASSERT_EQ(groups->size(), 1u); + auto group = groups->GetInterestGroups()[0]->interest_group; + ASSERT_TRUE(group.ads.has_value()); + ASSERT_EQ(group.ads->size(), 1u); + EXPECT_EQ(group.ads.value()[0].render_url(), "https://example.com/render"); + + // Try another IG update, this time with no crash. It should succceed. + // (We need to advance time since this next attempt is rate-limited). + in_process_data_decoder.SimulateJsonParserCrash( + /*drop=*/false); + task_environment()->FastForwardBy( + InterestGroupStorage::kUpdateSucceededBackoffPeriod); + UpdateInterestGroupNoFlush(); + task_environment()->RunUntilIdle(); + + // Check that the ads *did* change this time. + groups = GetInterestGroupsForOwner(kOriginA); + ASSERT_EQ(groups->size(), 1u); + group = groups->GetInterestGroups()[0]->interest_group; + ASSERT_TRUE(group.ads.has_value()); + ASSERT_EQ(group.ads->size(), 1u); + EXPECT_EQ(group.ads.value()[0].render_url(), + "https://example.com/new_render"); +} + +#endif // !BUILDFLAG(IS_ANDROID) + // Trigger an update, but block it via ContentBrowserClient policy. // The update shouldn't happen. TEST_F(AdAuctionServiceImplTest, UpdateBlockedByContentBrowserClient) {
diff --git a/content/browser/preloading/prerender/prerender_browsertest.cc b/content/browser/preloading/prerender/prerender_browsertest.cc index db95f8b..c194b59 100644 --- a/content/browser/preloading/prerender/prerender_browsertest.cc +++ b/content/browser/preloading/prerender/prerender_browsertest.cc
@@ -15046,77 +15046,9 @@ EXPECT_FALSE(prerender_observer.was_activated()); } -class PrerenderWarmUpCompositorBrowserTest - : public PrerenderBrowserTest, - public testing::WithParamInterface<std::tuple<bool, bool, std::string>> { - public: - static std::string DescribeParams( - const testing::TestParamInfo<ParamType>& info) { - auto [warm_up_compositor, prerender2_warm_up_compositor, - prerender2_warm_up_compositor_trigger_point] = info.param; - std::stringstream params_description; - params_description << "kWarmUpCompositor"; - params_description << (warm_up_compositor ? "Enabled" : "Disabled"); - params_description << "_kPrerender2WarmUpCompositor"; - params_description << (prerender2_warm_up_compositor ? "Enabled" - : "Disabled"); - params_description << "_" << prerender2_warm_up_compositor_trigger_point; - return params_description.str(); - } - - PrerenderWarmUpCompositorBrowserTest() { - std::vector<base::test::FeatureRefAndParams> enabled_features; - std::vector<base::test::FeatureRef> disabled_features; - auto [warm_up_compositor, prerender2_warm_up_compositor, - prerender2_warm_up_compositor_trigger_point] = GetParam(); - if (warm_up_compositor) { - enabled_features.push_back({features::kWarmUpCompositor, {}}); - } else { - disabled_features.push_back(features::kWarmUpCompositor); - } - - if (prerender2_warm_up_compositor) { - enabled_features.push_back( - {blink::features::kPrerender2WarmUpCompositor, - {{"trigger_point", prerender2_warm_up_compositor_trigger_point}}}); - } else { - disabled_features.push_back(blink::features::kPrerender2WarmUpCompositor); - } - - feature_list_.InitWithFeaturesAndParameters(enabled_features, - disabled_features); - } - - private: - base::test::ScopedFeatureList feature_list_; -}; - -INSTANTIATE_TEST_SUITE_P( - All, - PrerenderWarmUpCompositorBrowserTest, - // Flips `kWarmUpCompositor` (cc) and `kPrerender2WarmUpCompositor`(blink) - // and puts the value of `kPrerender2WarmUpCompositorTriggerPoint` (if - // latter flag is enabled). - testing::Values( - std::make_tuple(true, true, "did_commit_load"), - std::make_tuple(true, true, "did_dispatch_dom_content_loaded_event"), - std::make_tuple(true, true, "did_finish_load"), - // `kWarmUpCompositor` controls the independent cc internal feature of - // warming up, and `kPrerender2WarmUpCompositor` manages the trigger - // point of that feature for prerender case. Therefore, warming up on - // prerender should not performed in the first place unless both flags - // are enabled. - std::make_tuple(true, false, ""), - std::make_tuple(false, true, "did_commit_load"), - std::make_tuple(false, true, "did_dispatch_dom_content_loaded_event"), - std::make_tuple(false, true, "did_finish_load")), - PrerenderWarmUpCompositorBrowserTest::DescribeParams); - -// Test that the prerendering page does not crash when enabling compositor -// warming up features. -// TODO(crbug.com/41496019): Check whether the warming up is actually happening. -IN_PROC_BROWSER_TEST_P(PrerenderWarmUpCompositorBrowserTest, - WarmingUpCCDoesntInvokeCrashes) { +// Tests that the prerendering page does not crash when performing compositor +// warming up. +IN_PROC_BROWSER_TEST_F(PrerenderBrowserTest, WarmingUpCCDoesntInvokeCrashes) { const GURL initial_url = GetUrl("/empty.html"); const GURL prerendering_url = GetUrl("/empty.html?prerender");
diff --git a/content/browser/renderer_host/browsing_context_group_swap.cc b/content/browser/renderer_host/browsing_context_group_swap.cc index e242be90..9f1856f 100644 --- a/content/browser/renderer_host/browsing_context_group_swap.cc +++ b/content/browser/renderer_host/browsing_context_group_swap.cc
@@ -23,11 +23,6 @@ ShouldSwapBrowsingInstance::kYes_ForceSwap}; } -BrowsingContextGroupSwap BrowsingContextGroupSwap::CreateRelatedCoopSwap() { - return {BrowsingContextGroupSwapType::kRelatedCoopSwap, - ShouldSwapBrowsingInstance::kYes_ForceSwap}; -} - BrowsingContextGroupSwap BrowsingContextGroupSwap::CreateSecuritySwap() { return {BrowsingContextGroupSwapType::kSecuritySwap, ShouldSwapBrowsingInstance::kYes_ForceSwap}; @@ -44,7 +39,6 @@ return false; case BrowsingContextGroupSwapType::kCoopSwap: - case BrowsingContextGroupSwapType::kRelatedCoopSwap: case BrowsingContextGroupSwapType::kSecuritySwap: case BrowsingContextGroupSwapType::kProactiveSwap: return true; @@ -57,7 +51,6 @@ case BrowsingContextGroupSwapType::kNoSwap: case BrowsingContextGroupSwapType::kSecuritySwap: case BrowsingContextGroupSwapType::kProactiveSwap: - case BrowsingContextGroupSwapType::kRelatedCoopSwap: return false; case BrowsingContextGroupSwapType::kCoopSwap: @@ -74,7 +67,6 @@ return false; case BrowsingContextGroupSwapType::kCoopSwap: - case BrowsingContextGroupSwapType::kRelatedCoopSwap: return true; } NOTREACHED();
diff --git a/content/browser/renderer_host/browsing_context_group_swap.h b/content/browser/renderer_host/browsing_context_group_swap.h index 68da509..954d7c6 100644 --- a/content/browser/renderer_host/browsing_context_group_swap.h +++ b/content/browser/renderer_host/browsing_context_group_swap.h
@@ -19,13 +19,6 @@ kNoSwap, // Used for swaps forced by a non matching COOP policy. kCoopSwap, - // Used for some swaps forced by a non matching COOP: restrict-properties - // policy. It puts the new document into a related browsing context group. - // - // Contrary to unrelated BrowsingContext groups, the communication in between - // two related browsing context groups is possible, but limited to using - // Window.postMessage() and Window.closed only. - kRelatedCoopSwap, // Used for swaps forced by a non-COOP security reason. This could be a // navigation from a WebUI page to a normal page for example. kSecuritySwap, @@ -48,20 +41,11 @@ static BrowsingContextGroupSwap CreateProactiveSwap( ShouldSwapBrowsingInstance reason); - // CreateRelatedCoopSwap() should only be used in cases where we can - // guarantee that we will not reuse the current browsing context group as part - // of the CoopRelatedGroup reuse mechanism. If the browsing context group ends - // up being reused, this will very likely cause a crash. Cases with - // CoopSwapResult::kRelatedSwap should provide such guarantees. - static BrowsingContextGroupSwap CreateRelatedCoopSwap(); - BrowsingContextGroupSwapType type() const { return type_; } ShouldSwapBrowsingInstance reason() const { return reason_.value(); } // Returns whether we should use a different browsing context group for the - // navigation. Note that this does not indicate whether it should stay in the - // same CoopRelatedGroup. To know if it should, verify type() == - // kRelatedCoopSwap. + // navigation. bool ShouldSwap() const; // Indicates whether the proxies to other documents in this browsing context
diff --git a/content/browser/renderer_host/browsing_context_group_swap_unittest.cc b/content/browser/renderer_host/browsing_context_group_swap_unittest.cc index 4e32c8d..e22c4af 100644 --- a/content/browser/renderer_host/browsing_context_group_swap_unittest.cc +++ b/content/browser/renderer_host/browsing_context_group_swap_unittest.cc
@@ -42,19 +42,6 @@ EXPECT_EQ(ShouldSwapBrowsingInstance::kYes_ForceSwap, coop_swap.reason()); } -TEST(BrowsingContextGroupSwap, CreateRelatedCoopSwap) { - BrowsingContextGroupSwap related_coop_swap = - BrowsingContextGroupSwap::CreateRelatedCoopSwap(); - - EXPECT_EQ(BrowsingContextGroupSwapType::kRelatedCoopSwap, - related_coop_swap.type()); - EXPECT_TRUE(related_coop_swap.ShouldSwap()); - EXPECT_FALSE(related_coop_swap.ShouldClearProxiesOnCommit()); - EXPECT_TRUE(related_coop_swap.ShouldClearWindowName()); - EXPECT_EQ(ShouldSwapBrowsingInstance::kYes_ForceSwap, - related_coop_swap.reason()); -} - TEST(BrowsingContextGroupSwap, CreateSecuritySwap) { BrowsingContextGroupSwap security_swap = BrowsingContextGroupSwap::CreateSecuritySwap();
diff --git a/content/browser/renderer_host/browsing_context_state.cc b/content/browser/renderer_host/browsing_context_state.cc index 208f4c2..90f3db4 100644 --- a/content/browser/renderer_host/browsing_context_state.cc +++ b/content/browser/renderer_host/browsing_context_state.cc
@@ -38,12 +38,10 @@ BrowsingContextState::BrowsingContextState( blink::mojom::FrameReplicationStatePtr replication_state, RenderFrameHostImpl* parent, - std::optional<BrowsingInstanceId> browsing_instance_id, - std::optional<base::UnguessableToken> coop_related_group_token) + std::optional<BrowsingInstanceId> browsing_instance_id) : replication_state_(std::move(replication_state)), parent_(parent), - browsing_instance_id_(browsing_instance_id), - coop_related_group_token_(coop_related_group_token) { + browsing_instance_id_(browsing_instance_id) { TRACE_EVENT_BEGIN("navigation", "BrowsingContextState", perfetto::Track::FromPointer(this), "browsing_context_state_when_created", this); @@ -78,7 +76,7 @@ // CHECK to verify that the proxy is being accessed from the correct // BrowsingContextState. As both BrowsingContextState (in non-legacy mode) // and RenderFrameProxyHost (via SiteInstance) are tied to a given - // CoopRelatedGroup, the CoopRelatedGroupId of the BrowsingContextState + // BrowsingInstance, the browsing_instance_id of the BrowsingContextState // (in the non-legacy mode) and of the SiteInstanceGroup should match. If // they do not, the code calling this method has likely chosen the wrong // BrowsingContextState (e.g. one from the current RenderFrameHost rather @@ -89,8 +87,8 @@ // Note: Outer delegates are an exception, and when we're expecting to // interact with one, we should pass in the proper `proxy_access_mode` to // not end up in this condition. - CHECK_EQ(coop_related_group_token_.value(), - site_instance_group->coop_related_group_token()); + CHECK_EQ(browsing_instance_id_.value(), + site_instance_group->browsing_instance_id()); } auto it = proxy_hosts_.find(site_instance_group->GetId()); if (it != proxy_hosts_.end()) { @@ -107,8 +105,8 @@ kSwapForCrossBrowsingInstanceNavigations && proxy_access_mode == ProxyAccessMode::kRegular) { // See comments in GetRenderFrameProxyHost for why this check is needed. - CHECK_EQ(coop_related_group_token_.value(), - site_instance_group->coop_related_group_token()); + CHECK_EQ(browsing_instance_id_.value(), + site_instance_group->browsing_instance_id()); } TRACE_EVENT("navigation", "BrowsingContextState::DeleteRenderFrameProxyHost", ChromeTrackEvent::kBrowsingContextState, this, @@ -142,8 +140,8 @@ kSwapForCrossBrowsingInstanceNavigations && proxy_access_mode == ProxyAccessMode::kRegular) { // See comments in GetRenderFrameProxyHost for why this check is needed. - CHECK_EQ(coop_related_group_token_.value(), - site_instance_group->coop_related_group_token()); + CHECK_EQ(browsing_instance_id_.value(), + site_instance_group->browsing_instance_id()); } auto site_instance_group_id = site_instance_group->GetId(); @@ -520,11 +518,6 @@ proto->set_browsing_instance_id(browsing_instance_id_.value().value()); } - if (coop_related_group_token_.has_value()) { - proto->set_coop_related_group_token( - coop_related_group_token_.value().ToString()); - } - perfetto::TracedDictionary dict = std::move(proto).AddDebugAnnotations(); dict.Add("this", static_cast<const void*>(this)); }
diff --git a/content/browser/renderer_host/browsing_context_state.h b/content/browser/renderer_host/browsing_context_state.h index aa0f870..2788dfd 100644 --- a/content/browser/renderer_host/browsing_context_state.h +++ b/content/browser/renderer_host/browsing_context_state.h
@@ -11,7 +11,6 @@ #include "base/memory/safe_ref.h" #include "base/unguessable_token.h" #include "content/browser/renderer_host/render_frame_proxy_host.h" -#include "content/browser/security/coop/coop_related_group.h" #include "content/browser/site_instance_group.h" #include "content/public/browser/browsing_instance_id.h" #include "services/network/public/cpp/permissions_policy/permissions_policy_declaration.h" @@ -79,17 +78,14 @@ std::unordered_map<SiteInstanceGroupId, std::unique_ptr<RenderFrameProxyHost>>; - // Currently `browsing_instance_id` and `coop_related_group_id` will be null - // iff the legacy mode is enabled, as the legacy mode BrowsingContextState is - // 1:1 with FrameTreeNode and therefore doesn't have a dedicated associated - // BrowsingInstance or CoopRelatedGroup. - // TODO(crbug.com/40205442): Make `browsing_instance_id` and - // `coop_related_group_id` non-optional when the legacy path is removed. - BrowsingContextState( - blink::mojom::FrameReplicationStatePtr replication_state, - RenderFrameHostImpl* parent, - std::optional<BrowsingInstanceId> browsing_instance_id, - std::optional<base::UnguessableToken> coop_related_group_token); + // Currently `browsing_instance_id` will be null iff the legacy mode is + // enabled, as the legacy mode BrowsingContextState is 1:1 with FrameTreeNode + // and therefore doesn't have a dedicated associated BrowsingInstance. + // TODO(crbug.com/40205442): Make `browsing_instance_id` non-optional when the + // legacy path is removed. + BrowsingContextState(blink::mojom::FrameReplicationStatePtr replication_state, + RenderFrameHostImpl* parent, + std::optional<BrowsingInstanceId> browsing_instance_id); // Returns a const reference to the map of proxy hosts. The keys are // SiteInstanceGroup IDs, the values are RenderFrameProxyHosts. @@ -142,15 +138,13 @@ } // All proxies except outer delegate proxies should belong to the same - // CoopRelatedGroup as their BrowsingContextState. + // BrowsingInstance as their BrowsingContextState. // // When kSwapForCrossBrowsingInstanceNavigations is enabled, we might change // BrowsingContextState during a navigation. To ensure that we haven't mixed - // up things, we CHECK that proxies are in the same CoopRelatedGroup. This - // includes proxies in the BrowsingInstance as well as proxies for COOP: - // restrict-properties related contexts. We do this CHECK in all functions for - // creating, deleting, and accessing proxies. See - // BrowsingContextState::GetRenderFrameProxyHostImpl() for an example. + // up things, we CHECK that proxies are in the same BrowsingInstance. We do + // this CHECK in all functions for creating, deleting, and accessing proxies. + // See BrowsingContextState::GetRenderFrameProxyHostImpl() for an example. // // When we expect to be in one the exception cases we specify it via the // ProxyAccessMode enum below, which will disable the CHECKs. @@ -305,15 +299,13 @@ // main frame BrowsingContextState. const raw_ptr<RenderFrameHostImpl> parent_; - // ID of the BrowsingInstance and token of the CoopRelatedGroup to which this - // BrowsingContextState belongs. Currently `browsing_instance_id` and - // `coop_related_group_token` will be null iff the legacy mode is enabled, as - // the legacy mode BrowsingContextState is 1:1 with FrameTreeNode and - // therefore doesn't have a dedicated associated BrowsingInstance or - // CoopRelatedGroup. TODO(crbug.com/40205442): Make `browsing_instance_id` and - // `coop_related_group_token` non-optional when the legacy path is removed. + // ID of the BrowsingInstance to which this BrowsingContextState belongs. + // Currently `browsing_instance_id` and will be null iff the legacy mode is + // enabled, as the legacy mode BrowsingContextState is 1:1 with FrameTreeNode + // and therefore doesn't have a dedicated associated BrowsingInstance. + // TODO(crbug.com/40205442): Make `browsing_instance_id` non-optional when the + // legacy path is removed. const std::optional<BrowsingInstanceId> browsing_instance_id_; - const std::optional<base::UnguessableToken> coop_related_group_token_; base::WeakPtrFactory<BrowsingContextState> weak_factory_{this}; };
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index 8a0e2b9..dccc2e0 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -4132,13 +4132,6 @@ .WithCrossOriginIsolationKey(cross_origin_isolation_key) .WithIsPdf(is_pdf_); - // Records in the UrlInfo if COOP: same-origin or COOP: restrict-properties - // was set, and from which origin. - auto common_coop_origin = ComputeCommonCoopOrigin(); - if (common_coop_origin.has_value()) { - url_info_init.WithCommonCoopOrigin(common_coop_origin.value()); - } - // Navigations with SiteInstances which have fixed storage partition (e.g. // <webview> tags) should always stay in the current StoragePartition. SiteInstanceImpl* current_instance = @@ -6736,8 +6729,7 @@ frame_tree_node_->current_frame_host()->GetSiteInstance(); SiteInstanceImpl* target_site_instance = activated_entry->render_frame_host()->GetSiteInstance(); - CHECK(!target_site_instance->IsCoopRelatedSiteInstance( - current_site_instance)); + CHECK(!target_site_instance->IsRelatedSiteInstance(current_site_instance)); browsing_context_group_swap_ = BrowsingContextGroupSwap::CreateSecuritySwap(); @@ -10668,42 +10660,6 @@ : WebExposedIsolationInfo::CreateIsolated(origin); } -std::optional<url::Origin> NavigationRequest::ComputeCommonCoopOrigin() { - // Embedded content that cannot set COOP directly should inherit their COOP - // common origin from their embedder. For iframes, this is to ensure that they - // do not reuse a SiteInstance in the wrong page. For other embedded - // content it is simply for consistency as they should never try to get - // another SiteInstance in the same CoopRelatedGroup anyway. For this reason - // we use IsOutermostMainFrame. - if (!frame_tree_node_->IsOutermostMainFrame()) { - return frame_tree_node_->current_frame_host() - ->GetMainFrame() - ->GetSiteInstance() - ->GetCommonCoopOrigin(); - } - - using CoopValue = network::mojom::CrossOriginOpenerPolicyValue; - - switch (coop_status().current_coop().value) { - case CoopValue::kSameOrigin: - case CoopValue::kSameOriginPlusCoep: - case CoopValue::kNoopenerAllowPopups: - // If we're early in the navigation process and the PolicyContainer was - // not yet computed, use a best effort origin. - // TODO(crbug.com/40879437): This is probably not very helpful. If - // we have a { Value+Origin } COOP bundle, we should be able to return a - // nullopt value that is distinct from { unsafe-none, nullopt }, similar - // to what exists for WebExposedIsolationInfo. - return policy_container_builder_->HasComputedPolicies() - ? coop_status().current_coop().origin - : GetTentativeOriginAtRequestTime(); - - case CoopValue::kUnsafeNone: - case CoopValue::kSameOriginAllowPopups: - return std::nullopt; - }; -} - void NavigationRequest::MaybeAssignInvalidPrerenderFrameTreeNodeId() { if (!prerender_frame_tree_node_id_.has_value()) { // This navigation won't activate a prerendered page. Otherwise,
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h index 36ff6be..b215ec3 100644 --- a/content/browser/renderer_host/navigation_request.h +++ b/content/browser/renderer_host/navigation_request.h
@@ -2277,18 +2277,6 @@ // a network response yet, or when going to an "about:blank" page. std::optional<WebExposedIsolationInfo> ComputeWebExposedIsolationInfo(); - // Computes whether the navigation is for a document that should live in a - // BrowsingInstance only containing other documents with the same COOP value - // set by the same origin. This is the case if this document or its top-level - // document sets COOP: same-origin or COOP: restrict-properties. If it is a - // top-level document, simply return its origin, otherwise inherit the - // top-level document value. - // - // If the return value is nullopt, it indicates that neither COOP: same-origin - // nor COOP: restrict-properties were used for this document or for its parent - // in the case of a subframe. - std::optional<url::Origin> ComputeCommonCoopOrigin(); - // Assign an invalid frame tree node id to `prerender_frame_tree_node_id_`. // Called as soon as when we are certain that this navigation won't activate a // prerendered page. This is needed because `IsPrerenderedPageActivation()`,
diff --git a/content/browser/renderer_host/navigator.cc b/content/browser/renderer_host/navigator.cc index 9cc3ae7..54ce1ea5 100644 --- a/content/browser/renderer_host/navigator.cc +++ b/content/browser/renderer_host/navigator.cc
@@ -725,9 +725,15 @@ navigation_request->browsing_context_group_swap().ShouldSwap()) { SiteInstanceImpl* final_site_instance = render_frame_host->GetSiteInstance(); + // TODO(crbug.com/412965095): Now that the CoopRelatedGroup no longer + // exists, the BrowsingContextGroupInfo class can be deleted and replaced by + // a simple token, the BrowsingInstance token. In the meantime, just pass + // the BrowsingInstanceToken as a CoopGroupToken so that we do not send an + // empty token. blink::BrowsingContextGroupInfo browsing_context_group_info( final_site_instance->browsing_instance_token(), - final_site_instance->coop_related_group_token()); + /*coop_related_group_token=*/final_site_instance + ->browsing_instance_token()); frame_tree.root()->render_manager()->ExecutePageBroadcastMethod( [&browsing_context_group_info](RenderViewHostImpl* rvh) { if (auto& broadcast = rvh->GetAssociatedPageBroadcast()) {
diff --git a/content/browser/renderer_host/render_frame_host_delegate.cc b/content/browser/renderer_host/render_frame_host_delegate.cc index 94f051a..566e4ba 100644 --- a/content/browser/renderer_host/render_frame_host_delegate.cc +++ b/content/browser/renderer_host/render_frame_host_delegate.cc
@@ -189,12 +189,6 @@ return std::vector<RenderFrameHostImpl*>(); } -std::vector<RenderFrameHostImpl*> -RenderFrameHostDelegate::GetActiveTopLevelDocumentsInCoopRelatedGroup( - RenderFrameHostImpl* render_frame_host) { - return std::vector<RenderFrameHostImpl*>(); -} - PrerenderHostRegistry* RenderFrameHostDelegate::GetPrerenderHostRegistry() { return nullptr; }
diff --git a/content/browser/renderer_host/render_frame_host_delegate.h b/content/browser/renderer_host/render_frame_host_delegate.h index fafbd520..c7bac7c2 100644 --- a/content/browser/renderer_host/render_frame_host_delegate.h +++ b/content/browser/renderer_host/render_frame_host_delegate.h
@@ -704,12 +704,6 @@ GetActiveTopLevelDocumentsInBrowsingContextGroup( RenderFrameHostImpl* render_frame_host); - // Returns the list of top-level RenderFrameHosts hosting active documents - // that belong to the same CoopRelatedGroup as `render_frame_host`. - virtual std::vector<RenderFrameHostImpl*> - GetActiveTopLevelDocumentsInCoopRelatedGroup( - RenderFrameHostImpl* render_frame_host); - // Returns the PrerenderHostRegistry to start/cancel prerendering. This // doesn't return nullptr except for some tests. virtual PrerenderHostRegistry* GetPrerenderHostRegistry();
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index ad821a0..66c2547 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -2588,10 +2588,10 @@ // 1) Their opener in RenderFrameHostImpl::CreateNewWindow(). // 2) Their navigation in RenderFrameHostImpl::DidCommitNavigationInternal(). virtual_browsing_context_group_ = CrossOriginOpenerPolicyAccessReportManager:: - GetNewVirtualBrowsingContextGroup(); + NextVirtualBrowsingContextGroup(); soap_by_default_virtual_browsing_context_group_ = CrossOriginOpenerPolicyAccessReportManager:: - GetNewVirtualBrowsingContextGroup(); + NextVirtualBrowsingContextGroup(); // IdleManager should be unique per RenderFrame to provide proper isolation // of overrides. @@ -9836,12 +9836,12 @@ int popup_virtual_browsing_context_group = params->opener_suppressed ? CrossOriginOpenerPolicyAccessReportManager:: - GetNewVirtualBrowsingContextGroup() + NextVirtualBrowsingContextGroup() : top_level_opener->virtual_browsing_context_group(); int popup_soap_by_default_virtual_browsing_context_group = params->opener_suppressed ? CrossOriginOpenerPolicyAccessReportManager:: - GetNewVirtualBrowsingContextGroup() + NextVirtualBrowsingContextGroup() : top_level_opener->soap_by_default_virtual_browsing_context_group(); // If the opener is suppressed or script access is disallowed, we should @@ -9940,9 +9940,14 @@ new_main_rfh->GetDevToolsFrameToken(), wait_for_debugger, new_main_rfh->GetDocumentToken(), new_main_rfh->policy_container_host()->CreatePolicyContainerForBlink(), + // TODO(crbug.com/412965095): Now that the CoopRelatedGroup no longer + // exists, replace BrowsingContextGroupInfo by a single token. In the + // meantime, just pass the BrowsingInstanceToken as a CoopGroupToken so + // that we do not send an empty token. blink::BrowsingContextGroupInfo( new_main_rfh->GetSiteInstance()->browsing_instance_token(), - new_main_rfh->GetSiteInstance()->coop_related_group_token()), + /*coop_related_group_token=*/new_main_rfh->GetSiteInstance() + ->browsing_instance_token()), delegate_->GetColorProviderColorMaps(), std::move(partitioned_popin_params), /*widget_screen_rect=*/std::nullopt, /*window_screen_rect=*/std::nullopt); @@ -16121,10 +16126,15 @@ CHECK(!commit_params->browsing_context_group_info.has_value()); if (is_main_frame() && navigation_request->browsing_context_group_swap().ShouldSwap()) { + // TODO(crbug.com/412965095): Now that the CoopRelatedGroup no longer + // exists, replace BrowsingContextGroupInfo by a single token. In the + // meantime, just pass the BrowsingInstanceToken as a CoopGroupToken so that + // we do not send an empty token. commit_params->browsing_context_group_info = blink::BrowsingContextGroupInfo( GetSiteInstance()->browsing_instance_token(), - GetSiteInstance()->coop_related_group_token()); + /*coop_related_group_token=*/GetSiteInstance() + ->browsing_instance_token()); } auto* cookie_deprecation_label_manager = @@ -16204,10 +16214,15 @@ CHECK(!commit_params->browsing_context_group_info.has_value()); if (is_main_frame() && navigation_request->browsing_context_group_swap().ShouldSwap()) { + // TODO(crbug.com/412965095): Now that the CoopRelatedGroup no longer + // exists, replace BrowsingContextGroupInfo by a single token. In the + // meantime, just pass the BrowsingInstanceToken as a CoopGroupToken so that + // we do not send an empty token. commit_params->browsing_context_group_info = blink::BrowsingContextGroupInfo( GetSiteInstance()->browsing_instance_token(), - GetSiteInstance()->coop_related_group_token()); + /*coop_related_group_token=*/GetSiteInstance() + ->browsing_instance_token()); } {
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index d26c850e..b61dfcc 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -667,10 +667,7 @@ frame_tree_node_->parent(), is_legacy_browsing_context_state_mode ? static_cast<std::optional<BrowsingInstanceId>>(std::nullopt) - : site_instance->GetBrowsingInstanceId(), - is_legacy_browsing_context_state_mode - ? static_cast<std::optional<base::UnguessableToken>>(std::nullopt) - : site_instance->coop_related_group_token()); + : site_instance->GetBrowsingInstanceId()); browsing_context_state->CommitFramePolicy(initial_main_frame_policy); browsing_context_state->SetFrameName(name, ""); UpdateProcessReusePolicyForProcessPerSiteWithMainFrameThreshold( @@ -719,10 +716,7 @@ frame_tree_node_->parent(), is_legacy_browsing_context_state_mode ? static_cast<std::optional<BrowsingInstanceId>>(std::nullopt) - : site_instance->GetBrowsingInstanceId(), - is_legacy_browsing_context_state_mode - ? static_cast<std::optional<base::UnguessableToken>>(std::nullopt) - : site_instance->coop_related_group_token()); + : site_instance->GetBrowsingInstanceId()); browsing_context_state->CommitFramePolicy(frame_policy); SetRenderFrameHost(CreateRenderFrameHost( CreateFrameCase::kInitChild, site_instance, frame_routing_id, @@ -2569,7 +2563,7 @@ bool is_reload, bool is_same_document, IsSameSiteGetter& is_same_site, - CoopSwapResult coop_swap_result, + bool coop_swap, bool was_server_redirect, bool should_replace_current_entry, bool has_rel_opener) { @@ -2600,7 +2594,7 @@ ShouldSwapBrowsingInstance::kNo_RendererDebugURL); } - if (coop_swap_result == CoopSwapResult::kSwap) { + if (coop_swap) { return BrowsingContextGroupSwap::CreateCoopSwap(); } @@ -2728,14 +2722,6 @@ } } - // We've checked that we didn't need to do a hard BrowsingInstance swap. If - // COOP: restrict-properties asks for it, do a BrowsingInstance swap that - // preserves a reference to the previous BrowsingInstance. Such - // BrowsingInstances are said to be "related". - if (coop_swap_result == CoopSwapResult::kSwapRelated) { - return BrowsingContextGroupSwap::CreateRelatedCoopSwap(); - } - // When doing a history navigation, we cannot assume that the page will behave // in the same way as it did previously. It could change headers, lead to an // error page, etc. We only check the destination_instance once we're done @@ -2745,11 +2731,8 @@ // BrowsingInstance. This is why this block is after security checks, but // before proactive BrowsingInstance swap. if (destination_instance) { - if (!destination_instance->IsCoopRelatedSiteInstance(current_instance)) { - return BrowsingContextGroupSwap::CreateSecuritySwap(); - } if (!destination_instance->IsRelatedSiteInstance(current_instance)) { - return BrowsingContextGroupSwap::CreateRelatedCoopSwap(); + return BrowsingContextGroupSwap::CreateSecuritySwap(); } return BrowsingContextGroupSwap::CreateNoSwap( ShouldSwapBrowsingInstance::kNo_AlreadyHasMatchingBrowsingInstance); @@ -2941,7 +2924,7 @@ IsSameSiteGetter& is_same_site, bool dest_is_view_source_mode, bool was_server_redirect, - CoopSwapResult coop_swap_result, + bool coop_swap, bool should_replace_current_entry, bool force_new_browsing_instance, bool has_rel_opener, @@ -2996,7 +2979,7 @@ current_effective_url, current_is_view_source_mode, source_instance, current_instance, dest_instance, dest_url_info, dest_is_view_source_mode, transition, error_page_process, - is_reload, is_same_document, is_same_site, coop_swap_result, + is_reload, is_same_document, is_same_site, coop_swap, was_server_redirect, should_replace_current_entry, has_rel_opener); @@ -3163,9 +3146,7 @@ // beyond COOP. ProcessReuseOnCOOPType coop_process_reuse_type = ProcessReuseOnCOOPType::kNone; - if (should_swap_result->type() == BrowsingContextGroupSwapType::kCoopSwap || - should_swap_result->type() == - BrowsingContextGroupSwapType::kRelatedCoopSwap) { + if (should_swap_result->type() == BrowsingContextGroupSwapType::kCoopSwap) { if (candidate_instance && candidate_instance != new_instance && candidate_instance->GetSiteInfo() == new_instance->GetSiteInfo()) { coop_process_reuse_type = ProcessReuseOnCOOPType::kDifferentSiteInstance; @@ -3187,9 +3168,7 @@ DCHECK(frame_tree_node_->IsMainFrame()); new_instance->ReuseExistingProcessIfPossible(process_to_reuse); } - if (should_swap_result->type() == BrowsingContextGroupSwapType::kCoopSwap || - should_swap_result->type() == - BrowsingContextGroupSwapType::kRelatedCoopSwap) { + if (should_swap_result->type() == BrowsingContextGroupSwapType::kCoopSwap) { if (new_instance->HasProcess()) { RecordProcessReuseOnCoopResult(coop_process_reuse_type, true); } else { @@ -3358,15 +3337,6 @@ SiteInstanceRelation::RELATED); } - if (browsing_context_group_swap.type() == - BrowsingContextGroupSwapType::kRelatedCoopSwap) { - // If we're dealing with COOP: restrict-properties, we need to stay in the - // same CoopRelatedGroup, so that further navigations get a - // chance to preserve their scriptability. - return SiteInstanceDescriptor( - computed_url_info, SiteInstanceRelation::RELATED_IN_COOP_GROUP); - } - return SiteInstanceDescriptor(computed_url_info, SiteInstanceRelation::UNRELATED); } @@ -3386,29 +3356,6 @@ bool can_use_source_instance = CanUseSourceSiteInstance(dest_url_info, source_instance, was_server_redirect, error_page_process, reason); - if (browsing_context_group_swap.type() == - BrowsingContextGroupSwapType::kRelatedCoopSwap) { - // We typically expect `source_instance` to be in the same BrowsingInstance - // as `current_instance`. However when extensions use the chrome.tabs.update - // API to navigate to about:blank, `source_instance` is set to the - // extension's SiteInstance, which should be in a different - // BrowsingInstance. In that case, `source_instance` should not be in a - // different BrowsingInstance in the same CoopRelatedGroup as - // `current_instance`, but use its own extension's CoopRelatedGroup. Note - // that it can be in another BrowsingInstance in another CoopRelatedGroup, - // which we have to consider for the kSwap case below. - // TODO(crbug.com/40186710): Add a test verifying that we cannot end - // up in that situation using chrome.tabs.update. This could be the case if - // an extension use that API to navigate from a COOP: restrict-properties - // page to about:blank. - CHECK(!can_use_source_instance || - source_instance->IsRelatedSiteInstance(current_instance) || - !source_instance->IsCoopRelatedSiteInstance(current_instance)); - AppendReason(reason, - "DetermineSiteInstanceForURL => related_in_COOP_group"); - return SiteInstanceDescriptor(dest_url_info, - SiteInstanceRelation::RELATED_IN_COOP_GROUP); - } // If a swap is required, we need to force the SiteInstance AND // BrowsingInstance to be different ones, using CreateForURL. @@ -3641,20 +3588,12 @@ bool was_server_redirect) { // Start by verifying that the dest_instance is compatible with the browsing // context group swap decision. - if (browsing_context_group_swap.ShouldSwap()) { - // 1. If we've decided that the target SiteInstance cannot be in the same - // BrowsingInstance, and that the dest_instance is, we should not reuse it. - if (dest_instance->IsRelatedSiteInstance(current_instance)) { - return false; - } - // 2. If we aren't looking for a SiteInstance in the same CoopRelatedGroup, - // then don't use a dest_instance in that group. - if (browsing_context_group_swap.type() != - BrowsingContextGroupSwapType::kRelatedCoopSwap && - dest_instance->IsCoopRelatedSiteInstance(current_instance)) { - return false; - } + // If we've decided that the target SiteInstance cannot be in the same + // BrowsingInstance, and that the dest_instance is, we should not reuse it. + if (browsing_context_group_swap.ShouldSwap() && + dest_instance->IsRelatedSiteInstance(current_instance)) { + return false; } // Note: The later call to IsSuitableForUrlInfo does not have context @@ -3824,11 +3763,6 @@ descriptor.dest_url_info); } - if (descriptor.relation == SiteInstanceRelation::RELATED_IN_COOP_GROUP) { - return current_instance->GetCoopRelatedSiteInstanceImpl( - descriptor.dest_url_info); - } - // At this point we know an unrelated site instance must be returned. // If the current SiteInstance has fixed storage partition (e.g. <webview> @@ -3845,7 +3779,7 @@ // `candidate_instance` is the SiteInstance that was created at request start // time. if (candidate_instance && - !current_instance->IsCoopRelatedSiteInstance(candidate_instance) && + !current_instance->IsRelatedSiteInstance(candidate_instance) && candidate_instance->DoesSiteInfoForURLMatch(dest_url_info)) { return candidate_instance; } @@ -4002,8 +3936,8 @@ SiteInstanceGroup* new_group, bool recovering_without_early_commit, const scoped_refptr<BrowsingContextState>& browsing_context_state) { - // Only create opener proxies if they are in the same CoopRelatedGroup. - if (new_group->IsCoopRelatedSiteInstanceGroup(old_group)) { + // Only create opener proxies if they are in the same BrowsingInstance. + if (new_group->IsRelatedSiteInstanceGroup(old_group)) { CreateOpenerProxies(new_group, frame_tree_node_, browsing_context_state); } else { // Ensure that the frame tree has RenderFrameProxyHosts for the @@ -4287,8 +4221,7 @@ render_frame_host_->browsing_context_state() ->current_replication_state() .Clone(), - frame_tree_node_->parent(), new_instance->GetBrowsingInstanceId(), - new_instance->coop_related_group_token()); + frame_tree_node_->parent(), new_instance->GetBrowsingInstanceId()); // Add a proxy to the outer delegate if one exists, as this is not // copied over to the new BrowsingContextState otherwise. @@ -4515,37 +4448,6 @@ } } -void RenderFrameHostManager::CreateRenderFrameProxyAndAncestorChainIfNeeded( - SiteInstanceGroup* group) { - SiteInstanceGroup* current_site_instance_group = - current_frame_host()->GetSiteInstance()->group(); - CHECK(!group->IsRelatedSiteInstanceGroup(current_site_instance_group)); - CHECK(group->IsCoopRelatedSiteInstanceGroup(current_site_instance_group)); - - // If the frame we need to create a proxy for is a subframe, we need to make - // sure the entire ancestor chain exists as proxies as well, otherwise the - // subframe proxy would be floating around. Note: we only need to create - // ancestors in this frame tree, so we can use IsMainFrame(). - std::vector<FrameTreeNode*> ancestor_chain; - FrameTreeNode* ancestor = frame_tree_node_; - while (ancestor) { - ancestor_chain.push_back(ancestor); - if (ancestor->IsMainFrame()) { - ancestor = nullptr; - } else { - ancestor = ancestor->parent()->frame_tree_node(); - } - } - - // Create proxies, from the top-level frame down to the initially specified - // subframe. TODO(crbug.com/40186710): Verify that the behavior is - // correct if the frame is pending deletion. - for (FrameTreeNode* node : base::Reversed(ancestor_chain)) { - node->render_manager()->CreateRenderFrameProxy( - group, node->current_frame_host()->browsing_context_state()); - } -} - void RenderFrameHostManager::CreateProxiesForChildFrame(FrameTreeNode* child) { TRACE_EVENT_INSTANT( "navigation", "RenderFrameHostManager::CreateProxiesForChildFrame_Parent", @@ -4768,7 +4670,7 @@ request->ComputeErrorPageProcess(), is_reload, request->IsSameDocument(), is_same_site, request->commit_params().is_view_source, request->WasServerRedirect(), - request->coop_status().browsing_instance_swap_result(), + request->coop_status().browsing_instance_swap(), request->common_params().should_replace_current_entry, request->force_new_browsing_instance(), request->begin_params().has_rel_opener, browsing_context_group_swap, @@ -5567,8 +5469,7 @@ void RenderFrameHostManager::CollectOpenerFrameTrees( SiteInstanceGroup* site_instance_group, std::vector<FrameTree*>* opener_frame_trees, - std::unordered_set<FrameTreeNode*>* nodes_with_back_links, - std::unordered_set<FrameTreeNode*>* cross_browsing_context_group_openers) { + std::unordered_set<FrameTreeNode*>* nodes_with_back_links) { CHECK(opener_frame_trees); opener_frame_trees->push_back(&frame_tree_node_->frame_tree()); @@ -5586,27 +5487,6 @@ if (!node->opener()) continue; - // Do not iterate recursively on FrameTrees in different BrowsingInstances - // in the same CoopRelatedGroup. Instead, simply record the direct opener - // in `cross_browsing_context_group_openers`. We can end up here with - // BrowsingInstance not in the same CoopRelatedGroup for rare cases - // involving outer delegate proxies. For example when a chrome app webview - // gets a new opener, we will iterate this opener tree and create proxies - // for newly connected frames in the outer delegate SiteInstanceGroup. We - // do not want to interact with these, so explicitly verify the - // CoopRelatedGroups match. - // TODO(crbug.com/40266207): It is not clear that this iteration is - // actually useful for outer delegate proxies. See if this can be - // prevented to simplify logic here. - SiteInstanceGroup* opener_sig = - node->opener()->current_frame_host()->GetSiteInstance()->group(); - if (site_instance_group && - !site_instance_group->IsRelatedSiteInstanceGroup(opener_sig) && - site_instance_group->IsCoopRelatedSiteInstanceGroup(opener_sig)) { - cross_browsing_context_group_openers->insert(node->opener()); - continue; - } - FrameTree& opener_tree = node->opener()->frame_tree(); const auto& existing_tree_it = std::ranges::find(*opener_frame_trees, &opener_tree); @@ -5641,19 +5521,8 @@ // web_contents_impl.cc. std::vector<FrameTree*> opener_frame_trees; std::unordered_set<FrameTreeNode*> nodes_with_back_links; - std::unordered_set<FrameTreeNode*> cross_browsing_context_group_openers; - CollectOpenerFrameTrees(group, &opener_frame_trees, &nodes_with_back_links, - &cross_browsing_context_group_openers); - - // Create the proxies for openers outside of this BrowsingInstance. They are - // created separately on purpose, because we do not want to create proxies for - // their entire tree, only the single point of contact with this - // BrowsingInstance (and for any necessary ancestor frames). - for (auto* node : cross_browsing_context_group_openers) { - node->render_manager()->CreateRenderFrameProxyAndAncestorChainIfNeeded( - group); - } + CollectOpenerFrameTrees(group, &opener_frame_trees, &nodes_with_back_links); // Create opener proxies for frame trees, processing furthest openers from // this node first and this node last. In the common case without cycles,
diff --git a/content/browser/renderer_host/render_frame_host_manager.h b/content/browser/renderer_host/render_frame_host_manager.h index 1e3521b7..9db49a1 100644 --- a/content/browser/renderer_host/render_frame_host_manager.h +++ b/content/browser/renderer_host/render_frame_host_manager.h
@@ -410,12 +410,6 @@ const scoped_refptr<BrowsingContextState>& browsing_context_state, BatchedProxyIPCSender* batched_proxy_ipc_sender = nullptr); - // Similar to `CreateRenderFrameProxy` but also creates the minimal ancestor - // chain of proxies in `group` to support a subframe. This only exists to - // support CoopRelatedGroup proxy creation and should not be used for other - // cases. It is CHECKed that `group` must be cross-BrowsingInstance. - void CreateRenderFrameProxyAndAncestorChainIfNeeded(SiteInstanceGroup* group); - // Creates proxies for a new child frame at FrameTreeNode |child| in all // SiteInstances for which the current frame has proxies. This method is // called on the parent of a new child frame before the child leaves the @@ -719,10 +713,6 @@ // Note: Using this value requires passing in a valid `source_site_instance` // to ConvertToSiteInstance. RELATED_IN_GROUP, - // A SiteInstance in a different BrowsingInstance, but in the same - // CoopRelatedGroup. Only used for COOP: restrict-properties - // navigations. - RELATED_IN_COOP_GROUP, // A SiteInstance in the same browsing instance as the current. RELATED, // A pre-existing SiteInstance that might or might not be in the same @@ -802,7 +792,7 @@ bool is_reload, bool is_same_document, IsSameSiteGetter& is_same_site, - CoopSwapResult coop_swap_result, + bool coop_swap, bool was_server_redirect, bool should_replace_current_entry, bool has_rel_opener); @@ -829,7 +819,7 @@ IsSameSiteGetter& is_same_site, bool dest_is_view_source_mode, bool was_server_redirect, - CoopSwapResult coop_swap_result, + bool coop_swap, bool should_replace_current_entry, bool force_new_browsing_instance, bool has_rel_opener, @@ -957,17 +947,10 @@ // etc). If the traversal encounters a node with an opener pointing to a // FrameTree that has already been traversed (such as when there's a cycle), // the node is added to `nodes_with_back_links`. - // - // This function does not recursively iterate on trees living in a different - // BrowsingInstance from `site_instance_group`, which may have maintained an - // opener using COOP: restrict-properties. When such openers are encountered, - // they are added to `cross_browsing_context_group_openers`. Tests can set - // `site_instance_group` to null to iterate through all trees. void CollectOpenerFrameTrees( SiteInstanceGroup* site_instance_group, std::vector<FrameTree*>* opener_frame_trees, - std::unordered_set<FrameTreeNode*>* nodes_with_back_links, - std::unordered_set<FrameTreeNode*>* cross_browsing_context_group_openers); + std::unordered_set<FrameTreeNode*>* nodes_with_back_links); // Create RenderFrameProxies and inactive RenderViewHosts in the given // SiteInstanceGroup for the current node's FrameTree. Used as a helper
diff --git a/content/browser/renderer_host/render_frame_host_manager_unittest.cc b/content/browser/renderer_host/render_frame_host_manager_unittest.cc index 8ba44847..439afea 100644 --- a/content/browser/renderer_host/render_frame_host_manager_unittest.cc +++ b/content/browser/renderer_host/render_frame_host_manager_unittest.cc
@@ -589,8 +589,7 @@ std::unordered_set<FrameTreeNode*>* cross_browsing_context_group_openers) { node->render_manager()->CollectOpenerFrameTrees( - site_instance_group, opener_frame_trees, nodes_with_back_links, - cross_browsing_context_group_openers); + site_instance_group, opener_frame_trees, nodes_with_back_links); } private:
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc index 52fecb01..dc3a4db2 100644 --- a/content/browser/renderer_host/render_frame_proxy_host.cc +++ b/content/browser/renderer_host/render_frame_proxy_host.cc
@@ -375,19 +375,7 @@ void RenderFrameProxyHost::UpdateOpener() { // Another frame in this proxy's SiteInstanceGroup may reach the new opener by // first reaching this proxy and then referencing its window.opener. Ensure - // the new opener's proxy exists in this case. If this is already a proxy for - // a frame in another BrowsingInstance in the same CoopRelatedGroup, we should - // not add extra proxies, as these are not discoverable via window.opener - // because property access is restricted. - SiteInstanceGroup* current_group = - frame_tree_node_->current_frame_host()->GetSiteInstance()->group(); - bool is_coop_rp_proxy = - current_group->IsCoopRelatedSiteInstanceGroup(site_instance_group()) && - !current_group->IsRelatedSiteInstanceGroup(site_instance_group()); - if (is_coop_rp_proxy) { - return; - } - + // the new opener's proxy exists in this case. if (frame_tree_node_->opener()) { frame_tree_node_->opener()->render_manager()->CreateOpenerProxies( site_instance_group(), frame_tree_node_, @@ -618,7 +606,7 @@ // but that the source is related to the embedder, allowing frames related // to the embedder to also message the guest. if (target_embedder_rfh && - site_instance_group()->IsCoopRelatedSiteInstanceGroup( + site_instance_group()->IsRelatedSiteInstanceGroup( target_embedder_rfh->GetSiteInstance()->group())) { is_embedder_to_guest_communication = true; } @@ -636,7 +624,7 @@ // Note that this is not checking that the source and target are related, // but that the target is related to the embedder. if (source_embedder_rfh && - target_group->IsCoopRelatedSiteInstanceGroup( + target_group->IsRelatedSiteInstanceGroup( source_embedder_rfh->GetSiteInstance()->group())) { is_guest_to_embedder_communication = true; } @@ -644,9 +632,9 @@ } // Only deliver the message if the request came from a RenderFrameHost in the - // same CoopRelatedGroup or if this is a message between a guest and its + // same BrowsingInstance or if this is a message between a guest and its // embedder. - if (!target_group->IsCoopRelatedSiteInstanceGroup(site_instance_group()) && + if (!target_group->IsRelatedSiteInstanceGroup(site_instance_group()) && !is_embedder_to_guest_communication && !is_guest_to_embedder_communication) { return; @@ -684,16 +672,7 @@ ->SynchronizeVisualPropertiesIgnoringPendingAck(); } - if (!target_group->IsRelatedSiteInstanceGroup(site_instance_group()) && - target_group->IsCoopRelatedSiteInstanceGroup(site_instance_group())) { - // If we're getting messaged by a frame in a different BrowsingInstance - // in the same CoopRelatedGroup, we should create only the proxies - // needed for event.source (and its ancestor chain). - source_rfh->frame_tree_node() - ->render_manager() - ->CreateRenderFrameProxyAndAncestorChainIfNeeded( - target_rfh->GetSiteInstance()->group()); - } else if (is_embedder_to_guest_communication) { + if (is_embedder_to_guest_communication) { // We create a RenderFrameProxyHost for the embedder in the guest's // render process but we intentionally do not expose the embedder's // opener chain to it.
diff --git a/content/browser/renderer_host/render_view_host_impl.cc b/content/browser/renderer_host/render_view_host_impl.cc index 00b1dc2a..9d430eb 100644 --- a/content/browser/renderer_host/render_view_host_impl.cc +++ b/content/browser/renderer_host/render_view_host_impl.cc
@@ -604,11 +604,16 @@ // cross-browsing-context-group popup to B, the RenderViewHost for the opener // in B's process should have A's BrowsingContextGroupInfo, which is the // current page in the opener. + // TODO(crbug.com/412965095): Now that the CoopRelatedGroup no longer exist, + // BrowsingContextGroupInfo can be replaced by a simple + // BrowsingContextGroupToken. In the meantime, just pass the + // BrowsingInstanceToken as a CoopGroupToken so that we do not send an empty + // token. params->browsing_context_group_info = blink::BrowsingContextGroupInfo( frame_tree_->GetMainFrame()->GetSiteInstance()->browsing_instance_token(), frame_tree_->GetMainFrame() ->GetSiteInstance() - ->coop_related_group_token()); + ->browsing_instance_token()); // RenderViewHostImpl is reused after a crash, so reset any endpoint that // might be a leftover from a crash.
diff --git a/content/browser/security/coop/coop_related_group.cc b/content/browser/security/coop/coop_related_group.cc deleted file mode 100644 index 635e5a7..0000000 --- a/content/browser/security/coop/coop_related_group.cc +++ /dev/null
@@ -1,117 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "content/browser/security/coop/coop_related_group.h" - -#include "content/browser/browsing_instance.h" -#include "content/browser/site_instance_impl.h" - -#include "base/logging.h" - -namespace content { - -CoopRelatedGroup::CoopRelatedGroup(BrowserContext* browser_context, - bool is_guest, - bool is_fenced, - bool is_fixed_storage_partition) - : browser_context_(browser_context), - is_guest_(is_guest), - is_fenced_(is_fenced), - is_fixed_storage_partition_(is_fixed_storage_partition) { - if (is_guest_) { - CHECK(is_fixed_storage_partition_); - } -} - -CoopRelatedGroup::~CoopRelatedGroup() = default; - -scoped_refptr<BrowsingInstance> -CoopRelatedGroup::FindSuitableBrowsingInstanceForCoopPolicy( - const std::optional<url::Origin>& common_coop_origin, - const WebExposedIsolationInfo& web_exposed_isolation_info) { - for (BrowsingInstance* current_browsing_instance : - coop_related_browsing_instances_) { - // Note: We don't need to know if the common_coop_origin value is the result - // of COOP: same-origin or COOP: restrict-properties. We will only ever - // reach this function when doing a swap within the CoopRelatedGroup, so it - // is necessarily for COOP: restrict-properties. WebExposedIsolationInfo is - // used to know if COEP was set together with it or not. - if ((current_browsing_instance->common_coop_origin() == - common_coop_origin) && - (current_browsing_instance->web_exposed_isolation_info() == - web_exposed_isolation_info)) { - return base::WrapRefCounted<BrowsingInstance>(current_browsing_instance); - } - } - - return nullptr; -} - -scoped_refptr<BrowsingInstance> -CoopRelatedGroup::GetOrCreateBrowsingInstanceForCoopPolicy( - const std::optional<url::Origin>& common_coop_origin, - const WebExposedIsolationInfo& web_exposed_isolation_info) { - scoped_refptr<BrowsingInstance> browsing_instance = - FindSuitableBrowsingInstanceForCoopPolicy(common_coop_origin, - web_exposed_isolation_info); - - if (browsing_instance.get()) { - return browsing_instance; - } - - return base::WrapRefCounted<BrowsingInstance>(new BrowsingInstance( - browser_context_, web_exposed_isolation_info, is_guest_, is_fenced_, - is_fixed_storage_partition_, base::WrapRefCounted<CoopRelatedGroup>(this), - common_coop_origin)); -} - -void CoopRelatedGroup::RegisterBrowsingInstance( - BrowsingInstance* browsing_instance) { - // We should never register the same BrowsingInstance twice. If that happens, - // we're not reusing the BrowsingInstance via GetBrowsingInstanceForCoop() - // somewhere when we should be doing so. - auto it = find(coop_related_browsing_instances_.begin(), - coop_related_browsing_instances_.end(), browsing_instance); - CHECK(it == coop_related_browsing_instances_.end()); - - // We should also never record a second BrowsingInstance with the same Policy - // as an existing BrowsingInstance. - scoped_refptr<BrowsingInstance> duplicated_policy_browsing_instance = - FindSuitableBrowsingInstanceForCoopPolicy( - browsing_instance->common_coop_origin(), - browsing_instance->web_exposed_isolation_info()); - CHECK(duplicated_policy_browsing_instance.get() == nullptr); - - CHECK(browsing_instance->is_fixed_storage_partition() == - is_fixed_storage_partition_); - - coop_related_browsing_instances_.push_back(browsing_instance); -} - -void CoopRelatedGroup::UnregisterBrowsingInstance( - BrowsingInstance* browsing_instance) { - auto it = find(coop_related_browsing_instances_.begin(), - coop_related_browsing_instances_.end(), browsing_instance); - CHECK(it != coop_related_browsing_instances_.end()); - - coop_related_browsing_instances_.erase(it); -} - -scoped_refptr<SiteInstanceImpl> -CoopRelatedGroup::GetCoopRelatedSiteInstanceForURL(const UrlInfo& url_info, - bool allow_default_si) { - // Fenced frames should never be able to request other SiteInstances in the - // same CoopRelatedGroup, as they cannot open popups without noopener and COOP - // is not enforced within the frame. - DCHECK(!is_fenced_); - scoped_refptr<BrowsingInstance> target_browsing_instance = - GetOrCreateBrowsingInstanceForCoopPolicy( - url_info.common_coop_origin, - url_info.web_exposed_isolation_info.value_or( - WebExposedIsolationInfo::CreateNonIsolated())); - return target_browsing_instance->GetSiteInstanceForURL(url_info, - allow_default_si); -} - -} // namespace content
diff --git a/content/browser/security/coop/coop_related_group.h b/content/browser/security/coop/coop_related_group.h deleted file mode 100644 index 896da68..0000000 --- a/content/browser/security/coop/coop_related_group.h +++ /dev/null
@@ -1,174 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_SECURITY_COOP_COOP_RELATED_GROUP_H_ -#define CONTENT_BROWSER_SECURITY_COOP_COOP_RELATED_GROUP_H_ - -#include <optional> -#include <vector> - -#include "base/memory/ref_counted.h" -#include "base/memory/scoped_refptr.h" -#include "content/browser/url_info.h" -#include "content/browser/web_exposed_isolation_info.h" -#include "content/common/content_export.h" -#include "url/origin.h" - -namespace content { - -class BrowserContext; -class BrowsingInstance; -class SiteInstanceImpl; - -// A CoopRelatedGroup is a set of browsing context groups that can communicate -// with each other via a limited subset of properties -// (currently window.postMessage() and window.closed). Documents in -// BrowsingContexts that are not part of the same CoopRelatedGroup cannot get -// references to each other's Window by any means at all. CoopRelatedGroup, -// browsing context groups (BrowsingInstances) and Agent Clusters (roughly, but -// not strictly equivalent to SiteInstances) provide three tiers of -// communication capabilities: -// - Documents in the same Agent Cluster can synchronously DOM script each -// other. -// - Documents in the same browsing context group can asynchronously interact -// with each other, via cross-origin Window properties. -// - Documents in the same CoopRelatedGroup can only message each -// other and observe window.closed. -// -// These layers have a 1->n relationship pattern: a CoopRelatedGroup contains 1 -// or more browsing context groups, itself containing 1 or more agent clusters. -// Each layer is refcounted and therefore kept alive by the layer below it, with -// individual SiteInstances at the base, being kept alive manually. -// -// When no document inside a browsing context group sets COOP: -// restrict-properties, the CoopRelatedGroup contains only a single browsing -// context group. CoopRelatedGroups containing more than a single browsing -// context group occur when COOP: restrict-properties forces a browsing context -// group swap in the same CoopRelatedGroup. It allows retaining a relationship -// to the opener across browsing context groups, hence creating the actual -// communication channel. -// -// Like BrowsingInstance, CoopRelatedGroup has no public members, as it is -// designed to be interacted with only from the BrowsingInstance class, itself -// only reachable from SiteInstance. To get a new SiteInstance that is part of -// the same CoopRelatedGroup but in a different BrowsingInstance, use -// SiteInstanceImpl::GetCoopRelatedSiteInstance. Because of this, -// CoopRelatedGroups are tested in site_instance_impl_unittest.cc. -class CONTENT_EXPORT CoopRelatedGroup final - : public base::RefCounted<CoopRelatedGroup> { - public: - CoopRelatedGroup(const CoopRelatedGroup&) = delete; - CoopRelatedGroup& operator=(const CoopRelatedGroup&) = delete; - - private: - friend class base::RefCounted<CoopRelatedGroup>; - friend class BrowsingInstance; - friend class CoopRelatedGroupTest; - - explicit CoopRelatedGroup(BrowserContext* browser_context, - bool is_guest, - bool is_fenced, - bool is_fixed_storage_partition); - ~CoopRelatedGroup(); - - // Returns the token uniquely identifying this CoopRelatedGroup. - base::UnguessableToken token() const { return token_; } - - // Returns a SiteInstance in this CoopRelatedGroup, depending on the passed - // `url_info`. It might reuse an existing BrowsingInstance that is part of the - // group if one is suitable, given its COOP value, origin and cross-origin - // isolation state. If none is suitable, a new BrowsingInstance with the - // appropriate characteristics will be created. - // - // `allow_default_site_instance` is used to specify whether the returned - // SiteInstance can be the default SiteInstance. - scoped_refptr<SiteInstanceImpl> GetCoopRelatedSiteInstanceForURL( - const UrlInfo& url_info, - bool allow_default_site_instance); - - // These functions keep the group informed of the BrowsingInstances that are - // alive and part of it. It is necessary for the BrowsingInstance reuse - // mechanism. They should be called in the constructor and destructor of - // BrowsingInstance. - void RegisterBrowsingInstance(BrowsingInstance* browsing_instance); - void UnregisterBrowsingInstance(BrowsingInstance* browsing_instance); - - // Internal helpers that return a BrowsingInstance for a given COOP "Policy" - // which includes whether COOP: restrict-properties was set and from which - // origin, as well as whether it was augmented with COEP. - // `FindSuitableBrowsingInstanceForCoopPolicy` only returns an existing - // BrowsingInstance with the given Policy, while - // `GetOrCreateBrowsingInstanceForCoopPolicy` will create a new one if no - // suitable BrowsingInstance exists in this group. - scoped_refptr<BrowsingInstance> FindSuitableBrowsingInstanceForCoopPolicy( - const std::optional<url::Origin>& common_coop_origin, - const WebExposedIsolationInfo& web_exposed_isolation_info); - scoped_refptr<BrowsingInstance> GetOrCreateBrowsingInstanceForCoopPolicy( - const std::optional<url::Origin>& common_coop_origin, - const WebExposedIsolationInfo& web_exposed_isolation_info); - - // Tracks the number of WebContents currently in this CoopRelatedGroup. - // Note: We also separately track the number of WebContents in specific - // BrowsingInstances, for validity checks. - size_t active_contents_count() const { return active_contents_count_; } - void increment_active_contents_count() { active_contents_count_++; } - void decrement_active_contents_count() { - DCHECK_LT(0u, active_contents_count_); - active_contents_count_--; - } - - // Recorded with the first BrowsingInstance and used to create new - // BrowsingInstances. All BrowsingInstances in a CoopRelatedGroup should share - // the same BrowserContext, therefore recording it at creation time is fine. - raw_ptr<BrowserContext, DanglingUntriaged> browser_context_; - - // Whether all the documents presented in this CoopRelatedGroup are for guest - // views. - bool is_guest_; - - // Whether all the documents presented in this CoopRelatedGroup are for a - // fenced frame. - bool is_fenced_; - - // Whether all the documents presented in this CoopRelatedGroup have fixed - // storage partition config. - // - // TODO(crbug.com/40943418): We actually always want this behavior. Remove - // this bit when we are ready. - bool is_fixed_storage_partition_; - - // All the BrowsingInstances belonging to this CoopRelatedGroup. They are not - // owned by this group, but collectively own it instead. To keep track of the - // group members we therefore use raw_ptrs, and add or delete members of the - // group via the RegisterBrowsingInstance and UnregisterBrowsingInstance - // methods. These are called from the BrowsingInstance constructor and - // destructor respectively. - // - // There exists at most one BrowsingInstance hosting documents with the same - // "Policy", namely a combination of whether COOP: restrict-properties was set - // and from which origin, and whether it set COEP as well. This gives us three - // types of BrowsingInstances: - // - The ones with COOP: restrict-properties set from a given origin. - // - The ones with COOP: restrict-properties-plus-COEP set from a given - // origin. - // - A single BrowsingInstance for all the rest. - // - // We make sure we do not create two BrowsingInstances with the same - // Policy when running RegisterBrowsingInstance. - std::vector<raw_ptr<BrowsingInstance>> coop_related_browsing_instances_; - - // Number of all WebContents currently using any of the BrowsingInstances in - // this group. This is used to determine if there are multiple windows in the - // group, to know whether certain actions (e.g. putting a page into the - // BFCache) are allowed. - size_t active_contents_count_{0u}; - - // A token uniquely identifying this CoopRelatedGroup. This can be sent to the - // renderer process if needed, without security risks. - const base::UnguessableToken token_ = base::UnguessableToken::Create(); -}; - -} // namespace content - -#endif // CONTENT_BROWSER_SECURITY_COOP_COOP_RELATED_GROUP_H_;
diff --git a/content/browser/security/coop/coop_swap_result.h b/content/browser/security/coop/coop_swap_result.h deleted file mode 100644 index 49399f5f..0000000 --- a/content/browser/security/coop/coop_swap_result.h +++ /dev/null
@@ -1,27 +0,0 @@ -// Copyright 2023 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CONTENT_BROWSER_SECURITY_COOP_COOP_SWAP_RESULT_H_ -#define CONTENT_BROWSER_SECURITY_COOP_COOP_SWAP_RESULT_H_ - -namespace content { - -// This enum indicates what the comparison of Cross-Origin-Opener-Policy headers -// has yielded. -enum class CoopSwapResult { - // Indicates that no BrowsingContext group swap is required, based on COOP - // values. - kNoSwap, - // Indicates that a BrowsingContext group swap is required, but that we should - // use a BrowsingContext group that is "related", preserving restricted - // openers. - kSwapRelated, - // Indicates that a BrowsingContext group swap is required, and that should - // sever all links between the two BrowsingContext groups, opener, names, etc. - kSwap -}; - -} // namespace content - -#endif // CONTENT_BROWSER_SECURITY_COOP_COOP_SWAP_RESULT_H_
diff --git a/content/browser/security/coop/cross_origin_opener_policy_access_report_manager.cc b/content/browser/security/coop/cross_origin_opener_policy_access_report_manager.cc index 896bd421..88c25e4 100644 --- a/content/browser/security/coop/cross_origin_opener_policy_access_report_manager.cc +++ b/content/browser/security/coop/cross_origin_opener_policy_access_report_manager.cc
@@ -21,15 +21,6 @@ namespace { -// A map of virtual browsing context groups to the coop related groups they -// belong to. This mimics the real behavior of BrowsingInstance and -// CoopRelatedGroup. It is useful to restrict access in a more granular manner -// and to account for browsing context group reuse. -std::map<int, int>& GetVirtualBrowsingContextGroupToCoopRelatedGroupMap() { - static auto& bcg_to_coop_group_map = *new std::map<int, int>(); - return bcg_to_coop_group_map; -} - std::optional<blink::FrameToken> GetFrameToken( FrameTreeNode* frame, SiteInstanceGroup* site_instance_group) { @@ -47,22 +38,18 @@ } // Find all the related windows that might try to access the new document in -// `frame`, but are in a different virtual browsing context group. The -// associated boolean indicates whether they are in the same virtual -// CoopRelatedGroup. -std::vector<std::pair<FrameTreeNode*, bool>> CollectOtherWindowForCoopAccess( +// `frame`, but are in a different virtual browsing context group. +std::vector<FrameTreeNode*> CollectOtherWindowForCoopAccess( FrameTreeNode* frame) { DCHECK(frame->IsMainFrame()); - std::map<int, int>& bcg_to_coop_group_map = - GetVirtualBrowsingContextGroupToCoopRelatedGroupMap(); int virtual_browsing_context_group = frame->current_frame_host()->virtual_browsing_context_group(); - std::vector<std::pair<FrameTreeNode*, bool>> out; + std::vector<FrameTreeNode*> out; for (RenderFrameHostImpl* rfh : frame->current_frame_host() ->delegate() - ->GetActiveTopLevelDocumentsInCoopRelatedGroup( + ->GetActiveTopLevelDocumentsInBrowsingContextGroup( frame->current_frame_host())) { // Filter out windows from the same virtual browsing context group. if (rfh->virtual_browsing_context_group() == @@ -70,18 +57,7 @@ continue; } - // Every virtual browsing context group should have an associated virtual - // CoopRelatedGroup. - CHECK(bcg_to_coop_group_map.find(rfh->virtual_browsing_context_group()) != - bcg_to_coop_group_map.end()); - CHECK(bcg_to_coop_group_map.find(virtual_browsing_context_group) != - bcg_to_coop_group_map.end()); - - bool is_in_same_virtual_coop_related_group = - bcg_to_coop_group_map[rfh->virtual_browsing_context_group()] == - bcg_to_coop_group_map[virtual_browsing_context_group]; - out.emplace_back(rfh->frame_tree_node(), - is_in_same_virtual_coop_related_group); + out.emplace_back(rfh->frame_tree_node()); } return out; } @@ -102,42 +78,35 @@ // Find all the related windows that might try to access the new document, // but are from a different virtual browsing context group. - std::vector<std::pair<FrameTreeNode*, bool>> other_main_frames = + std::vector<FrameTreeNode*> other_main_frames = CollectOtherWindowForCoopAccess(frame); - // Fenced frame roots are in their own browsing context group in a separate - // coop related group and shouldn't be joined with any other main frames. + // Fenced frame roots are in their own BrowsingInstance and shouldn't be + // joined with any other main frames. DCHECK(!frame->IsInFencedFrameTree() || other_main_frames.empty()); CrossOriginOpenerPolicyAccessReportManager* access_manager_frame = frame->current_frame_host()->coop_access_report_manager(); - for (const std::pair<FrameTreeNode*, bool>& other : other_main_frames) { - FrameTreeNode* other_ftn = other.first; - bool is_in_same_virtual_coop_related_group = other.second; + for (FrameTreeNode* other_ftn : other_main_frames) { CrossOriginOpenerPolicyAccessReportManager* access_manager_other = other_ftn->current_frame_host()->coop_access_report_manager(); // If the current frame has a reporter, install the access monitors to // monitor the accesses between this frame and the other frame. - access_manager_frame->MonitorAccesses( - frame, other_ftn, is_in_same_virtual_coop_related_group); - access_manager_frame->MonitorAccesses( - other_ftn, frame, is_in_same_virtual_coop_related_group); + access_manager_frame->MonitorAccesses(frame, other_ftn); + access_manager_frame->MonitorAccesses(other_ftn, frame); // If the other frame has a reporter, install the access monitors to monitor // the accesses between this frame and the other frame. - access_manager_other->MonitorAccesses( - frame, other_ftn, is_in_same_virtual_coop_related_group); - access_manager_other->MonitorAccesses( - other_ftn, frame, is_in_same_virtual_coop_related_group); + access_manager_other->MonitorAccesses(frame, other_ftn); + access_manager_other->MonitorAccesses(other_ftn, frame); } } void CrossOriginOpenerPolicyAccessReportManager::MonitorAccesses( FrameTreeNode* accessing_node, - FrameTreeNode* accessed_node, - bool is_in_same_virtual_coop_related_group) { + FrameTreeNode* accessed_node) { DCHECK_NE(accessing_node, accessed_node); DCHECK(accessing_node->current_frame_host()->coop_access_report_manager() == this || @@ -167,63 +136,16 @@ this == accessing_node->current_frame_host()->coop_access_report_manager(); + // TODO(crbug.com/412965095): Remove the is_in_same_virtual_coop_related_group + // boolean from the Mojo interface and cleanup the COOP restrict-properties + // renderer reporting code. accessing_node->current_frame_host() ->GetAssociatedLocalMainFrame() ->InstallCoopAccessMonitor( *accessed_window_token, coop_reporter_->CreateReporterParams(access_from_coop_page, accessing_node, accessed_node), - is_in_same_virtual_coop_related_group); -} - -// static -int CrossOriginOpenerPolicyAccessReportManager:: - GetNewVirtualBrowsingContextGroup() { - std::map<int, int>& bcg_to_coop_group_map = - GetVirtualBrowsingContextGroupToCoopRelatedGroupMap(); - - // Assign the newly created virtual browsing context group to a new virtual - // CoopRelatedGroup. - int virtual_browsing_context_group_id = NextVirtualBrowsingContextGroup(); - bcg_to_coop_group_map[virtual_browsing_context_group_id] = - NextVirtualCoopRelatedGroup(); - return virtual_browsing_context_group_id; -} - -// static -int CrossOriginOpenerPolicyAccessReportManager::GetVirtualBrowsingContextGroup( - CoopSwapResult enforce_result, - CoopSwapResult report_only_result, - int current_virtual_browsing_context_group) { - // This function should only ever be called if we require a different virtual - // browsing context group. - CHECK(enforce_result != CoopSwapResult::kNoSwap || - report_only_result != CoopSwapResult::kNoSwap); - - int next_browsing_context_group_id = NextVirtualBrowsingContextGroup(); - std::map<int, int>& bcg_to_coop_group_map = - GetVirtualBrowsingContextGroupToCoopRelatedGroupMap(); - - // If a swap in a different CoopRelatedGroup would be required, simply create - // a new virtual browsing context group in a new virtual CoopRelatedGroup. - if (enforce_result == CoopSwapResult::kSwap || - report_only_result == CoopSwapResult::kSwap) { - bcg_to_coop_group_map[next_browsing_context_group_id] = - NextVirtualCoopRelatedGroup(); - return next_browsing_context_group_id; - } - - // If a swap in the same CoopRelatedGroup would be required, create a new - // virtual browsing context group in the current virtual CoopRelatedGroup. - // TODO(crbug.com/40276687): This is not strictly correct, because - // browsing context groups can be reused when navigating in the same - // CoopRelatedGroup. Pass in the isolation information to make it as close - // to reality as possible. - int current_virtual_coop_related_group = - bcg_to_coop_group_map[current_virtual_browsing_context_group]; - bcg_to_coop_group_map[next_browsing_context_group_id] = - current_virtual_coop_related_group; - return next_browsing_context_group_id; + false); } // static @@ -233,10 +155,4 @@ return ++id; } -// static -int CrossOriginOpenerPolicyAccessReportManager::NextVirtualCoopRelatedGroup() { - static int id = -1; - return ++id; -} - } // namespace content
diff --git a/content/browser/security/coop/cross_origin_opener_policy_access_report_manager.h b/content/browser/security/coop/cross_origin_opener_policy_access_report_manager.h index 900342fc..5382320 100644 --- a/content/browser/security/coop/cross_origin_opener_policy_access_report_manager.h +++ b/content/browser/security/coop/cross_origin_opener_policy_access_report_manager.h
@@ -9,7 +9,6 @@ #include "base/values.h" #include "content/browser/security/coop/cross_origin_opener_policy_reporter.h" -#include "content/browser/security/coop/coop_swap_result.h" namespace content { @@ -36,37 +35,14 @@ // CoopAccessMonitor. The first window is identified by |node|. static void InstallAccessMonitorsIfNeeded(FrameTreeNode* node); - // Return a new virtual browsing context group ID belong to a new - // CoopRelatedGroup. - static int GetNewVirtualBrowsingContextGroup(); - - // Return a virtual browsing context group ID that is suitable given the - // information passed in. `enforce_result` and `report_only_result` indicate - // whether actual COOP values and report-only COOP values, respectively, need - // a browsing context group swap. It also accounts for swapping in the same - // CoopRelatedGroup or in a different one. Combined with - // `current_virtual_browsing_context_group`, we can decide what virtual - // browsing context group is suitable and return its ID. - static int GetVirtualBrowsingContextGroup( - CoopSwapResult enforce_result, - CoopSwapResult report_only_result, - int current_virtual_browsing_context_group); - - private: // Generate a new, previously unused, virtual browsing context group ID. static int NextVirtualBrowsingContextGroup(); - // Generate a new, previously unused, virtual CoopRelatedGroup ID. - static int NextVirtualCoopRelatedGroup(); - + private: // Install the CoopAccessMonitors monitoring accesses from `accessing_node` - // toward `accessed_node`. `is_in_same_virtual_coop_related_group` indicates - // whether the two nodes would be in the same CoopRelatedGroup. If that's the - // case, do not report window.postMessage() and window.closed accesses, which - // would be permitted by COOP: restrict-properties. + // toward `accessed_node`. void MonitorAccesses(FrameTreeNode* accessing_node, - FrameTreeNode* accessed_node, - bool is_in_same_virtual_coop_related_group); + FrameTreeNode* accessed_node); std::unique_ptr<CrossOriginOpenerPolicyReporter> coop_reporter_; };
diff --git a/content/browser/security/coop/cross_origin_opener_policy_browsertest.cc b/content/browser/security/coop/cross_origin_opener_policy_browsertest.cc index 2281627..9f9360d 100644 --- a/content/browser/security/coop/cross_origin_opener_policy_browsertest.cc +++ b/content/browser/security/coop/cross_origin_opener_policy_browsertest.cc
@@ -4070,21 +4070,27 @@ int rph_id_3 = current_frame_host()->GetProcess()->GetDeprecatedID(); EXPECT_EQ(rph_id_2, rph_id_3); - // The original speculative RFH should always be destroyed. - // - // Subtle note: this happens even when bfcache is enabled. With bfcache, - // we force a BrowsingInstance swap at the very beginning when the navigation - // to `url_2` starts. So when we learn about COOP at response time, the + // This test is parameterized on whether the bfcache is enabled. With + // bfcache, we force a BrowsingInstance swap at the very beginning when the + // navigation to `url_2` starts, so there's no need to create a new + // SiteInstance when we learn about COOP at response time, since the // candidate (speculative RFH's) SiteInstance is already in a fresh - // BrowsingInstance. However, it cannot be reused, because COOP requires a - // BrowsingInstance with b.test as its common_coop_origin(), and the - // candidate SiteInstance's BrowsingInstance has no common_coop_origin(), so - // it cannot be reused, and we end up creating a new speculative RFH and - // destroying the original one. - EXPECT_TRUE(speculative_rfh.IsDestroyed()); + // BrowsingInstance. Therefore, with bfcache, the original speculative RFH + // will be the RFH that eventually commits. Otherwise, the original + // speculative RFH should be destroyed and replaced by another RFH. + // + // When BackForwardCache is not enabled, the speculative RFH is created in the + // current BrowsingInstance, and is not appropriate for a navigation to the + // COOP page. So we destroy it, but we can still reuse its process for the new + // SiteInstance we create for the navigation. + if (IsBackForwardCacheEnabled()) { + EXPECT_FALSE(speculative_rfh.IsDestroyed()); + } else { + EXPECT_TRUE(speculative_rfh.IsDestroyed()); - histogram_tester.ExpectUniqueSample( - "Navigation.ProcessReuseOnCOOP.DifferentSiteInstance", true, 1); + histogram_tester.ExpectUniqueSample( + "Navigation.ProcessReuseOnCOOP.DifferentSiteInstance", true, 1); + } } // Ensure that same-site navigations that result in a COOP mismatch avoid an @@ -4113,13 +4119,14 @@ // process because the navigation is same-site. Otherwise, the navigation // should stay in the current RenderFrameHost. int rph_id_2; + RenderFrameHost* speculative_rfh = nullptr; if (IsBackForwardCacheEnabled() || ShouldCreateNewHostForAllFrames()) { navigation.WaitForSpeculativeRenderFrameHostCreation(); - RenderFrameHost* speculative_rfh = web_contents() - ->GetPrimaryFrameTree() - .root() - ->render_manager() - ->speculative_frame_host(); + speculative_rfh = web_contents() + ->GetPrimaryFrameTree() + .root() + ->render_manager() + ->speculative_frame_host(); ASSERT_TRUE(speculative_rfh); rph_id_2 = speculative_rfh->GetProcess()->GetDeprecatedID(); EXPECT_EQ(rph_id_1, rph_id_2); @@ -4132,6 +4139,8 @@ rph_id_2 = rph_id_1; } + RenderFrameHostWrapper speculative_rfh_checker(speculative_rfh); + // Allow the navigation to receive the response commit. EXPECT_TRUE(navigation.WaitForNavigationFinished()); EXPECT_TRUE(navigation.was_successful()); @@ -4145,6 +4154,12 @@ // and the old process wasn't already locked to a.test. In that case, a // process swap is required, since we are going from an unlocked process to a // locked process. + // + // When BFCache is enabled, we do a proactive BrowsingInstance swap at the + // beginning of navigation, which has created a brand new speculative + // RenderFrameHost. This speculative RenderFrameHost in a new BrowsingInstance + // can be used to commit the navigation to the COOP page, so it is not + // destroyed. int rph_id_3 = current_frame_host()->GetProcess()->GetDeprecatedID(); if (SiteIsolationPolicy::IsSiteIsolationForCOOPEnabled()) { EXPECT_NE(rph_id_2, rph_id_3); @@ -4158,7 +4173,9 @@ } else { EXPECT_EQ(rph_id_2, rph_id_3); - if (IsBackForwardCacheEnabled() || ShouldCreateNewHostForAllFrames()) { + if (IsBackForwardCacheEnabled()) { + EXPECT_FALSE(speculative_rfh_checker.IsDestroyed()); + } else if (ShouldCreateNewHostForAllFrames()) { histogram_tester.ExpectUniqueSample( "Navigation.ProcessReuseOnCOOP.DifferentSiteInstance", true, 1); } else {
diff --git a/content/browser/security/coop/cross_origin_opener_policy_status.cc b/content/browser/security/coop/cross_origin_opener_policy_status.cc index b769ed39..2d03dd3 100644 --- a/content/browser/security/coop/cross_origin_opener_policy_status.cc +++ b/content/browser/security/coop/cross_origin_opener_policy_status.cc
@@ -27,10 +27,9 @@ // The SiteInstance selection model heavily relies on this function to be // correct, and documents these assumptions, many of which would crash the // browser if incorrect. In particular, it assumes that returning a value of -// CoopSwapResult::kSwapRelated means that the current browsing context group -// will NOT be found suitable for reuse, as that would effectively mean no swap -// has happened. -CoopSwapResult ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy( +// true means that the current browsing context group will NOT be found suitable +// for reuse, as that would effectively mean no swap has happened. +bool ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy( network::mojom::CrossOriginOpenerPolicyValue initiator_coop, const url::Origin& initiator_origin, bool is_navigation_from_initial_empty_document, @@ -42,12 +41,12 @@ case CrossOriginOpenerPolicyValue::kUnsafeNone: switch (destination_coop) { case CrossOriginOpenerPolicyValue::kUnsafeNone: - return CoopSwapResult::kNoSwap; + return false; case CrossOriginOpenerPolicyValue::kSameOriginAllowPopups: case CrossOriginOpenerPolicyValue::kSameOrigin: case CrossOriginOpenerPolicyValue::kSameOriginPlusCoep: case CrossOriginOpenerPolicyValue::kNoopenerAllowPopups: - return CoopSwapResult::kSwap; + return true; } // "same-origin-allow-popups" is used to stay in the same BrowsingInstance @@ -55,41 +54,33 @@ case CrossOriginOpenerPolicyValue::kSameOriginAllowPopups: switch (destination_coop) { case CrossOriginOpenerPolicyValue::kUnsafeNone: - return is_navigation_from_initial_empty_document - ? CoopSwapResult::kNoSwap - : CoopSwapResult::kSwap; + return !is_navigation_from_initial_empty_document; case CrossOriginOpenerPolicyValue::kSameOriginAllowPopups: - return initiator_origin.IsSameOriginWith(destination_origin) - ? CoopSwapResult::kNoSwap - : CoopSwapResult::kSwap; + return !initiator_origin.IsSameOriginWith(destination_origin); case CrossOriginOpenerPolicyValue::kSameOrigin: case CrossOriginOpenerPolicyValue::kSameOriginPlusCoep: case CrossOriginOpenerPolicyValue::kNoopenerAllowPopups: - return CoopSwapResult::kSwap; + return true; } case CrossOriginOpenerPolicyValue::kNoopenerAllowPopups: switch (destination_coop) { case CrossOriginOpenerPolicyValue::kUnsafeNone: - return CoopSwapResult::kNoSwap; + return false; case CrossOriginOpenerPolicyValue::kNoopenerAllowPopups: return (is_navigation_from_initial_empty_document || - !initiator_origin.IsSameOriginWith(destination_origin)) - ? CoopSwapResult::kSwap - : CoopSwapResult::kNoSwap; + !initiator_origin.IsSameOriginWith(destination_origin)); case CrossOriginOpenerPolicyValue::kSameOriginAllowPopups: case CrossOriginOpenerPolicyValue::kSameOrigin: case CrossOriginOpenerPolicyValue::kSameOriginPlusCoep: - return CoopSwapResult::kSwap; + return true; } // "same-origin" requires that both policies and origin match. case CrossOriginOpenerPolicyValue::kSameOrigin: case CrossOriginOpenerPolicyValue::kSameOriginPlusCoep: - return (initiator_coop == destination_coop && - initiator_origin.IsSameOriginWith(destination_origin)) - ? CoopSwapResult::kNoSwap - : CoopSwapResult::kSwap; + return initiator_coop != destination_coop || + !initiator_origin.IsSameOriginWith(destination_origin); } } @@ -178,10 +169,10 @@ // We should force a COOP browsing instance swap to avoid certain // opener+error pages exploits, see https://crbug.com/1256823 and // https://github.com/whatwg/html/issues/7345. - browsing_instance_swap_result_ = CoopSwapResult::kSwap; + browsing_instance_swap_ = true; virtual_browsing_context_group_ = CrossOriginOpenerPolicyAccessReportManager:: - GetNewVirtualBrowsingContextGroup(); + NextVirtualBrowsingContextGroup(); return network::mojom::BlockedByResponseReason:: kCoopSandboxedIFrameCannotNavigateToCoopPage; @@ -243,35 +234,34 @@ const url::Origin current_coop_origin = current_coop_.origin.value_or(url::Origin()); - CoopSwapResult cross_origin_policy_swap = + bool cross_origin_policy_swap = ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy( current_coop_.value, current_coop_origin, is_navigation_from_initial_empty_document_, response_coop.value, response_coop_origin); - // Over the whole redirect chain, keep track of the "strongest" way the new - // context must be separated from the previous one. - // kNoSwap < kSwapRelated < kSwap. - if (cross_origin_policy_swap > browsing_instance_swap_result_) { - browsing_instance_swap_result_ = cross_origin_policy_swap; - } + // Any mismatch in COOP during any step of the redirect chain will result in + // the whole navigation requiring a BrowsingInstance swap. Update the tracking + // of necessary browsing instance swap for the navigation based on the result + // of checking COOP for this step of the redirect chain. + browsing_instance_swap_ |= cross_origin_policy_swap; // Both report only cases (navigation from and to document) use the following // result, computing the need of a browsing context group swap based on both // documents' report-only values. - CoopSwapResult report_only_coop_swap = + bool report_only_coop_swap = ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy( current_coop_.report_only_value, current_coop_origin, is_navigation_from_initial_empty_document_, response_coop.report_only_value, response_coop_origin); - CoopSwapResult navigating_to_report_only_coop_swap = + bool navigating_to_report_only_coop_swap = ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy( current_coop_.value, current_coop_origin, is_navigation_from_initial_empty_document_, response_coop.report_only_value, response_coop_origin); - CoopSwapResult navigating_from_report_only_coop_swap = + bool navigating_from_report_only_coop_swap = ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy( current_coop_.report_only_value, current_coop_origin, is_navigation_from_initial_empty_document_, response_coop.value, @@ -280,15 +270,14 @@ bool has_other_window_in_browsing_context_group = frame_tree_node_->current_frame_host() ->delegate() - ->GetActiveTopLevelDocumentsInCoopRelatedGroup( + ->GetActiveTopLevelDocumentsInBrowsingContextGroup( frame_tree_node_->current_frame_host()) .size() > 1; - // If this response's COOP causes a BrowsingInstance swap in another - // CoopRelatedGroup, report this to the previous COOP reporter and/or the COOP - // reporter of the response if they exist. Do not report swaps in the same - // CoopRelatedGroup, as these do not sever the opener. - if (cross_origin_policy_swap == CoopSwapResult::kSwap) { + // If this response's COOP causes a BrowsingInstance swap, report this to the + // previous COOP reporter and/or the COOP reporter of the response if they + // exist. + if (cross_origin_policy_swap) { // Using current_origin_ instead of current_coop_.origin here because // we only care about whether the actual origin has changed when determining // whether to show previous URL. @@ -313,32 +302,14 @@ // (from/to). If both report-only values match however, skip reports, as the // website likely wants to deploy COOP on both pages and is not interested in // these kind of reports. - bool has_matching_report_only = - report_only_coop_swap == CoopSwapResult::kNoSwap; - CoopSwapResult virtual_browsing_instance_swap_result = - CoopSwapResult::kNoSwap; - if (!has_matching_report_only) { - // Find the strongest type of swap that would happen, between the previous - // and next report-only values. - if (navigating_from_report_only_coop_swap == CoopSwapResult::kSwap || - navigating_to_report_only_coop_swap == CoopSwapResult::kSwap) { - virtual_browsing_instance_swap_result = CoopSwapResult::kSwap; - } else if (navigating_from_report_only_coop_swap == - CoopSwapResult::kSwapRelated || - navigating_to_report_only_coop_swap == - CoopSwapResult::kSwapRelated) { - virtual_browsing_instance_swap_result = CoopSwapResult::kSwapRelated; - } - } + bool virtual_browsing_instance_swap = + report_only_coop_swap && (navigating_from_report_only_coop_swap || + navigating_to_report_only_coop_swap); - // If this response's report-only COOP would cause a BrowsingInstance swap - // in another CoopRelatedGroup, report this to the previous COOP reporter - // and/or the COOP reporter of the response if they exist. Do not report swaps - // in the same CoopRelatedGroup, as these do not sever the opener. - if (virtual_browsing_instance_swap_result == CoopSwapResult::kSwap) { - // If this response's report-only COOP would cause a BrowsingInstance swap, - // report this to the previous COOP reporter and/or the COOP reporter of - // the response if they exist. + // If this response's report-only COOP would cause a BrowsingInstance swap, + // report this to the previous COOP reporter and/or the COOP reporter of the + // response if they exist. + if (virtual_browsing_instance_swap) { if (has_other_window_in_browsing_context_group) { if (response_origin.IsSameOriginWith(response_coop_origin)) { response_reporter->QueueNavigationToCOOPReport( @@ -356,14 +327,10 @@ } } - if (browsing_instance_swap_result_ != CoopSwapResult::kNoSwap || - virtual_browsing_instance_swap_result != CoopSwapResult::kNoSwap) { + if (browsing_instance_swap_ || virtual_browsing_instance_swap) { virtual_browsing_context_group_ = CrossOriginOpenerPolicyAccessReportManager:: - GetVirtualBrowsingContextGroup( - browsing_instance_swap_result_, - virtual_browsing_instance_swap_result, - virtual_browsing_context_group_); + NextVirtualBrowsingContextGroup(); } // Check if a COOP of same-origin-allow-popups by default would result in a @@ -371,11 +338,10 @@ if (ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy( current_coop_.soap_by_default_value, current_coop_origin, is_navigation_from_initial_empty_document_, - response_coop.soap_by_default_value, - response_coop_origin) != CoopSwapResult::kNoSwap) { + response_coop.soap_by_default_value, response_coop_origin)) { soap_by_default_virtual_browsing_context_group_ = CrossOriginOpenerPolicyAccessReportManager:: - GetNewVirtualBrowsingContextGroup(); + NextVirtualBrowsingContextGroup(); } // Finally, update the current COOP, origin and reporter to those of the
diff --git a/content/browser/security/coop/cross_origin_opener_policy_status.h b/content/browser/security/coop/cross_origin_opener_policy_status.h index bee7c10..f0b4b59 100644 --- a/content/browser/security/coop/cross_origin_opener_policy_status.h +++ b/content/browser/security/coop/cross_origin_opener_policy_status.h
@@ -10,7 +10,6 @@ #include "base/memory/raw_ptr.h" #include "base/scoped_observation.h" -#include "content/browser/security/coop/coop_swap_result.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_process_host_observer.h" #include "services/network/public/cpp/cross_origin_opener_policy.h" @@ -33,9 +32,8 @@ // Helper function that returns whether the BrowsingInstance should change // following COOP rules defined in: // -// https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e#changes-to-navigation -CONTENT_EXPORT CoopSwapResult -ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy( +// https://html.spec.whatwg.org/#browsing-context-group-switches-due-to-cross-origin-opener-policy +CONTENT_EXPORT bool ShouldSwapBrowsingInstanceForCrossOriginOpenerPolicy( network::mojom::CrossOriginOpenerPolicyValue initiator_coop, const url::Origin& initiator_origin, bool is_navigation_from_initial_empty_document, @@ -66,13 +64,9 @@ // Calling this function is safe because it can only tighten security. // This is used by _unfencedTop in fenced frames to ensure that navigations // leaving the fenced context create a new browsing instance. - void ForceBrowsingInstanceSwap() { - browsing_instance_swap_result_ = CoopSwapResult::kSwap; - } + void ForceBrowsingInstanceSwap() { browsing_instance_swap_ = true; } - CoopSwapResult browsing_instance_swap_result() const { - return browsing_instance_swap_result_; - } + bool browsing_instance_swap() const { return browsing_instance_swap_; } // The virtual browsing context group of the document to commit. Initially, // the navigation inherits the virtual browsing context group of the current @@ -144,7 +138,7 @@ // Tracks whether the new document created by the navigation needs to be // created in a different BrowsingContext group. This is updated after every // redirect, and after receiving the final response. - CoopSwapResult browsing_instance_swap_result_ = CoopSwapResult::kNoSwap; + bool browsing_instance_swap_ = false; int virtual_browsing_context_group_;
diff --git a/content/browser/security/coop/cross_origin_opener_policy_status_unittest.cc b/content/browser/security/coop/cross_origin_opener_policy_status_unittest.cc index cd7b701..b79f2a3 100644 --- a/content/browser/security/coop/cross_origin_opener_policy_status_unittest.cc +++ b/content/browser/security/coop/cross_origin_opener_policy_status_unittest.cc
@@ -13,7 +13,6 @@ namespace content { using COOP = network::mojom::CrossOriginOpenerPolicyValue; -using Result = CoopSwapResult; using CrossOriginOpenerPolicyStatusTest = testing::Test; TEST(CrossOriginOpenerPolicyStatusTest, @@ -21,49 +20,36 @@ struct TestCase { COOP coop_from; COOP coop_to; - CoopSwapResult expect_swap_same_origin; - CoopSwapResult expect_swap_cross_origin; - CoopSwapResult expect_swap_new_popup; + bool expect_swap_same_origin; + bool expect_swap_cross_origin; + bool expect_swap_new_popup; } cases[] = { // 'unsafe-none' -> * - {COOP::kUnsafeNone, COOP::kUnsafeNone, Result::kNoSwap, Result::kNoSwap, - Result::kNoSwap}, - {COOP::kUnsafeNone, COOP::kSameOrigin, Result::kSwap, Result::kSwap, - Result::kSwap}, - {COOP::kUnsafeNone, COOP::kSameOriginPlusCoep, Result::kSwap, - Result::kSwap, Result::kSwap}, - {COOP::kUnsafeNone, COOP::kSameOriginAllowPopups, Result::kSwap, - Result::kSwap, Result::kSwap}, + {COOP::kUnsafeNone, COOP::kUnsafeNone, false, false, false}, + {COOP::kUnsafeNone, COOP::kSameOrigin, true, true, true}, + {COOP::kUnsafeNone, COOP::kSameOriginPlusCoep, true, true, true}, + {COOP::kUnsafeNone, COOP::kSameOriginAllowPopups, true, true, true}, // 'same-origin' -> * - {COOP::kSameOrigin, COOP::kUnsafeNone, Result::kSwap, Result::kSwap, - Result::kSwap}, - {COOP::kSameOrigin, COOP::kSameOrigin, Result::kNoSwap, Result::kSwap, - Result::kSwap}, - {COOP::kSameOrigin, COOP::kSameOriginPlusCoep, Result::kSwap, - Result::kSwap, Result::kSwap}, - {COOP::kSameOrigin, COOP::kSameOriginAllowPopups, Result::kSwap, - Result::kSwap, Result::kSwap}, + {COOP::kSameOrigin, COOP::kUnsafeNone, true, true, true}, + {COOP::kSameOrigin, COOP::kSameOrigin, false, true, true}, + {COOP::kSameOrigin, COOP::kSameOriginPlusCoep, true, true, true}, + {COOP::kSameOrigin, COOP::kSameOriginAllowPopups, true, true, true}, // 'same-origin' + COEP -> * - {COOP::kSameOriginPlusCoep, COOP::kUnsafeNone, Result::kSwap, - Result::kSwap, Result::kSwap}, - {COOP::kSameOriginPlusCoep, COOP::kSameOrigin, Result::kSwap, - Result::kSwap, Result::kSwap}, - {COOP::kSameOriginPlusCoep, COOP::kSameOriginPlusCoep, Result::kNoSwap, - Result::kSwap, Result::kSwap}, - {COOP::kSameOriginPlusCoep, COOP::kSameOriginAllowPopups, Result::kSwap, - Result::kSwap, Result::kSwap}, + {COOP::kSameOriginPlusCoep, COOP::kUnsafeNone, true, true, true}, + {COOP::kSameOriginPlusCoep, COOP::kSameOrigin, true, true, true}, + {COOP::kSameOriginPlusCoep, COOP::kSameOriginPlusCoep, false, true, true}, + {COOP::kSameOriginPlusCoep, COOP::kSameOriginAllowPopups, true, true, + true}, // 'same-origin-allow-popups' -> * - {COOP::kSameOriginAllowPopups, COOP::kUnsafeNone, Result::kSwap, - Result::kSwap, Result::kNoSwap}, - {COOP::kSameOriginAllowPopups, COOP::kSameOrigin, Result::kSwap, - Result::kSwap, Result::kSwap}, - {COOP::kSameOriginAllowPopups, COOP::kSameOriginPlusCoep, Result::kSwap, - Result::kSwap, Result::kSwap}, - {COOP::kSameOriginAllowPopups, COOP::kSameOriginAllowPopups, - Result::kNoSwap, Result::kSwap, Result::kSwap}, + {COOP::kSameOriginAllowPopups, COOP::kUnsafeNone, true, true, false}, + {COOP::kSameOriginAllowPopups, COOP::kSameOrigin, true, true, true}, + {COOP::kSameOriginAllowPopups, COOP::kSameOriginPlusCoep, true, true, + true}, + {COOP::kSameOriginAllowPopups, COOP::kSameOriginAllowPopups, false, true, + true}, }; for (const auto& test : cases) { url::Origin A = url::Origin::Create(GURL("https://www.a.com"));
diff --git a/content/browser/service_worker/service_worker_main_resource_loader.cc b/content/browser/service_worker/service_worker_main_resource_loader.cc index c3a2b338..68a0d4d6 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader.cc +++ b/content/browser/service_worker/service_worker_main_resource_loader.cc
@@ -253,6 +253,7 @@ RaceNetworkRequestMode race_network_request_mode = RaceNetworkRequestMode::kDefault; + std::optional<network::mojom::ServiceWorkerRouterSourceType> source_type; // Check if registered static router rules match the request. if (active_worker->router_evaluator()) { CHECK(active_worker->router_evaluator()->IsValid()); @@ -284,12 +285,12 @@ blink::mojom::WebFeature::kServiceWorkerStaticRouter_Evaluate); if (eval_result) { // matched the rule. const auto& sources = eval_result->sources; - auto source_type = sources[0].type; - set_matched_router_source_type(source_type); + source_type = sources[0].type; + set_matched_router_source_type(*source_type); router_info->rule_id_matched = eval_result->id; router_info->matched_source_type = source_type; - switch (source_type) { + switch (*source_type) { case network::mojom::ServiceWorkerRouterSourceType::kNetwork: { response_head_->service_worker_router_info->actual_source_type = network::mojom::ServiceWorkerRouterSourceType::kNetwork; @@ -335,64 +336,60 @@ race_network_request_mode = RaceNetworkRequestMode::kSkipped; break; case network::mojom::ServiceWorkerRouterSourceType::kCache: - cache_matcher_ = std::make_unique<ServiceWorkerCacheStorageMatcher>( - sources[0].cache_source->cache_name, - blink::mojom::FetchAPIRequest::From(resource_request_), - active_worker, - base::BindOnce( - &ServiceWorkerMainResourceLoader::DidDispatchFetchEvent, - weak_factory_.GetWeakPtr())); - cache_matcher_->Run(); - // If the kServiceWorkerStaticRouterStartServiceWorker feature is - // enabled, it starts the ServiceWorker manually since we don't - // instantiate ServiceWorkerFetchDispatcher, which involves the - // ServiceWorker startup. - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, - base::BindOnce( - [](scoped_refptr<ServiceWorkerVersion> active_worker) { - if (active_worker->running_status() != - blink::EmbeddedWorkerStatus::kRunning && - base::FeatureList::IsEnabled( - features:: - kServiceWorkerStaticRouterStartServiceWorker)) { - active_worker->StartWorker( - ServiceWorkerMetrics::EventType::STATIC_ROUTER, - base::DoNothing()); - } - }, - active_worker)); + CreateAndRunCacheMatcher(sources[0].cache_source->cache_name, + active_worker); return; case network::mojom::ServiceWorkerRouterSourceType:: - kRaceNetworkAndCache: - // TODO(crbug.com/370844790): implement race network and cache + kRaceNetworkAndCache: { + race_network_request_mode = RaceNetworkRequestMode::kForced; + CreateAndRunCacheMatcher( + sources[0].race_network_and_cache_source->cache_source.cache_name, + active_worker); break; + } } } } - // Dispatch the fetch event. - fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>( - blink::mojom::FetchAPIRequest::From(resource_request_), - resource_request_.destination, /*client_id=*/fetch_event_client_id_, - /*resulting_client_id=*/service_worker_client_->client_uuid(), active_worker, - base::BindOnce(&ServiceWorkerMainResourceLoader::DidPrepareFetchEvent, - weak_factory_.GetWeakPtr(), active_worker, - active_worker->running_status()), - base::BindOnce(&ServiceWorkerMainResourceLoader::DidDispatchFetchEvent, - weak_factory_.GetWeakPtr())); + if (!source_type.has_value() || + *source_type != + network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache) { + // Dispatch the fetch event. + fetch_dispatcher_ = std::make_unique<ServiceWorkerFetchDispatcher>( + blink::mojom::FetchAPIRequest::From(resource_request_), + resource_request_.destination, /*client_id=*/fetch_event_client_id_, + /*resulting_client_id=*/service_worker_client_->client_uuid(), + active_worker, + base::BindOnce(&ServiceWorkerMainResourceLoader::DidPrepareFetchEvent, + weak_factory_.GetWeakPtr(), active_worker, + active_worker->running_status()), + base::BindOnce(&ServiceWorkerMainResourceLoader::DidDispatchFetchEvent, + weak_factory_.GetWeakPtr())); + } if (service_worker_client_->IsContainerForWindowClient()) { MaybeDispatchPreload(race_network_request_mode, context, active_worker); } if (race_network_request_mode == RaceNetworkRequestMode::kForced) { - if (base::FeatureList::IsEnabled( - features:: - kServiceWorkerStaticRouterRaceNetworkRequestPerformanceImprovement)) { - active_worker->CountFeature( - blink::mojom::WebFeature:: - kServiceWorkerStaticRouter_RaceNetworkAndFetchHandlerImprovement); + CHECK(source_type.has_value()); + switch (*source_type) { + case network::mojom::ServiceWorkerRouterSourceType::kNetwork: + case network::mojom::ServiceWorkerRouterSourceType::kCache: + case network::mojom::ServiceWorkerRouterSourceType::kFetchEvent: + NOTREACHED(); + case network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndFetchEvent: + if (base::FeatureList::IsEnabled( + features:: + kServiceWorkerStaticRouterRaceNetworkRequestPerformanceImprovement)) { + active_worker->CountFeature( + blink::mojom::WebFeature:: + kServiceWorkerStaticRouter_RaceNetworkAndFetchHandlerImprovement); + } + break; + case network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache: + return; } } // Record worker start time here as |fetch_dispatcher_| will start a service @@ -563,10 +560,12 @@ mojo::PendingRemote<network::mojom::URLLoaderFactory> remote_factory; forwarded_race_network_request_url_loader_factory_->Clone( remote_factory.InitWithNewPipeAndPassReceiver()); - fetch_dispatcher_->set_race_network_request_token( - base::UnguessableToken::Create()); - fetch_dispatcher_->set_race_network_request_loader_factory( - std::move(remote_factory)); + if (fetch_dispatcher_) { + fetch_dispatcher_->set_race_network_request_token( + base::UnguessableToken::Create()); + fetch_dispatcher_->set_race_network_request_loader_factory( + std::move(remote_factory)); + } mojo::PendingRemote<network::mojom::URLLoaderClient> client_to_pass; race_network_request_url_loader_client_->Bind(&client_to_pass); @@ -598,7 +597,8 @@ bool ServiceWorkerMainResourceLoader::MaybeStartNavigationPreload( scoped_refptr<ServiceWorkerContextWrapper> context_wrapper) { - if (fetch_dispatcher_->MaybeStartNavigationPreload( + if (fetch_dispatcher_ && + fetch_dispatcher_->MaybeStartNavigationPreload( resource_request_, context_wrapper, service_worker_client_)) { SetDispatchedPreloadType(DispatchedPreloadType::kNavigationPreload); return true; @@ -773,7 +773,7 @@ // Transition the state if the fetch result is fallback. This is a special // treatment for the case when RaceNetworkRequest and AutoPreload successfully - // dispatced the network request. + // dispatched the network request. if (is_fallback && !is_race_network_request_aborted) { switch (commit_responsibility()) { case FetchResponseFrom::kNoResponseYet: @@ -881,7 +881,9 @@ } if (IsMatchedRouterSourceType( - network::mojom::ServiceWorkerRouterSourceType::kCache)) { + network::mojom::ServiceWorkerRouterSourceType::kCache) || + IsMatchedRouterSourceType(network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndCache)) { CHECK(cache_matcher_); CHECK(response_head_->service_worker_router_info); response_head_->load_timing.service_worker_cache_lookup_start = @@ -939,7 +941,9 @@ // Determine the actual route type of static routing API when it is used. // If `race-network-and-fetch` was specified, we are setting `kFetchEvent` - // since executing this code means that the fetch event won. For other + // since executing this code means that the fetch event won. + // If `race-network-and-cache` was specified, set `kCache`as the + // `actual_source_type`, since the cache won the race. For other // cases (`kCache`, `kFetchEvent`), the `matched_source_type` will be the // `actual_source_type`. if (auto* route_info = response_head_->service_worker_router_info.get()) { @@ -949,6 +953,12 @@ kRaceNetworkAndFetchEvent) { route_info->actual_source_type = network::mojom::ServiceWorkerRouterSourceType::kFetchEvent; + } else if (route_info->matched_source_type && + *route_info->matched_source_type == + network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndCache) { + route_info->actual_source_type = + network::mojom::ServiceWorkerRouterSourceType::kCache; } else { route_info->actual_source_type = route_info->matched_source_type; } @@ -1214,17 +1224,20 @@ void ServiceWorkerMainResourceLoader::SetCommitResponsibility( FetchResponseFrom fetch_response_from) { // Set the actual source type used in Static Routing API when - // `race-network-and-fetch` is used. Determine this by checking the - // commit responsibility. If it's not the service worker, the network - // has won. - // This check is conducted here since in the case of `knetwork`, it does - // not call `DidDispatchFetchEvent`, where we set the `actual_source_type` - // for the other sources, and the `response_head_` is already passed on. + // `race-network-and-fetch` or `race-network-and-cache` is used. Determine + // this by checking the commit responsibility. If it's not the service worker, + // the network has won. This check is conducted here since in the case of + // `knetwork`, it does not call `DidDispatchFetchEvent`, where we set the + // `actual_source_type` for the other sources, and the `response_head_` is + // already passed on. if (response_head_ && response_head_->service_worker_router_info && response_head_->service_worker_router_info->matched_source_type && - *response_head_->service_worker_router_info->matched_source_type == - network::mojom::ServiceWorkerRouterSourceType:: - kRaceNetworkAndFetchEvent && + (*response_head_->service_worker_router_info->matched_source_type == + network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndFetchEvent || + *response_head_->service_worker_router_info->matched_source_type == + network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndCache) && fetch_response_from == FetchResponseFrom::kWithoutServiceWorker) { response_head_->service_worker_router_info->actual_source_type = network::mojom::ServiceWorkerRouterSourceType::kNetwork; @@ -1741,6 +1754,35 @@ return true; } +void ServiceWorkerMainResourceLoader::CreateAndRunCacheMatcher( + const std::optional<std::string>& cache_name, + scoped_refptr<ServiceWorkerVersion> active_worker) { + cache_matcher_ = std::make_unique<ServiceWorkerCacheStorageMatcher>( + cache_name, blink::mojom::FetchAPIRequest::From(resource_request_), + active_worker, + base::BindOnce(&ServiceWorkerMainResourceLoader::DidDispatchFetchEvent, + weak_factory_.GetWeakPtr())); + cache_matcher_->Run(); + // If the kServiceWorkerStaticRouterStartServiceWorker feature is + // enabled, it starts the ServiceWorker manually since we don't + // instantiate ServiceWorkerFetchDispatcher, which involves the + // ServiceWorker startup. + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce( + [](scoped_refptr<ServiceWorkerVersion> active_worker) { + if (active_worker->running_status() != + blink::EmbeddedWorkerStatus::kRunning && + base::FeatureList::IsEnabled( + features::kServiceWorkerStaticRouterStartServiceWorker)) { + active_worker->StartWorker( + ServiceWorkerMetrics::EventType::STATIC_ROUTER, + base::DoNothing()); + } + }, + active_worker)); +} + ServiceWorkerMainResourceLoaderWrapper::ServiceWorkerMainResourceLoaderWrapper( std::unique_ptr<ServiceWorkerMainResourceLoader> loader) : loader_(std::move(loader)) {}
diff --git a/content/browser/service_worker/service_worker_main_resource_loader.h b/content/browser/service_worker/service_worker_main_resource_loader.h index 420ee14..bc53b17d 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader.h +++ b/content/browser/service_worker/service_worker_main_resource_loader.h
@@ -275,6 +275,10 @@ void OnCompleteSyntheticNetworkRequest( const network::URLLoaderCompletionStatus& status); + void CreateAndRunCacheMatcher( + const std::optional<std::string>& cache_name, + scoped_refptr<ServiceWorkerVersion> active_worker); + NavigationLoaderInterceptor::FallbackCallback fallback_callback_; int32_t request_id_ = 0;
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc b/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc index e20204a8..64b0e18 100644 --- a/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc +++ b/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc
@@ -628,9 +628,14 @@ source.cache_source = cache_source; break; } - case network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache: - // TODO(crbug.com/370844790): implement race network and cache + case network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndCache: { + source.race_network_and_cache_source.emplace(); + blink::ServiceWorkerRouterCacheSource cache_source; + cache_source.cache_name = kTestCacheName; + source.race_network_and_cache_source->cache_source = cache_source; break; + } } rule.sources.emplace_back(source); rules.rules.emplace_back(rule); @@ -758,9 +763,12 @@ // timing info. expect_service_worker_timing = false; } - if (expected_info.service_worker_router_info->matched_source_type == - network::mojom::ServiceWorkerRouterSourceType:: - kRaceNetworkAndFetchEvent && + if ((expected_info.service_worker_router_info->matched_source_type == + network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndFetchEvent || + expected_info.service_worker_router_info->matched_source_type == + network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndCache) && expected_info.service_worker_router_info->actual_source_type == network::mojom::ServiceWorkerRouterSourceType::kNetwork) { // If the matched router source is race and the actual source is @@ -1880,5 +1888,161 @@ } } +// Similar to Basic test setup, but with matching race-network-and-cache static +// routing rule and network wins. +TEST_F(ServiceWorkerMainResourceLoaderTest, + StaticRoutingRaceNetworkAndCacheNetworkWin) { + base::HistogramTester histogram_tester; + + SetupStaticRoutingRules( + network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache); + + SetupStoragePartition(); + + SetupNetworkResponse(); + + StartRequest(CreateRequest()); + client_.RunUntilComplete(); + + EXPECT_EQ(net::OK, client_.completion_status().error_code); + auto& info = client_.response_head(); + EXPECT_EQ(200, info->headers->response_code()); + EXPECT_FALSE(info->load_timing.receive_headers_start.is_null()); + EXPECT_FALSE(info->load_timing.receive_headers_end.is_null()); + auto expected_info = CreateResponseInfoFromServiceWorker(); + expected_info->was_fetched_via_service_worker = true; + auto expected_router_info = CreateExpectedMatchingServiceWorkerRouterInfo( + network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache); + expected_router_info->actual_source_type = + network::mojom::ServiceWorkerRouterSourceType::kNetwork; + expected_info->service_worker_router_info = std::move(expected_router_info); + ExpectResponseInfo(*info, *expected_info); + + histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 0); + if (LoaderRecordsTimingMetrics()) { + histogram_tester.ExpectTotalCount( + "ServiceWorker.LoadTiming.MainFrame.MainResource." + "FetchHandlerEndToFallbackNetwork", + 0); + histogram_tester.ExpectTotalCount( + "ServiceWorker.LoadTiming.MainFrame.MainResource." + "ResponseReceivedToCompleted2", + 0); + } +} + +// Similar to Basic test setup, but with matching race-network-and-cache static +// routing rule and the network wins, but the response is not 2xx. +TEST_F(ServiceWorkerMainResourceLoaderTest, + StaticRoutingRaceNetWorkAndCacheNetworkWinWithNon2xx) { + base::HistogramTester histogram_tester; + + SetupStaticRoutingRules( + network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache); + + SetupNon2xxResponse(); + + base::Time response_time = base::Time::Now(); + auto request = CreateRequestAndSetupCache(response_time); + + StartRequest(CreateRequest()); + client_.RunUntilComplete(); + + EXPECT_EQ(net::OK, client_.completion_status().error_code); + auto& info = client_.response_head(); + EXPECT_EQ(200, info->headers->response_code()); + EXPECT_FALSE(info->load_timing.receive_headers_start.is_null()); + EXPECT_FALSE(info->load_timing.receive_headers_end.is_null()); + EXPECT_FALSE(info->load_timing.service_worker_cache_lookup_start.is_null()); + EXPECT_EQ(info->client_address_space, + network::mojom::IPAddressSpace::kPrivate); + EXPECT_TRUE(info->was_fetched_via_service_worker); + auto expected_info = CreateResponseInfoFromServiceWorker(); + expected_info->service_worker_response_source = + network::mojom::FetchResponseSource::kCacheStorage; + expected_info->response_time = response_time; + expected_info->cache_storage_cache_name = kTestCacheName; + auto expected_router_info = CreateExpectedMatchingServiceWorkerRouterInfo( + network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache); + expected_router_info->actual_source_type = + network::mojom::ServiceWorkerRouterSourceType::kCache; + expected_info->service_worker_router_info = std::move(expected_router_info); + ExpectResponseInfo(*info, *expected_info); + + histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); + if (LoaderRecordsTimingMetrics()) { + histogram_tester.ExpectTotalCount( + "ServiceWorker.LoadTiming.MainFrame.MainResource." + "ResponseReceivedToCompleted2", + 0); + histogram_tester.ExpectTotalCount( + "ServiceWorker.LoadTiming.MainFrame.MainResource." + "FetchHandlerEndToFallbackNetwork", + 0); + } +} + +// Similar to Basic test setup, but with matching race-network-and-cache static +// routing rule and cache wins. +TEST_F(ServiceWorkerMainResourceLoaderTest, + StaticRoutingRaceNetWorkAndCacheCacheWin) { + base::HistogramTester histogram_tester; + + SetupStaticRoutingRules( + network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache); + + SetupErrorNetworkResponse(); + + // Defer the race network request processing to receive the cache + // response first. + DeferRequestHandling(); + + base::Time response_time = base::Time::Now(); + auto request = CreateRequestAndSetupCache(response_time); + + StartRequest(std::move(request)); + client_.RunUntilComplete(); + + // After receiving the cache response, resume the network request + // processing. + HandleDeferedRequest(); + + EXPECT_EQ(net::OK, client_.completion_status().error_code); + auto& info = client_.response_head(); + EXPECT_EQ(200, info->headers->response_code()); + EXPECT_FALSE(info->load_timing.receive_headers_start.is_null()); + EXPECT_FALSE(info->load_timing.receive_headers_end.is_null()); + EXPECT_FALSE(info->load_timing.service_worker_cache_lookup_start.is_null()); + EXPECT_EQ(info->client_address_space, + network::mojom::IPAddressSpace::kPrivate); + EXPECT_TRUE(info->was_fetched_via_service_worker); + auto expected_info = CreateResponseInfoFromServiceWorker(); + expected_info->service_worker_response_source = + network::mojom::FetchResponseSource::kCacheStorage; + expected_info->response_time = response_time; + expected_info->cache_storage_cache_name = kTestCacheName; + auto expected_router_info = CreateExpectedMatchingServiceWorkerRouterInfo( + network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache); + expected_router_info->actual_source_type = + network::mojom::ServiceWorkerRouterSourceType::kCache; + expected_info->service_worker_router_info = std::move(expected_router_info); + ExpectResponseInfo(*info, *expected_info); + + histogram_tester.ExpectUniqueSample(kHistogramMainResourceFetchEvent, + blink::ServiceWorkerStatusCode::kOk, 1); + if (LoaderRecordsTimingMetrics()) { + histogram_tester.ExpectTotalCount( + "ServiceWorker.LoadTiming.MainFrame.MainResource." + "ResponseReceivedToCompleted2", + 0); + histogram_tester.ExpectTotalCount( + "ServiceWorker.LoadTiming.MainFrame.MainResource." + "FetchHandlerEndToFallbackNetwork", + 0); + } +} + } // namespace service_worker_main_resource_loader_unittest } // namespace content
diff --git a/content/browser/site_instance_group.cc b/content/browser/site_instance_group.cc index 7cc0eae..dc4c63f 100644 --- a/content/browser/site_instance_group.cc +++ b/content/browser/site_instance_group.cc
@@ -106,11 +106,6 @@ return browsing_instance_id() == group->browsing_instance_id(); } -bool SiteInstanceGroup::IsCoopRelatedSiteInstanceGroup( - SiteInstanceGroup* group) { - return coop_related_group_token() == group->coop_related_group_token(); -} - void SiteInstanceGroup::RenderProcessHostDestroyed(RenderProcessHost* host) { DCHECK_EQ(process_->GetDeprecatedID(), host->GetDeprecatedID()); process_->RemoveObserver(this); @@ -149,9 +144,7 @@ WebExposedIsolationInfo::CreateNonIsolated(), /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false, - /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt), + /*is_fixed_storage_partition=*/false), process); }
diff --git a/content/browser/site_instance_group.h b/content/browser/site_instance_group.h index 979c6e7..ddac1f98 100644 --- a/content/browser/site_instance_group.h +++ b/content/browser/site_instance_group.h
@@ -14,7 +14,6 @@ #include "base/unguessable_token.h" #include "content/browser/browsing_instance.h" #include "content/browser/renderer_host/agent_scheduling_group_host.h" -#include "content/browser/security/coop/coop_related_group.h" #include "content/common/content_export.h" #include "content/public/browser/browsing_instance_id.h" #include "content/public/browser/render_process_host_observer.h" @@ -134,12 +133,6 @@ // used when a SiteInstanceGroup is available. bool IsRelatedSiteInstanceGroup(SiteInstanceGroup* group); - // Returns true if `group` is in the same CoopRelatedGroup as `this`. This can - // be true even though IsRelatedSiteInstanceGroup returns false, if the two - // SiteInstanceGroups are for different BrowsingInstances in the same - // CoopRelatedGroup. - bool IsCoopRelatedSiteInstanceGroup(SiteInstanceGroup* group); - // Get the number of active frames which belong to this SiteInstanceGroup. If // there are no active frames left, all frames in this SiteInstanceGroup can // be safely discarded. @@ -160,12 +153,6 @@ return browsing_instance_->token(); } - // Returns the token uniquely identifying the CoopRelatedGroup this - // SiteInstanceGroup belongs to. - base::UnguessableToken coop_related_group_token() const { - return browsing_instance_->coop_related_group_token(); - } - AgentSchedulingGroupHost& agent_scheduling_group() { DCHECK_EQ(agent_scheduling_group_->GetProcess(), &*process_); return *agent_scheduling_group_;
diff --git a/content/browser/site_instance_group_unittest.cc b/content/browser/site_instance_group_unittest.cc index 15f2d731..7652ddca 100644 --- a/content/browser/site_instance_group_unittest.cc +++ b/content/browser/site_instance_group_unittest.cc
@@ -30,8 +30,7 @@ scoped_refptr<BrowsingInstance> browsing_instance = new BrowsingInstance( &browser_context, WebExposedIsolationInfo::CreateNonIsolated(), /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false, /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt); + /*is_fixed_storage_partition=*/false); group = new SiteInstanceGroup(browsing_instance.get(), process.get()); browsing_instance_id = group->browsing_instance_id(); }
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc index adaa1cd42..4007e923 100644 --- a/content/browser/site_instance_impl.cc +++ b/content/browser/site_instance_impl.cc
@@ -144,8 +144,7 @@ return base::WrapRefCounted(new SiteInstanceImpl(new BrowsingInstance( browser_context, WebExposedIsolationInfo::CreateNonIsolated(), /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false, - /*coop_related_group=*/nullptr, /*common_coop_origin=*/std::nullopt))); + /*is_fixed_storage_partition=*/false))); } // static @@ -163,12 +162,11 @@ DCHECK(browser_context); // This will create a new SiteInstance and BrowsingInstance. - scoped_refptr<BrowsingInstance> instance(new BrowsingInstance( - browser_context, - url_info.web_exposed_isolation_info.value_or( - WebExposedIsolationInfo::CreateNonIsolated()), - is_guest, is_fenced, is_fixed_storage_partition, - /*coop_related_group=*/nullptr, url_info.common_coop_origin)); + scoped_refptr<BrowsingInstance> instance( + new BrowsingInstance(browser_context, + url_info.web_exposed_isolation_info.value_or( + WebExposedIsolationInfo::CreateNonIsolated()), + is_guest, is_fenced, is_fixed_storage_partition)); // Note: The |allow_default_instance| value used here MUST match the value // used in DoesSiteForURLMatch(). @@ -198,8 +196,7 @@ // It should be safe to just default this to true since the // BrowsingInstance is not shared with frames, and there are no // navigations happening in service workers. - /*is_fixed_storage_partition=*/true, - /*coop_related_group=*/nullptr, url_info.common_coop_origin)); + /*is_fixed_storage_partition=*/true)); // We do NOT want to allow the default site instance here because workers // need to be kept separate from other sites. @@ -238,9 +235,7 @@ browser_context, guest_site_info.web_exposed_isolation_info(), /*is_guest=*/true, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/true, - /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt))); + /*is_fixed_storage_partition=*/true))); site_instance->SetSiteInfoInternal(guest_site_info); return site_instance; @@ -274,9 +269,7 @@ browser_context, embedder_site_instance->GetWebExposedIsolationInfo(), embedder_site_instance->IsGuest(), /*is_fenced=*/should_isolate_fenced_frames, - embedder_site_instance->IsFixedStoragePartition(), - /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt))); + embedder_site_instance->IsFixedStoragePartition()))); // Give the new fenced frame SiteInstance the same site url as its embedder's // SiteInstance to allow it to reuse its embedder's process. We avoid doing @@ -321,9 +314,7 @@ scoped_refptr<BrowsingInstance> instance(new BrowsingInstance( browser_context, WebExposedIsolationInfo::CreateNonIsolated(), /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false, - /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt)); + /*is_fixed_storage_partition=*/false)); auto site_instance = instance->GetSiteInstanceForURL( UrlInfo(UrlInfoInit(url)), /* allow_default_instance */ false); site_instance->set_process_reuse_policy( @@ -795,12 +786,6 @@ url_info, site_instance_group_.get()); } -scoped_refptr<SiteInstanceImpl> -SiteInstanceImpl::GetCoopRelatedSiteInstanceImpl(const UrlInfo& url_info) { - return browsing_instance_->GetCoopRelatedSiteInstanceForURL( - url_info, /* allow_default_instance */ true); -} - AgentSchedulingGroupHost& SiteInstanceImpl::GetOrCreateAgentSchedulingGroup() { // Currently GetOrCreateAgentSchedulingGroup is called in the following // cases: @@ -850,7 +835,7 @@ } size_t SiteInstanceImpl::GetRelatedActiveContentsCount() { - return browsing_instance_->GetCoopRelatedGroupActiveContentsCount(); + return browsing_instance_->active_contents_count(); } namespace { @@ -1364,12 +1349,6 @@ return false; } - // Similarly, the common_coop_origin in the UrlInfo and in this - // SiteInstance's BrowsingInstance must be compatible. - if (url_info.common_coop_origin != GetCommonCoopOrigin()) { - return false; - } - // Similarly, the CrossOriginIsolationKeys should match. if (GetSiteInfo().agent_cluster_key() && GetSiteInfo().agent_cluster_key()->GetCrossOriginIsolationKey() != @@ -1562,11 +1541,6 @@ CrossOriginIsolationMode::kConcrete); } -const std::optional<url::Origin>& SiteInstanceImpl::GetCommonCoopOrigin() - const { - return browsing_instance_->common_coop_origin(); -} - // static void SiteInstance::StartIsolatingSite( BrowserContext* context, @@ -1663,12 +1637,6 @@ return nullptr; } -bool SiteInstanceImpl::IsCoopRelatedSiteInstance( - const SiteInstanceImpl* instance) const { - return instance->browsing_instance_->coop_related_group_token() == - browsing_instance_->coop_related_group_token(); -} - void SiteInstanceImpl::SetProcessForTesting(RenderProcessHost* process) { SetProcessInternal(process); }
diff --git a/content/browser/site_instance_impl.h b/content/browser/site_instance_impl.h index 1170e05..577cc9a 100644 --- a/content/browser/site_instance_impl.h +++ b/content/browser/site_instance_impl.h
@@ -13,7 +13,6 @@ #include "content/browser/browsing_instance.h" #include "content/browser/isolation_context.h" #include "content/browser/process_reuse_policy.h" -#include "content/browser/security/coop/coop_related_group.h" #include "content/browser/site_info.h" #include "content/browser/web_exposed_isolation_info.h" #include "content/common/content_export.h" @@ -147,14 +146,6 @@ scoped_refptr<SiteInstanceImpl> GetMaybeGroupRelatedSiteInstanceImpl( const UrlInfo& url_info); - // This function is used during navigation to get a SiteInstance in the same - // CoopRelatedGroup. If the provided `url_info` matches one of the existing - // BrowsingInstance of that group, a new or already existing SiteInstance in - // that BrowsingInstance, will be picked. Therefore returning the same - // SiteInstance is possible, if called with perfectly matching `url_info`. - scoped_refptr<SiteInstanceImpl> GetCoopRelatedSiteInstanceImpl( - const UrlInfo& url_info); - bool IsSameSiteWithURLInfo(const UrlInfo& url_info); // Returns an AgentSchedulingGroupHost, or creates one if @@ -457,13 +448,6 @@ // is_cross_origin_isolated property of the AgentClusterKey::IsolationKey. bool IsCrossOriginIsolated() const; - // Returns whether the two SiteInstances belong to the same CoopRelatedGroup. - // If so, a subset of JavaScript interactions that are permitted across - // origins (window.postMessage() and window.closed) should be supported. This - // is weaker than IsRelatedSiteInstance: if two SiteInstances belong to the - // same BrowsingInstance, they are related and COOP related. - bool IsCoopRelatedSiteInstance(const SiteInstanceImpl* instance) const; - // Returns the token uniquely identifying the BrowsingInstance this // SiteInstance belongs to. Can safely be sent to the renderer unlike the // BrowsingInstanceID. @@ -471,18 +455,6 @@ return browsing_instance_->token(); } - // Returns the token uniquely identifying the CoopRelatedGroup this - // SiteInstance belongs to. Can safely be sent to the renderer. - base::UnguessableToken coop_related_group_token() const { - return browsing_instance_->coop_related_group_token(); - } - - // Returns the unique origin of all top-level documents in this - // BrowsingInstance. This is only guaranteed by the use of a unique COOP value - // across the BrowsingInstance. It is empty if the BrowsingInstance does not - // contain COOP: same-origin or COOP: restrict-properties documents. - const std::optional<url::Origin>& GetCommonCoopOrigin() const; - // Finds an existing SiteInstance in this SiteInstance's BrowsingInstance that // matches this `url_info` but with the `is_sandboxed_` flag true. It's // assumed that `url_info.url` is 'about:srcdoc' here, so the new SiteInstance
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc index 0939917..7462763 100644 --- a/content/browser/site_instance_impl_unittest.cc +++ b/content/browser/site_instance_impl_unittest.cc
@@ -1017,9 +1017,7 @@ BrowsingInstance* browsing_instance = new BrowsingInstance( browser_context.get(), WebExposedIsolationInfo::CreateNonIsolated(), /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false, - /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt); + /*is_fixed_storage_partition=*/false); const GURL url_a1("http://www.google.com/1.html"); scoped_refptr<SiteInstanceImpl> site_instance_a1( @@ -1054,9 +1052,7 @@ BrowsingInstance* browsing_instance2 = new BrowsingInstance( browser_context.get(), WebExposedIsolationInfo::CreateNonIsolated(), /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false, - /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt); + /*is_fixed_storage_partition=*/false); // Ensure the new SiteInstance is ref counted so that it gets deleted. scoped_refptr<SiteInstanceImpl> site_instance_a2_2( browsing_instance2->GetSiteInstanceForURL( @@ -1100,9 +1096,7 @@ scoped_refptr<BrowsingInstance> browsing_instance = new BrowsingInstance( browser_context.get(), WebExposedIsolationInfo::CreateNonIsolated(), /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false, - /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt); + /*is_fixed_storage_partition=*/false); const GURL url_a1("http://www.google.com/1.html"); scoped_refptr<SiteInstanceImpl> site_instance_a1( @@ -1137,9 +1131,7 @@ BrowsingInstance* browsing_instance2 = new BrowsingInstance( browser_context.get(), WebExposedIsolationInfo::CreateNonIsolated(), /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false, - /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt); + /*is_fixed_storage_partition=*/false); scoped_refptr<SiteInstanceImpl> site_instance_a1_2( browsing_instance2->GetSiteInstanceForURL( UrlInfo::CreateForTesting(url_a1), false)); @@ -1154,9 +1146,7 @@ BrowsingInstance* browsing_instance3 = new BrowsingInstance( browser_context2.get(), WebExposedIsolationInfo::CreateNonIsolated(), /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false, - /*coop_related_group=*/nullptr, - /*common_coop_origin=*/std::nullopt); + /*is_fixed_storage_partition=*/false); scoped_refptr<SiteInstanceImpl> site_instance_a2_3( browsing_instance3->GetSiteInstanceForURL( UrlInfo::CreateForTesting(url_a2), false)); @@ -2295,155 +2285,6 @@ blank_with_opaque_unique_origin)); } -TEST_F(SiteInstanceTest, CoopRelatedSiteInstanceIdentity) { - const GURL test_url("https://example.com"); - - const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( - context(), UrlInfo(UrlInfoInit(test_url)), /*is_guest=*/false, - /*is_fenced=*/false, /*is_fixed_storage_partition=*/false); - - const auto derived_instance = base_instance->GetCoopRelatedSiteInstanceImpl( - UrlInfo(UrlInfoInit(test_url))); - - EXPECT_EQ(derived_instance.get(), base_instance.get()); - EXPECT_TRUE(derived_instance->IsRelatedSiteInstance(base_instance.get())); - EXPECT_TRUE(derived_instance->IsCoopRelatedSiteInstance(base_instance.get())); -} - -TEST_F(SiteInstanceTest, CoopRelatedSiteInstanceCrossSite) { - const GURL test_url("https://example.com"); - - const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( - context(), UrlInfo(UrlInfoInit(test_url)), /*is_guest=*/false, - /*is_fenced=*/false, /*is_fixed_storage_partition=*/false); - - const auto derived_instance = base_instance->GetCoopRelatedSiteInstanceImpl( - UrlInfo(UrlInfoInit(GURL("https://other-example.com")))); - - // Without full Site Isolation, we'll group different sites in the default - // SiteInstance. - if (!AreAllSitesIsolatedForTesting()) { - EXPECT_EQ(derived_instance.get(), base_instance.get()); - return; - } - - EXPECT_NE(derived_instance.get(), base_instance.get()); - EXPECT_TRUE(derived_instance->IsRelatedSiteInstance(base_instance.get())); - EXPECT_TRUE(derived_instance->IsCoopRelatedSiteInstance(base_instance.get())); -} - -TEST_F(SiteInstanceTest, CoopRelatedSiteInstanceIdenticalCoopOriginSameSite) { - const GURL test_url("https://example.com"); - - const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( - context(), - UrlInfo(UrlInfoInit(test_url).WithCommonCoopOrigin( - url::Origin::Create(test_url))), - /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false); - - const auto derived_instance = base_instance->GetCoopRelatedSiteInstanceImpl( - UrlInfo(UrlInfoInit(test_url).WithCommonCoopOrigin( - url::Origin::Create(test_url)))); - EXPECT_EQ(derived_instance.get(), base_instance.get()); - EXPECT_TRUE(derived_instance->IsRelatedSiteInstance(base_instance.get())); - EXPECT_TRUE(derived_instance->IsCoopRelatedSiteInstance(base_instance.get())); -} - -TEST_F(SiteInstanceTest, CoopRelatedSiteInstanceIdenticalCoopOriginCrossSite) { - const GURL test_url("https://example.com"); - - const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( - context(), - UrlInfo(UrlInfoInit(test_url).WithCommonCoopOrigin( - url::Origin::Create(test_url))), - /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false); - - // COOP common origin might differ from the frame's actual origin (for - // example for cross-origin subframes), so we verify that this case is handled - // properly. - const auto derived_instance = base_instance->GetCoopRelatedSiteInstanceImpl( - UrlInfo(UrlInfoInit(GURL("https://other-example.com")) - .WithCommonCoopOrigin(url::Origin::Create(test_url)))); - - // Without full Site Isolation, we'll group different sites in the default - // SiteInstance. - if (!AreAllSitesIsolatedForTesting()) { - EXPECT_EQ(derived_instance.get(), base_instance.get()); - return; - } - - EXPECT_NE(derived_instance.get(), base_instance.get()); - EXPECT_TRUE(derived_instance->IsRelatedSiteInstance(base_instance.get())); - EXPECT_TRUE(derived_instance->IsCoopRelatedSiteInstance(base_instance.get())); -} - -TEST_F(SiteInstanceTest, CoopRelatedSiteInstanceDifferentCoopOrigin) { - const GURL test_url("https://example.com"); - - // Start without a COOP origin. - const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( - context(), UrlInfo(UrlInfoInit(test_url)), /*is_guest=*/false, - /*is_fenced=*/false, /*is_fixed_storage_partition=*/false); - - const auto derived_instance = base_instance->GetCoopRelatedSiteInstanceImpl( - UrlInfo(UrlInfoInit(test_url).WithCommonCoopOrigin( - url::Origin::Create(test_url)))); - EXPECT_NE(derived_instance.get(), base_instance.get()); - EXPECT_FALSE(derived_instance->IsRelatedSiteInstance(base_instance.get())); - EXPECT_TRUE(derived_instance->IsCoopRelatedSiteInstance(base_instance.get())); -} - -TEST_F(SiteInstanceTest, CoopRelatedSiteInstanceIdenticalCrossOriginIsolation) { - const GURL test_url("https://example.com"); - - const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( - context(), - UrlInfo(UrlInfoInit(test_url).WithWebExposedIsolationInfo( - WebExposedIsolationInfo::CreateIsolated( - url::Origin::Create(test_url)))), - /*is_guest=*/false, /*is_fenced=*/false, - /*is_fixed_storage_partition=*/false); - - const auto derived_instance = base_instance->GetCoopRelatedSiteInstanceImpl( - UrlInfo(UrlInfoInit(test_url).WithWebExposedIsolationInfo( - WebExposedIsolationInfo::CreateIsolated( - url::Origin::Create(test_url))))); - EXPECT_EQ(derived_instance.get(), base_instance.get()); - EXPECT_TRUE(derived_instance->IsRelatedSiteInstance(base_instance.get())); - EXPECT_TRUE(derived_instance->IsCoopRelatedSiteInstance(base_instance.get())); -} - -TEST_F(SiteInstanceTest, CoopRelatedSiteInstanceDifferentCrossOriginIsolation) { - const GURL test_url("https://example.com"); - - const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( - context(), UrlInfo(UrlInfoInit(test_url)), /*is_guest=*/false, - /*is_fenced=*/false, /*is_fixed_storage_partition=*/false); - - const auto derived_instance = base_instance->GetCoopRelatedSiteInstanceImpl( - UrlInfo(UrlInfoInit(test_url).WithWebExposedIsolationInfo( - WebExposedIsolationInfo::CreateIsolated( - url::Origin::Create(test_url))))); - EXPECT_NE(derived_instance.get(), base_instance.get()); - EXPECT_FALSE(derived_instance->IsRelatedSiteInstance(base_instance.get())); - EXPECT_TRUE(derived_instance->IsCoopRelatedSiteInstance(base_instance.get())); -} - -TEST_F(SiteInstanceTest, GroupTokensBuilding) { - const GURL test_url("https://example.com"); - const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( - context(), UrlInfo(UrlInfoInit(test_url)), /*is_guest=*/false, - /*is_fenced=*/false, /*is_fixed_storage_partition=*/false); - - base::UnguessableToken browsing_instance_token = - base_instance->browsing_instance_token(); - base::UnguessableToken coop_related_group_token = - base_instance->coop_related_group_token(); - EXPECT_NE(browsing_instance_token, coop_related_group_token); -} - TEST_F(SiteInstanceTest, GroupTokensRelatedSiteInstances) { const GURL test_url("https://example.com"); const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( @@ -2464,30 +2305,6 @@ EXPECT_TRUE(derived_instance->IsRelatedSiteInstance(base_instance.get())); EXPECT_EQ(derived_instance->browsing_instance_token(), base_instance->browsing_instance_token()); - EXPECT_EQ(derived_instance->coop_related_group_token(), - base_instance->coop_related_group_token()); -} - -TEST_F(SiteInstanceTest, GroupTokensCoopRelatedSiteInstances) { - const GURL test_url("https://example.com"); - const auto base_instance = SiteInstanceImpl::CreateForUrlInfo( - context(), UrlInfo(UrlInfoInit(test_url)), /*is_guest=*/false, - /*is_fenced=*/false, /*is_fixed_storage_partition=*/false); - - // Derive a SiteInstance that lives in the same CoopRelatedGroup but a - // different BrowsingInstance. Provide a different WebExposedIsolationInfo to - // make sure we do not reuse the BrowsingInstance. - const auto derived_instance = base_instance->GetCoopRelatedSiteInstanceImpl( - UrlInfo(UrlInfoInit(test_url).WithWebExposedIsolationInfo( - WebExposedIsolationInfo::CreateIsolated( - url::Origin::Create(test_url))))); - EXPECT_NE(derived_instance.get(), base_instance.get()); - EXPECT_FALSE(derived_instance->IsRelatedSiteInstance(base_instance.get())); - EXPECT_TRUE(derived_instance->IsCoopRelatedSiteInstance(base_instance.get())); - EXPECT_NE(derived_instance->browsing_instance_token(), - base_instance->browsing_instance_token()); - EXPECT_EQ(derived_instance->coop_related_group_token(), - base_instance->coop_related_group_token()); } TEST_F(SiteInstanceTest, GroupTokensUnrelatedSiteInstances) { @@ -2502,11 +2319,8 @@ EXPECT_NE(other_instance.get(), base_instance.get()); EXPECT_FALSE(other_instance->IsRelatedSiteInstance(base_instance.get())); - EXPECT_FALSE(other_instance->IsCoopRelatedSiteInstance(base_instance.get())); EXPECT_NE(other_instance->browsing_instance_token(), base_instance->browsing_instance_token()); - EXPECT_NE(other_instance->coop_related_group_token(), - base_instance->coop_related_group_token()); } namespace {
diff --git a/content/browser/url_info.cc b/content/browser/url_info.cc index 333fa8a..c6a0218 100644 --- a/content/browser/url_info.cc +++ b/content/browser/url_info.cc
@@ -29,7 +29,6 @@ storage_partition_config(init.storage_partition_config_), web_exposed_isolation_info(init.web_exposed_isolation_info_), is_pdf(init.is_pdf_), - common_coop_origin(init.common_coop_origin_), cross_origin_isolation_key(init.cross_origin_isolation_key_) { // An origin-keyed process can only be used for origin-keyed agent clusters. // We can check this for the explicit header case here, and it is checked more @@ -165,12 +164,6 @@ return *this; } -UrlInfoInit& UrlInfoInit::WithCommonCoopOrigin( - const url::Origin& common_coop_origin) { - common_coop_origin_ = common_coop_origin; - return *this; -} - UrlInfoInit& UrlInfoInit::WithCrossOriginIsolationKey( const std::optional<AgentClusterKey::CrossOriginIsolationKey>& cross_origin_isolation_key) {
diff --git a/content/browser/url_info.h b/content/browser/url_info.h index 342687f0..ec4beb115 100644 --- a/content/browser/url_info.h +++ b/content/browser/url_info.h
@@ -203,21 +203,6 @@ // NativePage is created for a main frame navigation. bool is_pdf = false; - // If set, indicates that this UrlInfo is for a document that sets either - // COOP: same-origin or COOP: restrict-properties from the given origin. For - // subframes, it is inherited from the top-level frame. This is used to select - // an appropriate BrowsingInstance when navigating within a CoopRelatedGroup. - // - // Note: This cannot be part of the WebExposedIsolationInfo, because while it - // might force a different BrowsingInstance to be used, it may not force a - // strict process isolation, which non-matching web_exposed_isolation_info - // implies. Example: a top-level a.com document sets COOP: - // restrict-properties, and an a.com iframe in another tab has no COOP set. - // Under memory pressure they should be able to reuse the same process. This - // is not the case if the top-level document sets COOP: restrict-properties + - // COEP, because it then has an isolated WebExposedIsolationInfo. - std::optional<url::Origin> common_coop_origin; - // The CrossOriginIsolationKey to use for the navigation. This represents the // isolation requested by the page itself through the use of COOP, COEP and // DIP. Right now, this is only set when DocumentIsolationPolicy is enabled, @@ -251,7 +236,6 @@ UrlInfoInit& WithWebExposedIsolationInfo( std::optional<WebExposedIsolationInfo> web_exposed_isolation_info); UrlInfoInit& WithIsPdf(bool is_pdf); - UrlInfoInit& WithCommonCoopOrigin(const url::Origin& origin); UrlInfoInit& WithCrossOriginIsolationKey( const std::optional<AgentClusterKey::CrossOriginIsolationKey>& cross_origin_isolation_key); @@ -274,7 +258,6 @@ std::optional<StoragePartitionConfig> storage_partition_config_; std::optional<WebExposedIsolationInfo> web_exposed_isolation_info_; bool is_pdf_ = false; - std::optional<url::Origin> common_coop_origin_; std::optional<AgentClusterKey::CrossOriginIsolationKey> cross_origin_isolation_key_;
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 2039ac7..4c48081c 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -9248,9 +9248,8 @@ } std::vector<RenderFrameHostImpl*> -WebContentsImpl::GetActiveTopLevelDocumentsInGroup( - RenderFrameHostImpl* render_frame_host, - GroupType group_type) { +WebContentsImpl::GetActiveTopLevelDocumentsInBrowsingContextGroup( + RenderFrameHostImpl* render_frame_host) { std::vector<RenderFrameHostImpl*> out; for (WebContentsImpl* web_contents : GetAllWebContents()) { RenderFrameHostImpl* other_render_frame_host = @@ -9262,18 +9261,8 @@ continue; } - // If we're looking for frames in the same browsing context group, filter - // frames in different browsing context groups. - if (group_type == GroupType::kBrowsingContextGroup && - !render_frame_host->GetSiteInstance()->IsRelatedSiteInstance( - other_render_frame_host->GetSiteInstance())) { - continue; - } - - // If we're looking for frames in the same CoopRelatedGroup, filter frames - // in different CoopRelatedGroups. - if (group_type == GroupType::kCoopRelatedGroup && - !render_frame_host->GetSiteInstance()->IsCoopRelatedSiteInstance( + // Filter frames in different browsing context groups. + if (!render_frame_host->GetSiteInstance()->IsRelatedSiteInstance( other_render_frame_host->GetSiteInstance())) { continue; } @@ -9283,20 +9272,6 @@ return out; } -std::vector<RenderFrameHostImpl*> -WebContentsImpl::GetActiveTopLevelDocumentsInBrowsingContextGroup( - RenderFrameHostImpl* render_frame_host) { - return GetActiveTopLevelDocumentsInGroup(render_frame_host, - GroupType::kBrowsingContextGroup); -} - -std::vector<RenderFrameHostImpl*> -WebContentsImpl::GetActiveTopLevelDocumentsInCoopRelatedGroup( - RenderFrameHostImpl* render_frame_host) { - return GetActiveTopLevelDocumentsInGroup(render_frame_host, - GroupType::kCoopRelatedGroup); -} - PrerenderHostRegistry* WebContentsImpl::GetPrerenderHostRegistry() { DCHECK(prerender_host_registry_); return prerender_host_registry_.get();
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h index c0a0400..ebbefa0 100644 --- a/content/browser/web_contents/web_contents_impl.h +++ b/content/browser/web_contents/web_contents_impl.h
@@ -916,9 +916,6 @@ std::vector<RenderFrameHostImpl*> GetActiveTopLevelDocumentsInBrowsingContextGroup( RenderFrameHostImpl* render_frame_host) override; - std::vector<RenderFrameHostImpl*> - GetActiveTopLevelDocumentsInCoopRelatedGroup( - RenderFrameHostImpl* render_frame_host) override; PrerenderHostRegistry* GetPrerenderHostRegistry() override; #if BUILDFLAG(ENABLE_PPAPI) void OnPepperInstanceCreated(RenderFrameHostImpl* source, @@ -2192,16 +2189,6 @@ const mojom::CreateNewWindowParams& params, RenderFrameHostImpl* opener); - // Describes the different types of groups we can be interested in when - // looking for scriptable frames. - enum class GroupType { kBrowsingContextGroup, kCoopRelatedGroup }; - - // Returns a vector of all the top-level active frames in the same group type - // specified by `group_type`. - std::vector<RenderFrameHostImpl*> GetActiveTopLevelDocumentsInGroup( - RenderFrameHostImpl* render_frame_host, - GroupType group_type); - // Creates a new ForwardingAudioStreamFactory. std::unique_ptr<ForwardingAudioStreamFactory> CreateAudioStreamFactory();
diff --git a/content/common/service_worker/service_worker_router_evaluator.cc b/content/common/service_worker/service_worker_router_evaluator.cc index 27aa47d..f1dda13 100644 --- a/content/common/service_worker/service_worker_router_evaluator.cc +++ b/content/common/service_worker/service_worker_router_evaluator.cc
@@ -820,7 +820,15 @@ break; case network::mojom::ServiceWorkerRouterSourceType:: kRaceNetworkAndCache: - // TODO(crbug.com/370844790): implement race network and cache + if (s.race_network_and_cache_source->cache_source.cache_name) { + base::Value::Dict out_s; + out_s.Set( + "race_network_and_cache_cache_name", + *s.race_network_and_cache_source->cache_source.cache_name); + source.Append(std::move(out_s)); + } else { + source.Append("race-network-and-cache"); + } break; } }
diff --git a/content/common/service_worker/service_worker_router_evaluator_unittest.cc b/content/common/service_worker/service_worker_router_evaluator_unittest.cc index 30b372b..ad93016 100644 --- a/content/common/service_worker/service_worker_router_evaluator_unittest.cc +++ b/content/common/service_worker/service_worker_router_evaluator_unittest.cc
@@ -1383,6 +1383,25 @@ source.cache_source = cache_source; rule.sources.push_back(source); } + { + blink::ServiceWorkerRouterSource source; + source.type = + network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache; + source.race_network_and_cache_source.emplace(); + blink::ServiceWorkerRouterCacheSource cache_source; + source.race_network_and_cache_source->cache_source = cache_source; + rule.sources.push_back(source); + } + { + blink::ServiceWorkerRouterSource source; + source.type = + network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache; + source.race_network_and_cache_source.emplace(); + blink::ServiceWorkerRouterCacheSource cache_source; + cache_source.cache_name = "example_cache_name"; + source.race_network_and_cache_source->cache_source = cache_source; + rule.sources.push_back(source); + } rules.rules.push_back(rule); } ASSERT_EQ(1U, rules.rules.size()); @@ -1431,6 +1450,12 @@ source.Set("cache_name", "example_cache_name"); sources.Append(std::move(source)); } + sources.Append("race-network-and-cache"); + { + base::Value::Dict source; + source.Set("race_network_and_cache_cache_name", "example_cache_name"); + sources.Append(std::move(source)); + } rule.Set("source", std::move(sources)); } }
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java index bcdabfb..4401b0b5e 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityActionAndEventTracker.java
@@ -110,18 +110,7 @@ * @return String representation of the given event */ private static @Nullable String eventToString(AccessibilityEvent event) { - // Convert event type to a human readable String (except TYPE_WINDOW_CONTENT_CHANGED with no - // CONTENT_CHANGE_TYPE_STATE_DESCRIPTION flag or CONTENT_CHANGE_TYPE_PANE_TITLE flag) - if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED - && (event.getContentChangeTypes() - & AccessibilityEvent.CONTENT_CHANGE_TYPE_STATE_DESCRIPTION) - == 0 - && (event.getContentChangeTypes() - & AccessibilityEvent.CONTENT_CHANGE_TYPE_PANE_TITLE) - == 0) { - return null; - } - + // Convert event type to a human readable String StringBuilder builder = new StringBuilder(); builder.append(AccessibilityEvent.eventTypeToString(event.getEventType()));
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java index 3523e70..4fda149 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityEventsTest.java
@@ -173,21 +173,21 @@ @EnableFeatures(ContentFeatureList.ACCESSIBILITY_DEPRECATE_TYPE_ANNOUNCE) @DisabledTest(message = "https://crbug.com/414363686") public void test_addAlertContent_exp() { - performTest("add-alert-content.html", EMPTY_EXPECTATIONS_FILE); + performTest("add-alert-content.html", "add-alert-content-expected-android-exp.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_addChild() { - performTest("add-child.html", EMPTY_EXPECTATIONS_FILE); + performTest("add-child.html", "add-child-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_addChildOfBody() { - performTest("add-child-of-body.html", EMPTY_EXPECTATIONS_FILE); + performTest("add-child-of-body.html", "add-child-of-body-expected-android.txt"); } @Test @@ -218,7 +218,7 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_addHiddenAttribute() { - performTest("add-hidden-attribute.html", EMPTY_EXPECTATIONS_FILE); + performTest("add-hidden-attribute.html", "add-hidden-attribute-expected-android.txt"); } @Test @@ -241,35 +241,37 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_anonymousBlockChildrenChanged() { - performTest("anonymous-block-children-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "anonymous-block-children-changed.html", + "anonymous-block-children-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaAtomicChanged() { - performTest("aria-atomic-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-atomic-changed.html", "aria-atomic-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaAtomicChanged2() { - performTest("aria-atomic-changed2.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-atomic-changed2.html", "aria-atomic-changed2-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaBusyChanged() { - performTest("aria-busy-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-busy-changed.html", "aria-busy-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaButtonExpand() { - performTest("aria-button-expand.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-button-expand.html", "aria-button-expand-expected-android.txt"); } @Test @@ -330,77 +332,84 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaComboboxUneditable() { - performTest("aria-combo-box-uneditable.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-combo-box-uneditable.html", "aria-combo-box-uneditable-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaControlsChanged() { - performTest("aria-controls-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-controls-changed.html", "aria-controls-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaCurrentChanged() { - performTest("aria-current-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-current-changed.html", "aria-current-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaDisabledChanged() { - performTest("aria-disabled-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-disabled-changed.html", "aria-disabled-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaFlowTo() { - performTest("aria-flow-to.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-flow-to.html", "aria-flow-to-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaHasPopupChanged() { - performTest("aria-haspopup-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-haspopup-changed.html", "aria-haspopup-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaHiddenChanged() { - performTest("aria-hidden-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-hidden-changed.html", "aria-hidden-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaHiddenDescendantsAlreadyIgnored() { - performTest("aria-hidden-descendants-already-ignored.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-hidden-descendants-already-ignored.html", + "aria-hidden-descendants-already-ignored-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaHiddenDescendants() { - performTest("aria-hidden-descendants.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-hidden-descendants.html", "aria-hidden-descendants-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaHiddenDescendantDisplayNone() { - performTest("aria-hidden-single-descendant-display-none.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-hidden-single-descendant-display-none.html", + "aria-hidden-single-descendant-display-none-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaHiddenSingleDescendant() { - performTest("aria-hidden-single-descendant.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-hidden-single-descendant.html", + "aria-hidden-single-descendant-expected-android.txt"); } @Test @@ -408,49 +417,52 @@ @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaHiddenSingleDescendantVisibilityHidden() { performTest( - "aria-hidden-single-descendant-visibility-hidden.html", EMPTY_EXPECTATIONS_FILE); + "aria-hidden-single-descendant-visibility-hidden.html", + "aria-hidden-single-descendant-visibility-hidden-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaLevelChanged() { - performTest("aria-level-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-level-changed.html", "aria-level-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaLiveChanged() { - performTest("aria-live-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-live-changed.html", "aria-live-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/1190218") public void test_ariaMenuItemFocus() { - performTest("aria-menuitem-focus.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-menuitem-focus.html", "aria-menuitem-focus-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaMultilineChanged() { - performTest("aria-multiline-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-multiline-changed.html", "aria-multiline-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaMultiselectableChanged() { - performTest("aria-multiselectable-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-multiselectable-changed.html", + "aria-multiselectable-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaPosinsetChanged() { - performTest("aria-posinset-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-posinset-changed.html", "aria-posinset-changed-expected-android.txt"); } @Test @@ -473,28 +485,28 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaReadonlyChanged() { - performTest("aria-readonly-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-readonly-changed.html", "aria-readonly-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaRelevantChanged() { - performTest("aria-relevant-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-relevant-changed.html", "aria-relevant-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaRelevantChanged2() { - performTest("aria-relevant-changed2.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-relevant-changed2.html", "aria-relevant-changed2-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaRequiredChanged() { - performTest("aria-required-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-required-changed.html", "aria-required-changed-expected-android.txt"); } @Test @@ -508,14 +520,16 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaSelectedChangedNewSubtree() { - performTest("aria-selected-changed-new-subtree.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-selected-changed-new-subtree.html", + "aria-selected-changed-new-subtree-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaSetsizeChanged() { - performTest("aria-setsize-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-setsize-changed.html", "aria-setsize-changed-expected-android.txt"); } @Test @@ -548,70 +562,82 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaSortChanged() { - performTest("aria-sort-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-sort-changed.html", "aria-sort-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaSpinbuttonValueBothChanged() { - performTest("aria-spinbutton-value-both-change.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-spinbutton-value-both-change.html", + "aria-spinbutton-value-both-change-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaSpinbuttonValueChanged() { - performTest("aria-spinbutton-value-change.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-spinbutton-value-change.html", + "aria-spinbutton-value-change-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaSpinbuttonValuetextChanged() { - performTest("aria-spinbutton-valuetext-change.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-spinbutton-valuetext-change.html", + "aria-spinbutton-valuetext-change-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaTextboxChildrenChange() { - performTest("aria-textbox-children-change.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-textbox-children-change.html", + "aria-textbox-children-change-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaTextboxEditabilityChanges() { - performTest("aria-textbox-editability-changes.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-textbox-editability-changes.html", + "aria-textbox-editability-changes-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaTextboxWithFocusableChildren() { - performTest("aria-textbox-with-focusable-children.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "aria-textbox-with-focusable-children.html", + "aria-textbox-with-focusable-children-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaTreeCollapse() { - performTest("aria-tree-collapse.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-tree-collapse.html", "aria-tree-collapse-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaTreeExpand() { - performTest("aria-tree-expand.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-tree-expand.html", "aria-tree-expand-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ariaTreeItemFocus() { - performTest("aria-treeitem-focus.html", EMPTY_EXPECTATIONS_FILE); + performTest("aria-treeitem-focus.html", "aria-treeitem-focus-expected-android.txt"); } @Test @@ -625,7 +651,7 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_buttonRemoveChildren() { - performTest("button-remove-children.html", EMPTY_EXPECTATIONS_FILE); + performTest("button-remove-children.html", "button-remove-children-expected-android.txt"); } @Test @@ -675,35 +701,37 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_checkboxValidity() { - performTest("checkbox-validity.html", EMPTY_EXPECTATIONS_FILE); + performTest("checkbox-validity.html", "checkbox-validity-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_checkedMixedChanged() { - performTest("checked-mixed-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("checked-mixed-changed.html", "checked-mixed-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_checkedStateChanged() { - performTest("checked-state-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("checked-state-changed.html", "checked-state-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_childrenChangedOnlyOnAncestor() { - performTest("children-changed-only-on-ancestor.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "children-changed-only-on-ancestor.html", + "children-changed-only-on-ancestor-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_cssDisplayDescendants() { - performTest("css-display-descendants.html", EMPTY_EXPECTATIONS_FILE); + performTest("css-display-descendants.html", "css-display-descendants-expected-android.txt"); } @Test @@ -717,28 +745,30 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_cssFlexTextUpdate() { - performTest("css-flex-text-update.html", EMPTY_EXPECTATIONS_FILE); + performTest("css-flex-text-update.html", "css-flex-text-update-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_cssVisibilityCollapse() { - performTest("css-visibility-collapse.html", EMPTY_EXPECTATIONS_FILE); + performTest("css-visibility-collapse.html", "css-visibility-collapse-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_cssVisibilityDescendants() { - performTest("css-visibility-descendants.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "css-visibility-descendants.html", + "css-visibility-descendants-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_cssVisibility() { - performTest("css-visibility.html", EMPTY_EXPECTATIONS_FILE); + performTest("css-visibility.html", "css-visibility-expected-android.txt"); } @Test @@ -752,7 +782,7 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_descriptionChanged() { - performTest("description-change.html", EMPTY_EXPECTATIONS_FILE); + performTest("description-change.html", "description-change-expected-android.txt"); } @Test @@ -777,35 +807,39 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_descriptionChangedIndirect() { - performTest("description-change-indirect.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "description-change-indirect.html", + "description-change-indirect-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_descriptionChangedNoRelation() { - performTest("description-change-no-relation.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "description-change-no-relation.html", + "description-change-no-relation-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_disabledStateChanged() { - performTest("disabled-state-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("disabled-state-changed.html", "disabled-state-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_documentTitleChanged() { - performTest("document-title-change.html", EMPTY_EXPECTATIONS_FILE); + performTest("document-title-change.html", "document-title-change-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_expandedChanged() { - performTest("expanded-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("expanded-changed.html", "expanded-changed-expected-android.txt"); } @Test @@ -820,21 +854,22 @@ @SmallTest @DisabledTest(message = "https://crbug.com/1190218") public void test_focusListbox() { - performTest("focus-listbox.html", EMPTY_EXPECTATIONS_FILE); + performTest("focus-listbox.html", "focus-listbox-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/1190218") public void test_focusListboxMultiselect() { - performTest("focus-listbox-multiselect.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "focus-listbox-multiselect.html", "focus-listbox-multiselect-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_formDisabledChanged() { - performTest("form-disabled-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("form-disabled-changed.html", "form-disabled-changed-expected-android.txt"); } @Test @@ -848,21 +883,21 @@ @SmallTest @DisabledTest(message = "https://crbug.com/1392791") public void test_immediateRefresh() { - performTest("immediate-refresh.html", EMPTY_EXPECTATIONS_FILE); + performTest("immediate-refresh.html", "immediate-refresh-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_innerHtmlChanged() { - performTest("inner-html-change.html", EMPTY_EXPECTATIONS_FILE); + performTest("inner-html-change.html", "inner-html-change-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_iframeSrcChanged() { - performTest("iframe-src-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("iframe-src-changed.html", "iframe-src-changed-expected-android.txt"); } @Test @@ -890,21 +925,23 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_inputTypeTextValueChanged() { - performTest("input-type-text-value-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "input-type-text-value-changed.html", + "input-type-text-value-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/1190218") public void test_listboxFocus() { - performTest("listbox-focus.html", EMPTY_EXPECTATIONS_FILE); + performTest("listbox-focus.html", "listbox-focus-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_listboxNext() { - performTest("listbox-next.html", EMPTY_EXPECTATIONS_FILE); + performTest("listbox-next.html", "listbox-next-expected-android.txt"); } @Test @@ -920,14 +957,16 @@ @EnableFeatures(ContentFeatureList.ACCESSIBILITY_DEPRECATE_TYPE_ANNOUNCE) @DisabledTest(message = "https://crbug.com/414363686") public void test_liveRegionAdd_exp() { - performTest("live-region-add.html", EMPTY_EXPECTATIONS_FILE); + performTest("live-region-add.html", "live-region-add-expected-android-exp.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_liveRegionAddLiveAttribute() { - performTest("live-region-add-live-attribute.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "live-region-add-live-attribute.html", + "live-region-add-live-attribute-expected-android.txt"); } @Test @@ -943,7 +982,7 @@ @EnableFeatures(ContentFeatureList.ACCESSIBILITY_DEPRECATE_TYPE_ANNOUNCE) @DisabledTest(message = "https://crbug.com/414363686") public void test_liveRegionChanged_exp() { - performTest("live-region-change.html", EMPTY_EXPECTATIONS_FILE); + performTest("live-region-change.html", "live-region-change-expected-android-exp.txt"); } @Test @@ -961,7 +1000,9 @@ @EnableFeatures(ContentFeatureList.ACCESSIBILITY_DEPRECATE_TYPE_ANNOUNCE) @DisabledTest(message = "https://crbug.com/414363686") public void test_liveRegionChangedInnerHtml_exp() { - performTest("live-region-change-innerhtml.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "live-region-change-innerhtml.html", + "live-region-change-innerhtml-expected-android-exp.txt"); } @Test @@ -979,14 +1020,16 @@ @EnableFeatures(ContentFeatureList.ACCESSIBILITY_DEPRECATE_TYPE_ANNOUNCE) @DisabledTest(message = "https://crbug.com/414363686") public void test_liveRegionChangedInnerText_exp() { - performTest("live-region-change-innertext.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "live-region-change-innertext.html", + "live-region-change-innertext-expected-android-exp.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_liveRegionCreate() { - performTest("live-region-create.html", EMPTY_EXPECTATIONS_FILE); + performTest("live-region-create.html", "live-region-create-expected-android.txt"); } @Test @@ -1020,91 +1063,93 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_liveRegionOff() { - performTest("live-region-off.html", EMPTY_EXPECTATIONS_FILE); + performTest("live-region-off.html", "live-region-off-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_liveRegionRemove() { - performTest("live-region-remove.html", EMPTY_EXPECTATIONS_FILE); + performTest("live-region-remove.html", "live-region-remove-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_menuBarShowHideMenus() { - performTest("menubar-show-hide-menus.html", EMPTY_EXPECTATIONS_FILE); + performTest("menubar-show-hide-menus.html", "menubar-show-hide-menus-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_menulistCollapse() { - performTest("menulist-collapse.html", EMPTY_EXPECTATIONS_FILE); + performTest("menulist-collapse.html", "menulist-collapse-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_menulistCollapseNext() { - performTest("menulist-collapse-next.html", EMPTY_EXPECTATIONS_FILE); + performTest("menulist-collapse-next.html", "menulist-collapse-next-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_menulistExpand() { - performTest("menulist-expand.html", EMPTY_EXPECTATIONS_FILE); + performTest("menulist-expand.html", "menulist-expand-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/1190218") public void test_menulistFocus() { - performTest("menulist-focus.html", EMPTY_EXPECTATIONS_FILE); + performTest("menulist-focus.html", "menulist-focus-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_menulistNext() { - performTest("menulist-next.html", EMPTY_EXPECTATIONS_FILE); + performTest("menulist-next.html", "menulist-next-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_menuOpenedClosed() { - performTest("menu-opened-closed.html", EMPTY_EXPECTATIONS_FILE); + performTest("menu-opened-closed.html", "menu-opened-closed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_multipleAriaPropertiesChanged() { - performTest("multiple-aria-properties-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "multiple-aria-properties-changed.html", + "multiple-aria-properties-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_nameChanged() { - performTest("name-change.html", EMPTY_EXPECTATIONS_FILE); + performTest("name-change.html", "name-change-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_nameChangedIndirect() { - performTest("name-change-indirect.html", EMPTY_EXPECTATIONS_FILE); + performTest("name-change-indirect.html", "name-change-indirect-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "crbug.com/382549182") public void test_navigationApi() { - performTest("navigation-api.html", EMPTY_EXPECTATIONS_FILE); + performTest("navigation-api.html", "navigation-api-expected-android.txt"); } @Test @@ -1118,28 +1163,35 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_rangeValueIsReadonlyChanged() { - performTest("range-value-is-readonly-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "range-value-is-readonly-changed.html", + "range-value-is-readonly-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_rangeValueMaximumChanged() { - performTest("range-value-maximum-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "range-value-maximum-changed.html", + "range-value-maximum-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_rangeValueMinimumChanged() { - performTest("range-value-minimum-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "range-value-minimum-changed.html", + "range-value-minimum-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_rangeValueStepChanged() { - performTest("range-value-step-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "range-value-step-changed.html", "range-value-step-changed-expected-android.txt"); } @Test @@ -1154,14 +1206,14 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_removeChild() { - performTest("remove-child.html", EMPTY_EXPECTATIONS_FILE); + performTest("remove-child.html", "remove-child-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_removeHiddenAttribute() { - performTest("remove-hidden-attribute.html", EMPTY_EXPECTATIONS_FILE); + performTest("remove-hidden-attribute.html", "remove-hidden-attribute-expected-android.txt"); } @Test @@ -1228,14 +1280,16 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_selectSelectedAddRemove() { - performTest("select-selected-add-remove.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "select-selected-add-remove.html", + "select-selected-add-remove-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_styleChanged() { - performTest("style-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("style-changed.html", "style-changed-expected-android.txt"); } @Test @@ -1269,63 +1323,73 @@ @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_tabIndexAddedOnAriaHidden() { - performTest("tabindex-added-on-aria-hidden.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "tabindex-added-on-aria-hidden.html", + "tabindex-added-on-aria-hidden-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_tabIndexAddedOnPlainDiv() { - performTest("tabindex-added-on-plain-div.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "tabindex-added-on-plain-div.html", + "tabindex-added-on-plain-div-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_tabIndexRemoveOnAriaHidden() { - performTest("tabindex-removed-on-aria-hidden.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "tabindex-removed-on-aria-hidden.html", + "tabindex-removed-on-aria-hidden-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_tabIndexRemovedOnPlainDiv() { - performTest("tabindex-removed-on-plain-div.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "tabindex-removed-on-plain-div.html", + "tabindex-removed-on-plain-div-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/1190218") public void test_tbodyFocus() { - performTest("tbody-focus.html", EMPTY_EXPECTATIONS_FILE); + performTest("tbody-focus.html", "tbody-focus-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_textAlignChanged() { - performTest("text-align-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("text-align-changed.html", "text-align-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_textChangedContenteditable() { - performTest("text-changed-contenteditable.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "text-changed-contenteditable.html", + "text-changed-contenteditable-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_textChanged() { - performTest("text-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("text-changed.html", "text-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_textIndentChanged() { - performTest("text-indent-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("text-indent-changed.html", "text-indent-changed-expected-android.txt"); } @Test @@ -1357,34 +1421,36 @@ @SmallTest @DisabledTest(message = "https://crbug.com/1190218") public void test_tfootFocus() { - performTest("tfoot-focus.html", EMPTY_EXPECTATIONS_FILE); + performTest("tfoot-focus.html", "tfoot-focus-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/1190218") public void test_theadFocus() { - performTest("thead-focus.html", EMPTY_EXPECTATIONS_FILE); + performTest("thead-focus.html", "thead-focus-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_valudIsReadonlyChanged() { - performTest("value-is-readonly-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "value-is-readonly-changed.html", "value-is-readonly-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_ValueValueChanged() { - performTest("value-value-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest("value-value-changed.html", "value-value-changed-expected-android.txt"); } @Test @SmallTest @DisabledTest(message = "https://crbug.com/414363686") public void test_visibilityHiddenChanged() { - performTest("visibility-hidden-changed.html", EMPTY_EXPECTATIONS_FILE); + performTest( + "visibility-hidden-changed.html", "visibility-hidden-changed-expected-android.txt"); } }
diff --git a/content/renderer/service_worker/service_worker_subresource_loader.cc b/content/renderer/service_worker/service_worker_subresource_loader.cc index 476b1d9..b9761791 100644 --- a/content/renderer/service_worker/service_worker_subresource_loader.cc +++ b/content/renderer/service_worker/service_worker_subresource_loader.cc
@@ -438,7 +438,13 @@ return; case network::mojom::ServiceWorkerRouterSourceType:: kRaceNetworkAndCache: - // TODO(crbug.com/370844790): implement race network and cache + race_network_request_mode = kForced; + controller_connector_->CallCacheStorageMatch( + sources[0].race_network_and_cache_source->cache_source.cache_name, + blink::mojom::FetchAPIRequest::From(resource_request_), + base::BindOnce( + &ServiceWorkerSubresourceLoader::DidCacheStorageMatch, + weak_factory_.GetWeakPtr(), base::TimeTicks::Now())); break; } } @@ -1359,17 +1365,20 @@ void ServiceWorkerSubresourceLoader::SetCommitResponsibility( FetchResponseFrom fetch_response_from) { // Set the actual source type used in Static Routing API when - // `race-network-and-fetch` is used. Determine this by checking the - // commit responsibility. If it's not the service worker, the network - // has won. + // `race-network-and-fetch` or `race-network-and-race` is used. + // Determine this by checking the commit responsibility. If it's not the + // service worker, the network has won. // This check is conducted here since in the case of `knetwork`, it does // not call `DidDispatchFetchEvent`, where we set the `actual_source_type` // for the other sources, and the `response_head_` is already passed on. if (response_head_ && response_head_->service_worker_router_info && response_head_->service_worker_router_info->matched_source_type && - *response_head_->service_worker_router_info->matched_source_type == - network::mojom::ServiceWorkerRouterSourceType:: - kRaceNetworkAndFetchEvent && + (*response_head_->service_worker_router_info->matched_source_type == + network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndFetchEvent || + *response_head_->service_worker_router_info->matched_source_type == + network::mojom::ServiceWorkerRouterSourceType:: + kRaceNetworkAndCache) && fetch_response_from == FetchResponseFrom::kWithoutServiceWorker) { response_head_->service_worker_router_info->actual_source_type = network::mojom::ServiceWorkerRouterSourceType::kNetwork;
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist index 53cc522..3cc6954 100644 --- a/content/test/content_test_bundle_data.filelist +++ b/content/test/content_test_bundle_data.filelist
@@ -2147,10 +2147,10 @@ data/accessibility/css/reading-flow-out-of-flow-position.html data/accessibility/css/reading-flow-pseudo-elements-expected-blink.txt data/accessibility/css/reading-flow-pseudo-elements.html -data/accessibility/css/reading-flow-shadow-dom-slot-expected-blink.txt -data/accessibility/css/reading-flow-shadow-dom-slot.html data/accessibility/css/reading-flow-scroll-marker-expected-blink.txt data/accessibility/css/reading-flow-scroll-marker.html +data/accessibility/css/reading-flow-shadow-dom-slot-expected-blink.txt +data/accessibility/css/reading-flow-shadow-dom-slot.html data/accessibility/css/reading-flow.html data/accessibility/css/scroll-buttons-disabled-status-expected-blink.txt data/accessibility/css/scroll-buttons-disabled-status.html @@ -2218,6 +2218,7 @@ data/accessibility/display-locking/viewport-activation-expected-mac.txt data/accessibility/display-locking/viewport-activation-expected-win.txt data/accessibility/display-locking/viewport-activation.html +data/accessibility/event/add-alert-content-expected-android-exp.txt data/accessibility/event/add-alert-content-expected-android.txt data/accessibility/event/add-alert-content-expected-auralinux.txt data/accessibility/event/add-alert-content-expected-mac.txt @@ -2235,8 +2236,10 @@ data/accessibility/event/add-alert-with-role-change-expected-win.txt data/accessibility/event/add-alert-with-role-change.html data/accessibility/event/add-alert.html +data/accessibility/event/add-child-expected-android.txt data/accessibility/event/add-child-expected-auralinux.txt data/accessibility/event/add-child-expected-win.txt +data/accessibility/event/add-child-of-body-expected-android.txt data/accessibility/event/add-child-of-body-expected-win.txt data/accessibility/event/add-child-of-body.html data/accessibility/event/add-child.html @@ -2258,6 +2261,7 @@ data/accessibility/event/add-dialog-no-info-expected-win.txt data/accessibility/event/add-dialog-no-info.html data/accessibility/event/add-dialog.html +data/accessibility/event/add-hidden-attribute-expected-android.txt data/accessibility/event/add-hidden-attribute-expected-auralinux.txt data/accessibility/event/add-hidden-attribute-expected-win.txt data/accessibility/event/add-hidden-attribute-subtree-expected-android.txt @@ -2270,6 +2274,7 @@ data/accessibility/event/add-subtree-expected-uia-win.txt data/accessibility/event/add-subtree-expected-win.txt data/accessibility/event/add-subtree.html +data/accessibility/event/anonymous-block-children-changed-expected-android.txt data/accessibility/event/anonymous-block-children-changed-expected-auralinux.txt data/accessibility/event/anonymous-block-children-changed.html data/accessibility/event/aria-activedescendant-element-tree-changes-expected-auralinux.txt @@ -2278,14 +2283,18 @@ data/accessibility/event/aria-activedescendant-element-tree-changes.html data/accessibility/event/aria-activedescendant-id-and-tree-changes-expected-auralinux.txt data/accessibility/event/aria-activedescendant-id-and-tree-changes.html +data/accessibility/event/aria-atomic-changed-expected-android.txt data/accessibility/event/aria-atomic-changed-expected-uia-win.txt data/accessibility/event/aria-atomic-changed.html +data/accessibility/event/aria-atomic-changed2-expected-android.txt data/accessibility/event/aria-atomic-changed2-expected-uia-win.txt data/accessibility/event/aria-atomic-changed2.html +data/accessibility/event/aria-busy-changed-expected-android.txt data/accessibility/event/aria-busy-changed-expected-auralinux.txt data/accessibility/event/aria-busy-changed-expected-mac.txt data/accessibility/event/aria-busy-changed-expected-uia-win.txt data/accessibility/event/aria-busy-changed.html +data/accessibility/event/aria-button-expand-expected-android.txt data/accessibility/event/aria-button-expand-expected-auralinux.txt data/accessibility/event/aria-button-expand.html data/accessibility/event/aria-checked-changed-expected-android.txt @@ -2327,16 +2336,20 @@ data/accessibility/event/aria-combo-box-next-expected-uia-win.txt data/accessibility/event/aria-combo-box-next-expected-win.txt data/accessibility/event/aria-combo-box-next.html +data/accessibility/event/aria-combo-box-uneditable-expected-android.txt data/accessibility/event/aria-combo-box-uneditable-expected-mac.txt data/accessibility/event/aria-combo-box-uneditable-expected-win.txt data/accessibility/event/aria-combo-box-uneditable.html +data/accessibility/event/aria-controls-changed-expected-android.txt data/accessibility/event/aria-controls-changed-expected-uia-win.txt data/accessibility/event/aria-controls-changed.html +data/accessibility/event/aria-current-changed-expected-android.txt data/accessibility/event/aria-current-changed-expected-auralinux.txt data/accessibility/event/aria-current-changed-expected-mac.txt data/accessibility/event/aria-current-changed-expected-uia-win.txt data/accessibility/event/aria-current-changed-expected-win.txt data/accessibility/event/aria-current-changed.html +data/accessibility/event/aria-disabled-changed-expected-android.txt data/accessibility/event/aria-disabled-changed-expected-auralinux.txt data/accessibility/event/aria-disabled-changed-expected-mac.txt data/accessibility/event/aria-disabled-changed-expected-uia-win.txt @@ -2346,46 +2359,60 @@ data/accessibility/event/aria-expanded-and-collapsed-reparenting-expected-auralinux.txt data/accessibility/event/aria-expanded-and-collapsed-reparenting.html data/accessibility/event/aria-expanded-and-collapsed.html +data/accessibility/event/aria-flow-to-expected-android.txt data/accessibility/event/aria-flow-to-expected-uia-win.txt data/accessibility/event/aria-flow-to.html +data/accessibility/event/aria-haspopup-changed-expected-android.txt data/accessibility/event/aria-haspopup-changed-expected-uia-win.txt data/accessibility/event/aria-haspopup-changed.html +data/accessibility/event/aria-hidden-changed-expected-android.txt data/accessibility/event/aria-hidden-changed-expected-auralinux.txt data/accessibility/event/aria-hidden-changed-expected-uia-win.txt data/accessibility/event/aria-hidden-changed.html +data/accessibility/event/aria-hidden-descendants-already-ignored-expected-android.txt data/accessibility/event/aria-hidden-descendants-already-ignored-expected-auralinux.txt data/accessibility/event/aria-hidden-descendants-already-ignored-expected-uia-win.txt data/accessibility/event/aria-hidden-descendants-already-ignored-expected-win.txt data/accessibility/event/aria-hidden-descendants-already-ignored.html +data/accessibility/event/aria-hidden-descendants-expected-android.txt data/accessibility/event/aria-hidden-descendants-expected-uia-win.txt data/accessibility/event/aria-hidden-descendants-expected-win.txt data/accessibility/event/aria-hidden-descendants.html +data/accessibility/event/aria-hidden-single-descendant-display-none-expected-android.txt data/accessibility/event/aria-hidden-single-descendant-display-none-expected-auralinux.txt data/accessibility/event/aria-hidden-single-descendant-display-none-expected-uia-win.txt data/accessibility/event/aria-hidden-single-descendant-display-none-expected-win.txt data/accessibility/event/aria-hidden-single-descendant-display-none.html +data/accessibility/event/aria-hidden-single-descendant-expected-android.txt data/accessibility/event/aria-hidden-single-descendant-expected-uia-win.txt data/accessibility/event/aria-hidden-single-descendant-expected-win.txt +data/accessibility/event/aria-hidden-single-descendant-visibility-hidden-expected-android.txt data/accessibility/event/aria-hidden-single-descendant-visibility-hidden-expected-auralinux.txt data/accessibility/event/aria-hidden-single-descendant-visibility-hidden-expected-uia-win.txt data/accessibility/event/aria-hidden-single-descendant-visibility-hidden-expected-win.txt data/accessibility/event/aria-hidden-single-descendant-visibility-hidden.html data/accessibility/event/aria-hidden-single-descendant.html +data/accessibility/event/aria-level-changed-expected-android.txt data/accessibility/event/aria-level-changed-expected-uia-win.txt data/accessibility/event/aria-level-changed.html +data/accessibility/event/aria-live-changed-expected-android.txt data/accessibility/event/aria-live-changed-expected-auralinux.txt data/accessibility/event/aria-live-changed-expected-mac.txt data/accessibility/event/aria-live-changed-expected-uia-win.txt data/accessibility/event/aria-live-changed.html +data/accessibility/event/aria-menuitem-focus-expected-android.txt data/accessibility/event/aria-menuitem-focus-expected-auralinux.txt data/accessibility/event/aria-menuitem-focus.html +data/accessibility/event/aria-multiline-changed-expected-android.txt data/accessibility/event/aria-multiline-changed-expected-uia-win.txt data/accessibility/event/aria-multiline-changed.html +data/accessibility/event/aria-multiselectable-changed-expected-android.txt data/accessibility/event/aria-multiselectable-changed-expected-auralinux.txt data/accessibility/event/aria-multiselectable-changed-expected-mac.txt data/accessibility/event/aria-multiselectable-changed-expected-uia-win.txt data/accessibility/event/aria-multiselectable-changed-expected-win.txt data/accessibility/event/aria-multiselectable-changed.html +data/accessibility/event/aria-posinset-changed-expected-android.txt data/accessibility/event/aria-posinset-changed-expected-uia-win.txt data/accessibility/event/aria-posinset-changed.html data/accessibility/event/aria-pressed-changed-expected-android.txt @@ -2398,12 +2425,16 @@ data/accessibility/event/aria-pressed-changes-button-role-expected-uia-win.txt data/accessibility/event/aria-pressed-changes-button-role-expected-win.txt data/accessibility/event/aria-pressed-changes-button-role.html +data/accessibility/event/aria-readonly-changed-expected-android.txt data/accessibility/event/aria-readonly-changed-expected-uia-win.txt data/accessibility/event/aria-readonly-changed.html +data/accessibility/event/aria-relevant-changed-expected-android.txt data/accessibility/event/aria-relevant-changed-expected-uia-win.txt data/accessibility/event/aria-relevant-changed.html +data/accessibility/event/aria-relevant-changed2-expected-android.txt data/accessibility/event/aria-relevant-changed2-expected-uia-win.txt data/accessibility/event/aria-relevant-changed2.html +data/accessibility/event/aria-required-changed-expected-android.txt data/accessibility/event/aria-required-changed-expected-mac.txt data/accessibility/event/aria-required-changed-expected-uia-win.txt data/accessibility/event/aria-required-changed-expected-win.txt @@ -2411,12 +2442,14 @@ data/accessibility/event/aria-selected-changed-expected-android.txt data/accessibility/event/aria-selected-changed-expected-uia-win.txt data/accessibility/event/aria-selected-changed-expected-win.txt +data/accessibility/event/aria-selected-changed-new-subtree-expected-android.txt data/accessibility/event/aria-selected-changed-new-subtree-expected-auralinux.txt data/accessibility/event/aria-selected-changed-new-subtree-expected-mac.txt data/accessibility/event/aria-selected-changed-new-subtree-expected-uia-win.txt data/accessibility/event/aria-selected-changed-new-subtree-expected-win.txt data/accessibility/event/aria-selected-changed-new-subtree.html data/accessibility/event/aria-selected-changed.html +data/accessibility/event/aria-setsize-changed-expected-android.txt data/accessibility/event/aria-setsize-changed-expected-uia-win.txt data/accessibility/event/aria-setsize-changed.html data/accessibility/event/aria-slider-value-both-change-expected-android.txt @@ -2437,41 +2470,51 @@ data/accessibility/event/aria-slider-valuetext-change-expected-uia-win.txt data/accessibility/event/aria-slider-valuetext-change-expected-win.txt data/accessibility/event/aria-slider-valuetext-change.html +data/accessibility/event/aria-sort-changed-expected-android.txt data/accessibility/event/aria-sort-changed-expected-auralinux.txt data/accessibility/event/aria-sort-changed-expected-uia-win.txt data/accessibility/event/aria-sort-changed-expected-win.txt data/accessibility/event/aria-sort-changed.html +data/accessibility/event/aria-spinbutton-value-both-change-expected-android.txt data/accessibility/event/aria-spinbutton-value-both-change-expected-auralinux.txt data/accessibility/event/aria-spinbutton-value-both-change-expected-mac.txt data/accessibility/event/aria-spinbutton-value-both-change-expected-uia-win.txt data/accessibility/event/aria-spinbutton-value-both-change-expected-win.txt data/accessibility/event/aria-spinbutton-value-both-change.html +data/accessibility/event/aria-spinbutton-value-change-expected-android.txt data/accessibility/event/aria-spinbutton-value-change-expected-auralinux.txt data/accessibility/event/aria-spinbutton-value-change-expected-mac.txt data/accessibility/event/aria-spinbutton-value-change-expected-uia-win.txt data/accessibility/event/aria-spinbutton-value-change-expected-win.txt data/accessibility/event/aria-spinbutton-value-change.html +data/accessibility/event/aria-spinbutton-valuetext-change-expected-android.txt data/accessibility/event/aria-spinbutton-valuetext-change-expected-auralinux.txt data/accessibility/event/aria-spinbutton-valuetext-change-expected-mac.txt data/accessibility/event/aria-spinbutton-valuetext-change-expected-uia-win.txt data/accessibility/event/aria-spinbutton-valuetext-change-expected-win.txt data/accessibility/event/aria-spinbutton-valuetext-change.html +data/accessibility/event/aria-textbox-children-change-expected-android.txt data/accessibility/event/aria-textbox-children-change-expected-auralinux.txt data/accessibility/event/aria-textbox-children-change-expected-mac.txt data/accessibility/event/aria-textbox-children-change-expected-win.txt data/accessibility/event/aria-textbox-children-change.html +data/accessibility/event/aria-textbox-editability-changes-expected-android.txt data/accessibility/event/aria-textbox-editability-changes-expected-auralinux.txt data/accessibility/event/aria-textbox-editability-changes-expected-mac.txt data/accessibility/event/aria-textbox-editability-changes-expected-win.txt data/accessibility/event/aria-textbox-editability-changes.html +data/accessibility/event/aria-textbox-with-focusable-children-expected-android.txt data/accessibility/event/aria-textbox-with-focusable-children-expected-auralinux.txt data/accessibility/event/aria-textbox-with-focusable-children-expected-mac.txt data/accessibility/event/aria-textbox-with-focusable-children-expected-win.txt data/accessibility/event/aria-textbox-with-focusable-children.html +data/accessibility/event/aria-tree-collapse-expected-android.txt data/accessibility/event/aria-tree-collapse-expected-mac.txt data/accessibility/event/aria-tree-collapse.html +data/accessibility/event/aria-tree-expand-expected-android.txt data/accessibility/event/aria-tree-expand-expected-mac.txt data/accessibility/event/aria-tree-expand.html +data/accessibility/event/aria-treeitem-focus-expected-android.txt data/accessibility/event/aria-treeitem-focus-expected-auralinux.txt data/accessibility/event/aria-treeitem-focus-expected-mac.txt data/accessibility/event/aria-treeitem-focus-expected-uia-win.txt @@ -2482,6 +2525,7 @@ data/accessibility/event/button-click-expected-auralinux.txt data/accessibility/event/button-click-expected-uia-win.txt data/accessibility/event/button-click.html +data/accessibility/event/button-remove-children-expected-android.txt data/accessibility/event/button-remove-children-expected-auralinux.txt data/accessibility/event/button-remove-children-expected-uia-win.txt data/accessibility/event/button-remove-children-expected-win.txt @@ -2509,48 +2553,60 @@ data/accessibility/event/carousel-with-tabs-expected-android.txt data/accessibility/event/carousel-with-tabs-expected-auralinux.txt data/accessibility/event/carousel-with-tabs.html +data/accessibility/event/checkbox-validity-expected-android.txt data/accessibility/event/checkbox-validity-expected-auralinux.txt data/accessibility/event/checkbox-validity.html +data/accessibility/event/checked-mixed-changed-expected-android.txt data/accessibility/event/checked-mixed-changed-expected-auralinux.txt data/accessibility/event/checked-mixed-changed-expected-mac.txt data/accessibility/event/checked-mixed-changed-expected-uia-win.txt data/accessibility/event/checked-mixed-changed-expected-win.txt data/accessibility/event/checked-mixed-changed.html +data/accessibility/event/checked-state-changed-expected-android.txt data/accessibility/event/checked-state-changed-expected-auralinux.txt data/accessibility/event/checked-state-changed-expected-mac.txt data/accessibility/event/checked-state-changed-expected-uia-win.txt data/accessibility/event/checked-state-changed-expected-win.txt data/accessibility/event/checked-state-changed.html +data/accessibility/event/children-changed-only-on-ancestor-expected-android.txt data/accessibility/event/children-changed-only-on-ancestor-expected-auralinux.txt data/accessibility/event/children-changed-only-on-ancestor-expected-uia-win.txt data/accessibility/event/children-changed-only-on-ancestor-expected-win.txt data/accessibility/event/children-changed-only-on-ancestor.html +data/accessibility/event/css-display-descendants-expected-android.txt data/accessibility/event/css-display-descendants-expected-win.txt data/accessibility/event/css-display-descendants.html data/accessibility/event/css-display-expected-android.txt data/accessibility/event/css-display-expected-auralinux.txt data/accessibility/event/css-display-expected-win.txt data/accessibility/event/css-display.html +data/accessibility/event/css-flex-text-update-expected-android.txt data/accessibility/event/css-flex-text-update-expected-auralinux.txt data/accessibility/event/css-flex-text-update-expected-mac.txt data/accessibility/event/css-flex-text-update-expected-uia-win.txt data/accessibility/event/css-flex-text-update-expected-win.txt data/accessibility/event/css-flex-text-update.html +data/accessibility/event/css-visibility-collapse-expected-android.txt data/accessibility/event/css-visibility-collapse-expected-win.txt data/accessibility/event/css-visibility-collapse.html +data/accessibility/event/css-visibility-descendants-expected-android.txt data/accessibility/event/css-visibility-descendants-expected-win.txt data/accessibility/event/css-visibility-descendants.html +data/accessibility/event/css-visibility-expected-android.txt data/accessibility/event/css-visibility-expected-win.txt data/accessibility/event/css-visibility.html data/accessibility/event/delete-subtree-expected-android.txt data/accessibility/event/delete-subtree-expected-auralinux.txt data/accessibility/event/delete-subtree.html +data/accessibility/event/description-change-expected-android.txt data/accessibility/event/description-change-expected-auralinux.txt data/accessibility/event/description-change-expected-uia-win.txt data/accessibility/event/description-change-expected-win.txt +data/accessibility/event/description-change-indirect-expected-android.txt data/accessibility/event/description-change-indirect-expected-uia-win.txt data/accessibility/event/description-change-indirect-expected-win.txt data/accessibility/event/description-change-indirect.html +data/accessibility/event/description-change-no-relation-expected-android.txt data/accessibility/event/description-change-no-relation-expected-auralinux.txt data/accessibility/event/description-change-no-relation-expected-uia-win.txt data/accessibility/event/description-change-no-relation-expected-win.txt @@ -2560,25 +2616,31 @@ data/accessibility/event/description-changed-pane-title.html data/accessibility/event/description-changed-subtree-expected-android.txt data/accessibility/event/description-changed-subtree.html +data/accessibility/event/disabled-state-changed-expected-android.txt data/accessibility/event/disabled-state-changed-expected-auralinux.txt data/accessibility/event/disabled-state-changed-expected-win.txt data/accessibility/event/disabled-state-changed.html +data/accessibility/event/document-title-change-expected-android.txt data/accessibility/event/document-title-change.html data/accessibility/event/document-title-changed-expected-auralinux.txt +data/accessibility/event/expanded-changed-expected-android.txt data/accessibility/event/expanded-changed-expected-auralinux.txt data/accessibility/event/expanded-changed-expected-mac.txt data/accessibility/event/expanded-changed-expected-uia-win.txt data/accessibility/event/expanded-changed.html +data/accessibility/event/focus-listbox-expected-android.txt data/accessibility/event/focus-listbox-expected-auralinux.txt data/accessibility/event/focus-listbox-expected-mac.txt data/accessibility/event/focus-listbox-expected-uia-win.txt data/accessibility/event/focus-listbox-expected-win.txt +data/accessibility/event/focus-listbox-multiselect-expected-android.txt data/accessibility/event/focus-listbox-multiselect-expected-auralinux.txt data/accessibility/event/focus-listbox-multiselect-expected-mac.txt data/accessibility/event/focus-listbox-multiselect-expected-uia-win.txt data/accessibility/event/focus-listbox-multiselect-expected-win.txt data/accessibility/event/focus-listbox-multiselect.html data/accessibility/event/focus-listbox.html +data/accessibility/event/form-disabled-changed-expected-android.txt data/accessibility/event/form-disabled-changed-expected-mac.txt data/accessibility/event/form-disabled-changed-expected-win.txt data/accessibility/event/form-disabled-changed.html @@ -2587,14 +2649,17 @@ data/accessibility/event/form-required-changed-expected-uia-win.txt data/accessibility/event/form-required-changed-expected-win.txt data/accessibility/event/form-required-changed.html +data/accessibility/event/iframe-src-changed-expected-android.txt data/accessibility/event/iframe-src-changed-expected-auralinux.txt data/accessibility/event/iframe-src-changed.html +data/accessibility/event/immediate-refresh-expected-android.txt data/accessibility/event/immediate-refresh-expected-auralinux.txt data/accessibility/event/immediate-refresh.html data/accessibility/event/individual-nodes-become-ignored-but-included-expected-auralinux.txt data/accessibility/event/individual-nodes-become-ignored-but-included.html data/accessibility/event/individual-nodes-become-ignored-expected-auralinux.txt data/accessibility/event/individual-nodes-become-ignored.html +data/accessibility/event/inner-html-change-expected-android.txt data/accessibility/event/inner-html-change-expected-uia-win.txt data/accessibility/event/inner-html-change-expected-win.txt data/accessibility/event/inner-html-change.html @@ -2604,40 +2669,48 @@ data/accessibility/event/input-combobox-dialog.html data/accessibility/event/input-combobox-expected-android.txt data/accessibility/event/input-combobox.html +data/accessibility/event/input-type-text-value-changed-expected-android.txt data/accessibility/event/input-type-text-value-changed-expected-mac.txt data/accessibility/event/input-type-text-value-changed-expected-uia-win.txt data/accessibility/event/input-type-text-value-changed-expected-win.txt data/accessibility/event/input-type-text-value-changed.html +data/accessibility/event/listbox-focus-expected-android.txt data/accessibility/event/listbox-focus-expected-auralinux.txt data/accessibility/event/listbox-focus-expected-mac.txt data/accessibility/event/listbox-focus-expected-uia-win.txt data/accessibility/event/listbox-focus-expected-win.txt data/accessibility/event/listbox-focus.html +data/accessibility/event/listbox-next-expected-android.txt data/accessibility/event/listbox-next-expected-auralinux.txt data/accessibility/event/listbox-next-expected-mac.txt data/accessibility/event/listbox-next-expected-uia-win.txt data/accessibility/event/listbox-next-expected-win.txt data/accessibility/event/listbox-next.html +data/accessibility/event/live-region-add-expected-android-exp.txt data/accessibility/event/live-region-add-expected-android.txt data/accessibility/event/live-region-add-expected-auralinux.txt data/accessibility/event/live-region-add-expected-mac.txt data/accessibility/event/live-region-add-expected-uia-win.txt data/accessibility/event/live-region-add-expected-win.txt +data/accessibility/event/live-region-add-live-attribute-expected-android.txt data/accessibility/event/live-region-add-live-attribute-expected-auralinux.txt data/accessibility/event/live-region-add-live-attribute-expected-mac.txt data/accessibility/event/live-region-add-live-attribute-expected-uia-win.txt data/accessibility/event/live-region-add-live-attribute.html data/accessibility/event/live-region-add.html +data/accessibility/event/live-region-change-expected-android-exp.txt data/accessibility/event/live-region-change-expected-android.txt data/accessibility/event/live-region-change-expected-auralinux.txt data/accessibility/event/live-region-change-expected-mac.txt data/accessibility/event/live-region-change-expected-uia-win.txt data/accessibility/event/live-region-change-expected-win.txt +data/accessibility/event/live-region-change-innerhtml-expected-android-exp.txt data/accessibility/event/live-region-change-innerhtml-expected-android.txt data/accessibility/event/live-region-change-innerhtml-expected-auralinux.txt data/accessibility/event/live-region-change-innerhtml-expected-mac.txt data/accessibility/event/live-region-change-innerhtml-expected-win.txt data/accessibility/event/live-region-change-innerhtml.html +data/accessibility/event/live-region-change-innertext-expected-android-exp.txt data/accessibility/event/live-region-change-innertext-expected-android.txt data/accessibility/event/live-region-change-innertext-expected-auralinux.txt data/accessibility/event/live-region-change-innertext-expected-mac.txt @@ -2646,6 +2719,7 @@ data/accessibility/event/live-region-change-on-freshly-unignored-node-expected-uia-win.txt data/accessibility/event/live-region-change-on-freshly-unignored-node.html data/accessibility/event/live-region-change.html +data/accessibility/event/live-region-create-expected-android.txt data/accessibility/event/live-region-create-expected-auralinux.txt data/accessibility/event/live-region-create-expected-mac.txt data/accessibility/event/live-region-create-expected-uia-win.txt @@ -2668,24 +2742,29 @@ data/accessibility/event/live-region-off-expected-uia-win.txt data/accessibility/event/live-region-off-expected-win.txt data/accessibility/event/live-region-off.html +data/accessibility/event/live-region-remove-expected-android.txt data/accessibility/event/live-region-remove-expected-auralinux.txt data/accessibility/event/live-region-remove-expected-mac.txt data/accessibility/event/live-region-remove-expected-win.txt data/accessibility/event/live-region-remove.html +data/accessibility/event/menu-opened-closed-expected-android.txt data/accessibility/event/menu-opened-closed-expected-auralinux.txt data/accessibility/event/menu-opened-closed-expected-mac.txt data/accessibility/event/menu-opened-closed-expected-uia-win.txt data/accessibility/event/menu-opened-closed-expected-win.txt data/accessibility/event/menu-opened-closed.html +data/accessibility/event/menubar-show-hide-menus-expected-android.txt data/accessibility/event/menubar-show-hide-menus-expected-auralinux.txt data/accessibility/event/menubar-show-hide-menus-expected-mac.txt data/accessibility/event/menubar-show-hide-menus-expected-uia-win.txt data/accessibility/event/menubar-show-hide-menus-expected-win.txt data/accessibility/event/menubar-show-hide-menus.html +data/accessibility/event/menulist-collapse-expected-android.txt data/accessibility/event/menulist-collapse-expected-auralinux.txt data/accessibility/event/menulist-collapse-expected-mac.txt data/accessibility/event/menulist-collapse-expected-uia-win.txt data/accessibility/event/menulist-collapse-expected-win.txt +data/accessibility/event/menulist-collapse-next-expected-android.txt data/accessibility/event/menulist-collapse-next-expected-auralinux.txt data/accessibility/event/menulist-collapse-next-expected-mac.txt data/accessibility/event/menulist-collapse-next-expected-uia-win.txt @@ -2704,32 +2783,39 @@ data/accessibility/event/menulist-custom-next-expected-mac.txt data/accessibility/event/menulist-custom-next-expected-win.txt data/accessibility/event/menulist-custom-next.html +data/accessibility/event/menulist-expand-expected-android.txt data/accessibility/event/menulist-expand-expected-auralinux.txt data/accessibility/event/menulist-expand-expected-mac.txt data/accessibility/event/menulist-expand-expected-win.txt data/accessibility/event/menulist-expand.html +data/accessibility/event/menulist-focus-expected-android.txt data/accessibility/event/menulist-focus-expected-auralinux.txt data/accessibility/event/menulist-focus-expected-mac.txt data/accessibility/event/menulist-focus-expected-uia-win.txt data/accessibility/event/menulist-focus-expected-win.txt data/accessibility/event/menulist-focus.html +data/accessibility/event/menulist-next-expected-android.txt data/accessibility/event/menulist-next-expected-auralinux.txt data/accessibility/event/menulist-next-expected-mac.txt data/accessibility/event/menulist-next-expected-win.txt data/accessibility/event/menulist-next.html data/accessibility/event/menulist-with-optgroup-next-expected-auralinux.txt data/accessibility/event/menulist-with-optgroup-next.html +data/accessibility/event/multiple-aria-properties-changed-expected-android.txt data/accessibility/event/multiple-aria-properties-changed-expected-uia-win.txt data/accessibility/event/multiple-aria-properties-changed.html +data/accessibility/event/name-change-expected-android.txt data/accessibility/event/name-change-expected-auralinux.txt data/accessibility/event/name-change-expected-mac.txt data/accessibility/event/name-change-expected-uia-win.txt data/accessibility/event/name-change-expected-win.txt +data/accessibility/event/name-change-indirect-expected-android.txt data/accessibility/event/name-change-indirect-expected-mac.txt data/accessibility/event/name-change-indirect-expected-uia-win.txt data/accessibility/event/name-change-indirect-expected-win.txt data/accessibility/event/name-change-indirect.html data/accessibility/event/name-change.html +data/accessibility/event/navigation-api-expected-android.txt data/accessibility/event/navigation-api-expected-auralinux.txt data/accessibility/event/navigation-api-expected-win.txt data/accessibility/event/navigation-api.html @@ -2741,14 +2827,18 @@ data/accessibility/event/pressed-state-changed-expected-mac.txt data/accessibility/event/pressed-state-changed-expected-win.txt data/accessibility/event/pressed-state-changed.html +data/accessibility/event/range-value-is-readonly-changed-expected-android.txt data/accessibility/event/range-value-is-readonly-changed-expected-auralinux.txt data/accessibility/event/range-value-is-readonly-changed-expected-uia-win.txt data/accessibility/event/range-value-is-readonly-changed-expected-win.txt data/accessibility/event/range-value-is-readonly-changed.html +data/accessibility/event/range-value-maximum-changed-expected-android.txt data/accessibility/event/range-value-maximum-changed-expected-uia-win.txt data/accessibility/event/range-value-maximum-changed.html +data/accessibility/event/range-value-minimum-changed-expected-android.txt data/accessibility/event/range-value-minimum-changed-expected-uia-win.txt data/accessibility/event/range-value-minimum-changed.html +data/accessibility/event/range-value-step-changed-expected-android.txt data/accessibility/event/range-value-step-changed-expected-uia-win.txt data/accessibility/event/range-value-step-changed-expected-win.txt data/accessibility/event/range-value-step-changed.html @@ -2757,10 +2847,12 @@ data/accessibility/event/range-value-value-changed-expected-uia-win.txt data/accessibility/event/range-value-value-changed-expected-win.txt data/accessibility/event/range-value-value-changed.html +data/accessibility/event/remove-child-expected-android.txt data/accessibility/event/remove-child-expected-auralinux.txt data/accessibility/event/remove-child-expected-uia-win.txt data/accessibility/event/remove-child-expected-win.txt data/accessibility/event/remove-child.html +data/accessibility/event/remove-hidden-attribute-expected-android.txt data/accessibility/event/remove-hidden-attribute-expected-auralinux.txt data/accessibility/event/remove-hidden-attribute-expected-win.txt data/accessibility/event/remove-hidden-attribute-subtree-expected-android.txt @@ -2804,11 +2896,13 @@ data/accessibility/event/scroll-vertical-scroll-percent-change-expected-uia-win.txt data/accessibility/event/scroll-vertical-scroll-percent-change-expected-win.txt data/accessibility/event/scroll-vertical-scroll-percent-change.html +data/accessibility/event/select-selected-add-remove-expected-android.txt data/accessibility/event/select-selected-add-remove-expected-auralinux.txt data/accessibility/event/select-selected-add-remove-expected-mac.txt data/accessibility/event/select-selected-add-remove-expected-uia-win.txt data/accessibility/event/select-selected-add-remove-expected-win.txt data/accessibility/event/select-selected-add-remove.html +data/accessibility/event/style-changed-expected-android.txt data/accessibility/event/style-changed-expected-auralinux.txt data/accessibility/event/style-changed-expected-uia-win.txt data/accessibility/event/style-changed-expected-win.txt @@ -2829,33 +2923,42 @@ data/accessibility/event/subtree-reparented-via-aria-owns-expected-mac.txt data/accessibility/event/subtree-reparented-via-aria-owns-expected-win.txt data/accessibility/event/subtree-reparented-via-aria-owns.html +data/accessibility/event/tabindex-added-on-aria-hidden-expected-android.txt data/accessibility/event/tabindex-added-on-aria-hidden-expected-auralinux.txt data/accessibility/event/tabindex-added-on-aria-hidden-expected-win.txt data/accessibility/event/tabindex-added-on-aria-hidden.html +data/accessibility/event/tabindex-added-on-plain-div-expected-android.txt data/accessibility/event/tabindex-added-on-plain-div-expected-auralinux.txt data/accessibility/event/tabindex-added-on-plain-div-expected-win.txt data/accessibility/event/tabindex-added-on-plain-div.html +data/accessibility/event/tabindex-removed-on-aria-hidden-expected-android.txt data/accessibility/event/tabindex-removed-on-aria-hidden-expected-win.txt data/accessibility/event/tabindex-removed-on-aria-hidden.html +data/accessibility/event/tabindex-removed-on-plain-div-expected-android.txt data/accessibility/event/tabindex-removed-on-plain-div-expected-auralinux.txt data/accessibility/event/tabindex-removed-on-plain-div-expected-win.txt data/accessibility/event/tabindex-removed-on-plain-div.html +data/accessibility/event/tbody-focus-expected-android.txt data/accessibility/event/tbody-focus-expected-auralinux.txt data/accessibility/event/tbody-focus-expected-mac.txt data/accessibility/event/tbody-focus-expected-uia-win.txt data/accessibility/event/tbody-focus-expected-win.txt data/accessibility/event/tbody-focus.html +data/accessibility/event/text-align-changed-expected-android.txt data/accessibility/event/text-align-changed-expected-auralinux.txt data/accessibility/event/text-align-changed-expected-win.txt data/accessibility/event/text-align-changed.html +data/accessibility/event/text-changed-contenteditable-expected-android.txt data/accessibility/event/text-changed-contenteditable-expected-auralinux.txt data/accessibility/event/text-changed-contenteditable-expected-uia-win.txt data/accessibility/event/text-changed-contenteditable-expected-win.txt data/accessibility/event/text-changed-contenteditable.html +data/accessibility/event/text-changed-expected-android.txt data/accessibility/event/text-changed-expected-auralinux.txt data/accessibility/event/text-changed-expected-uia-win.txt data/accessibility/event/text-changed-expected-win.txt data/accessibility/event/text-changed.html +data/accessibility/event/text-indent-changed-expected-android.txt data/accessibility/event/text-indent-changed-expected-auralinux.txt data/accessibility/event/text-indent-changed-expected-win.txt data/accessibility/event/text-indent-changed.html @@ -2870,23 +2973,28 @@ data/accessibility/event/text-selection-inside-video-expected-android.txt data/accessibility/event/text-selection-inside-video-expected-auralinux.txt data/accessibility/event/text-selection-inside-video.html +data/accessibility/event/tfoot-focus-expected-android.txt data/accessibility/event/tfoot-focus-expected-auralinux.txt data/accessibility/event/tfoot-focus-expected-mac.txt data/accessibility/event/tfoot-focus-expected-uia-win.txt data/accessibility/event/tfoot-focus-expected-win.txt data/accessibility/event/tfoot-focus.html +data/accessibility/event/thead-focus-expected-android.txt data/accessibility/event/thead-focus-expected-auralinux.txt data/accessibility/event/thead-focus-expected-mac.txt data/accessibility/event/thead-focus-expected-uia-win.txt data/accessibility/event/thead-focus-expected-win.txt data/accessibility/event/thead-focus.html +data/accessibility/event/value-is-readonly-changed-expected-android.txt data/accessibility/event/value-is-readonly-changed-expected-auralinux.txt data/accessibility/event/value-is-readonly-changed-expected-uia-win.txt data/accessibility/event/value-is-readonly-changed-expected-win.txt data/accessibility/event/value-is-readonly-changed.html +data/accessibility/event/value-value-changed-expected-android.txt data/accessibility/event/value-value-changed-expected-uia-win.txt data/accessibility/event/value-value-changed-expected-win.txt data/accessibility/event/value-value-changed.html +data/accessibility/event/visibility-hidden-changed-expected-android.txt data/accessibility/event/visibility-hidden-changed-expected-auralinux.txt data/accessibility/event/visibility-hidden-changed-expected-uia-win.txt data/accessibility/event/visibility-hidden-changed.html
diff --git a/content/test/data/accessibility/event/add-alert-content-expected-android-exp.txt b/content/test/data/accessibility/event/add-alert-content-expected-android-exp.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/add-alert-content-expected-android-exp.txt
diff --git a/content/test/data/accessibility/event/add-child-expected-android.txt b/content/test/data/accessibility/event/add-child-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/add-child-expected-android.txt
diff --git a/content/test/data/accessibility/event/add-child-of-body-expected-android.txt b/content/test/data/accessibility/event/add-child-of-body-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/add-child-of-body-expected-android.txt
diff --git a/content/test/data/accessibility/event/add-hidden-attribute-expected-android.txt b/content/test/data/accessibility/event/add-hidden-attribute-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/add-hidden-attribute-expected-android.txt
diff --git a/content/test/data/accessibility/event/anonymous-block-children-changed-expected-android.txt b/content/test/data/accessibility/event/anonymous-block-children-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/anonymous-block-children-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-atomic-changed-expected-android.txt b/content/test/data/accessibility/event/aria-atomic-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-atomic-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-atomic-changed2-expected-android.txt b/content/test/data/accessibility/event/aria-atomic-changed2-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-atomic-changed2-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-busy-changed-expected-android.txt b/content/test/data/accessibility/event/aria-busy-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-busy-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-button-expand-expected-android.txt b/content/test/data/accessibility/event/aria-button-expand-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-button-expand-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-combo-box-uneditable-expected-android.txt b/content/test/data/accessibility/event/aria-combo-box-uneditable-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-combo-box-uneditable-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-controls-changed-expected-android.txt b/content/test/data/accessibility/event/aria-controls-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-controls-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-current-changed-expected-android.txt b/content/test/data/accessibility/event/aria-current-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-current-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-disabled-changed-expected-android.txt b/content/test/data/accessibility/event/aria-disabled-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-disabled-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-flow-to-expected-android.txt b/content/test/data/accessibility/event/aria-flow-to-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-flow-to-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-haspopup-changed-expected-android.txt b/content/test/data/accessibility/event/aria-haspopup-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-haspopup-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-hidden-changed-expected-android.txt b/content/test/data/accessibility/event/aria-hidden-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-hidden-descendants-already-ignored-expected-android.txt b/content/test/data/accessibility/event/aria-hidden-descendants-already-ignored-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-descendants-already-ignored-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-hidden-descendants-expected-android.txt b/content/test/data/accessibility/event/aria-hidden-descendants-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-descendants-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-hidden-single-descendant-display-none-expected-android.txt b/content/test/data/accessibility/event/aria-hidden-single-descendant-display-none-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-single-descendant-display-none-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-hidden-single-descendant-expected-android.txt b/content/test/data/accessibility/event/aria-hidden-single-descendant-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-single-descendant-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-hidden-single-descendant-visibility-hidden-expected-android.txt b/content/test/data/accessibility/event/aria-hidden-single-descendant-visibility-hidden-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-hidden-single-descendant-visibility-hidden-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-level-changed-expected-android.txt b/content/test/data/accessibility/event/aria-level-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-level-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-live-changed-expected-android.txt b/content/test/data/accessibility/event/aria-live-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-live-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-menuitem-focus-expected-android.txt b/content/test/data/accessibility/event/aria-menuitem-focus-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-menuitem-focus-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-multiline-changed-expected-android.txt b/content/test/data/accessibility/event/aria-multiline-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-multiline-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-multiselectable-changed-expected-android.txt b/content/test/data/accessibility/event/aria-multiselectable-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-multiselectable-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-posinset-changed-expected-android.txt b/content/test/data/accessibility/event/aria-posinset-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-posinset-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-readonly-changed-expected-android.txt b/content/test/data/accessibility/event/aria-readonly-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-readonly-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-relevant-changed-expected-android.txt b/content/test/data/accessibility/event/aria-relevant-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-relevant-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-relevant-changed2-expected-android.txt b/content/test/data/accessibility/event/aria-relevant-changed2-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-relevant-changed2-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-required-changed-expected-android.txt b/content/test/data/accessibility/event/aria-required-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-required-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-selected-changed-new-subtree-expected-android.txt b/content/test/data/accessibility/event/aria-selected-changed-new-subtree-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-selected-changed-new-subtree-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-setsize-changed-expected-android.txt b/content/test/data/accessibility/event/aria-setsize-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-setsize-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-sort-changed-expected-android.txt b/content/test/data/accessibility/event/aria-sort-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-sort-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-spinbutton-value-both-change-expected-android.txt b/content/test/data/accessibility/event/aria-spinbutton-value-both-change-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-spinbutton-value-both-change-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-spinbutton-value-change-expected-android.txt b/content/test/data/accessibility/event/aria-spinbutton-value-change-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-spinbutton-value-change-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-spinbutton-valuetext-change-expected-android.txt b/content/test/data/accessibility/event/aria-spinbutton-valuetext-change-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-spinbutton-valuetext-change-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-textbox-children-change-expected-android.txt b/content/test/data/accessibility/event/aria-textbox-children-change-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-textbox-children-change-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-textbox-editability-changes-expected-android.txt b/content/test/data/accessibility/event/aria-textbox-editability-changes-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-textbox-editability-changes-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-textbox-with-focusable-children-expected-android.txt b/content/test/data/accessibility/event/aria-textbox-with-focusable-children-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-textbox-with-focusable-children-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-tree-collapse-expected-android.txt b/content/test/data/accessibility/event/aria-tree-collapse-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-tree-collapse-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-tree-expand-expected-android.txt b/content/test/data/accessibility/event/aria-tree-expand-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-tree-expand-expected-android.txt
diff --git a/content/test/data/accessibility/event/aria-treeitem-focus-expected-android.txt b/content/test/data/accessibility/event/aria-treeitem-focus-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/aria-treeitem-focus-expected-android.txt
diff --git a/content/test/data/accessibility/event/button-remove-children-expected-android.txt b/content/test/data/accessibility/event/button-remove-children-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/button-remove-children-expected-android.txt
diff --git a/content/test/data/accessibility/event/checkbox-validity-expected-android.txt b/content/test/data/accessibility/event/checkbox-validity-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/checkbox-validity-expected-android.txt
diff --git a/content/test/data/accessibility/event/checked-mixed-changed-expected-android.txt b/content/test/data/accessibility/event/checked-mixed-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/checked-mixed-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/checked-state-changed-expected-android.txt b/content/test/data/accessibility/event/checked-state-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/checked-state-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/children-changed-only-on-ancestor-expected-android.txt b/content/test/data/accessibility/event/children-changed-only-on-ancestor-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/children-changed-only-on-ancestor-expected-android.txt
diff --git a/content/test/data/accessibility/event/css-display-descendants-expected-android.txt b/content/test/data/accessibility/event/css-display-descendants-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/css-display-descendants-expected-android.txt
diff --git a/content/test/data/accessibility/event/css-flex-text-update-expected-android.txt b/content/test/data/accessibility/event/css-flex-text-update-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/css-flex-text-update-expected-android.txt
diff --git a/content/test/data/accessibility/event/css-visibility-collapse-expected-android.txt b/content/test/data/accessibility/event/css-visibility-collapse-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/css-visibility-collapse-expected-android.txt
diff --git a/content/test/data/accessibility/event/css-visibility-descendants-expected-android.txt b/content/test/data/accessibility/event/css-visibility-descendants-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/css-visibility-descendants-expected-android.txt
diff --git a/content/test/data/accessibility/event/css-visibility-expected-android.txt b/content/test/data/accessibility/event/css-visibility-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/css-visibility-expected-android.txt
diff --git a/content/test/data/accessibility/event/description-change-expected-android.txt b/content/test/data/accessibility/event/description-change-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/description-change-expected-android.txt
diff --git a/content/test/data/accessibility/event/description-change-indirect-expected-android.txt b/content/test/data/accessibility/event/description-change-indirect-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/description-change-indirect-expected-android.txt
diff --git a/content/test/data/accessibility/event/description-change-no-relation-expected-android.txt b/content/test/data/accessibility/event/description-change-no-relation-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/description-change-no-relation-expected-android.txt
diff --git a/content/test/data/accessibility/event/disabled-state-changed-expected-android.txt b/content/test/data/accessibility/event/disabled-state-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/disabled-state-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/document-title-change-expected-android.txt b/content/test/data/accessibility/event/document-title-change-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/document-title-change-expected-android.txt
diff --git a/content/test/data/accessibility/event/expanded-changed-expected-android.txt b/content/test/data/accessibility/event/expanded-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/expanded-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/focus-listbox-expected-android.txt b/content/test/data/accessibility/event/focus-listbox-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/focus-listbox-expected-android.txt
diff --git a/content/test/data/accessibility/event/focus-listbox-multiselect-expected-android.txt b/content/test/data/accessibility/event/focus-listbox-multiselect-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/focus-listbox-multiselect-expected-android.txt
diff --git a/content/test/data/accessibility/event/form-disabled-changed-expected-android.txt b/content/test/data/accessibility/event/form-disabled-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/form-disabled-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/iframe-src-changed-expected-android.txt b/content/test/data/accessibility/event/iframe-src-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/iframe-src-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/immediate-refresh-expected-android.txt b/content/test/data/accessibility/event/immediate-refresh-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/immediate-refresh-expected-android.txt
diff --git a/content/test/data/accessibility/event/inner-html-change-expected-android.txt b/content/test/data/accessibility/event/inner-html-change-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/inner-html-change-expected-android.txt
diff --git a/content/test/data/accessibility/event/input-type-text-value-changed-expected-android.txt b/content/test/data/accessibility/event/input-type-text-value-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/input-type-text-value-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/listbox-focus-expected-android.txt b/content/test/data/accessibility/event/listbox-focus-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/listbox-focus-expected-android.txt
diff --git a/content/test/data/accessibility/event/listbox-next-expected-android.txt b/content/test/data/accessibility/event/listbox-next-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/listbox-next-expected-android.txt
diff --git a/content/test/data/accessibility/event/live-region-add-expected-android-exp.txt b/content/test/data/accessibility/event/live-region-add-expected-android-exp.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/live-region-add-expected-android-exp.txt
diff --git a/content/test/data/accessibility/event/live-region-add-live-attribute-expected-android.txt b/content/test/data/accessibility/event/live-region-add-live-attribute-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/live-region-add-live-attribute-expected-android.txt
diff --git a/content/test/data/accessibility/event/live-region-change-expected-android-exp.txt b/content/test/data/accessibility/event/live-region-change-expected-android-exp.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/live-region-change-expected-android-exp.txt
diff --git a/content/test/data/accessibility/event/live-region-change-innerhtml-expected-android-exp.txt b/content/test/data/accessibility/event/live-region-change-innerhtml-expected-android-exp.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/live-region-change-innerhtml-expected-android-exp.txt
diff --git a/content/test/data/accessibility/event/live-region-change-innertext-expected-android-exp.txt b/content/test/data/accessibility/event/live-region-change-innertext-expected-android-exp.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/live-region-change-innertext-expected-android-exp.txt
diff --git a/content/test/data/accessibility/event/live-region-create-expected-android.txt b/content/test/data/accessibility/event/live-region-create-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/live-region-create-expected-android.txt
diff --git a/content/test/data/accessibility/event/live-region-remove-expected-android.txt b/content/test/data/accessibility/event/live-region-remove-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/live-region-remove-expected-android.txt
diff --git a/content/test/data/accessibility/event/menu-opened-closed-expected-android.txt b/content/test/data/accessibility/event/menu-opened-closed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/menu-opened-closed-expected-android.txt
diff --git a/content/test/data/accessibility/event/menubar-show-hide-menus-expected-android.txt b/content/test/data/accessibility/event/menubar-show-hide-menus-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/menubar-show-hide-menus-expected-android.txt
diff --git a/content/test/data/accessibility/event/menulist-collapse-expected-android.txt b/content/test/data/accessibility/event/menulist-collapse-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/menulist-collapse-expected-android.txt
diff --git a/content/test/data/accessibility/event/menulist-collapse-next-expected-android.txt b/content/test/data/accessibility/event/menulist-collapse-next-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/menulist-collapse-next-expected-android.txt
diff --git a/content/test/data/accessibility/event/menulist-expand-expected-android.txt b/content/test/data/accessibility/event/menulist-expand-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/menulist-expand-expected-android.txt
diff --git a/content/test/data/accessibility/event/menulist-focus-expected-android.txt b/content/test/data/accessibility/event/menulist-focus-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/menulist-focus-expected-android.txt
diff --git a/content/test/data/accessibility/event/menulist-next-expected-android.txt b/content/test/data/accessibility/event/menulist-next-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/menulist-next-expected-android.txt
diff --git a/content/test/data/accessibility/event/multiple-aria-properties-changed-expected-android.txt b/content/test/data/accessibility/event/multiple-aria-properties-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/multiple-aria-properties-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/name-change-expected-android.txt b/content/test/data/accessibility/event/name-change-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/name-change-expected-android.txt
diff --git a/content/test/data/accessibility/event/name-change-indirect-expected-android.txt b/content/test/data/accessibility/event/name-change-indirect-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/name-change-indirect-expected-android.txt
diff --git a/content/test/data/accessibility/event/navigation-api-expected-android.txt b/content/test/data/accessibility/event/navigation-api-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/navigation-api-expected-android.txt
diff --git a/content/test/data/accessibility/event/range-value-is-readonly-changed-expected-android.txt b/content/test/data/accessibility/event/range-value-is-readonly-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/range-value-is-readonly-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/range-value-maximum-changed-expected-android.txt b/content/test/data/accessibility/event/range-value-maximum-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/range-value-maximum-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/range-value-minimum-changed-expected-android.txt b/content/test/data/accessibility/event/range-value-minimum-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/range-value-minimum-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/range-value-step-changed-expected-android.txt b/content/test/data/accessibility/event/range-value-step-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/range-value-step-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/remove-child-expected-android.txt b/content/test/data/accessibility/event/remove-child-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/remove-child-expected-android.txt
diff --git a/content/test/data/accessibility/event/remove-hidden-attribute-expected-android.txt b/content/test/data/accessibility/event/remove-hidden-attribute-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/remove-hidden-attribute-expected-android.txt
diff --git a/content/test/data/accessibility/event/select-selected-add-remove-expected-android.txt b/content/test/data/accessibility/event/select-selected-add-remove-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/select-selected-add-remove-expected-android.txt
diff --git a/content/test/data/accessibility/event/style-changed-expected-android.txt b/content/test/data/accessibility/event/style-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/style-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/tabindex-added-on-aria-hidden-expected-android.txt b/content/test/data/accessibility/event/tabindex-added-on-aria-hidden-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/tabindex-added-on-aria-hidden-expected-android.txt
diff --git a/content/test/data/accessibility/event/tabindex-added-on-plain-div-expected-android.txt b/content/test/data/accessibility/event/tabindex-added-on-plain-div-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/tabindex-added-on-plain-div-expected-android.txt
diff --git a/content/test/data/accessibility/event/tabindex-removed-on-aria-hidden-expected-android.txt b/content/test/data/accessibility/event/tabindex-removed-on-aria-hidden-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/tabindex-removed-on-aria-hidden-expected-android.txt
diff --git a/content/test/data/accessibility/event/tabindex-removed-on-plain-div-expected-android.txt b/content/test/data/accessibility/event/tabindex-removed-on-plain-div-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/tabindex-removed-on-plain-div-expected-android.txt
diff --git a/content/test/data/accessibility/event/tbody-focus-expected-android.txt b/content/test/data/accessibility/event/tbody-focus-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/tbody-focus-expected-android.txt
diff --git a/content/test/data/accessibility/event/text-align-changed-expected-android.txt b/content/test/data/accessibility/event/text-align-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/text-align-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/text-changed-contenteditable-expected-android.txt b/content/test/data/accessibility/event/text-changed-contenteditable-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/text-changed-contenteditable-expected-android.txt
diff --git a/content/test/data/accessibility/event/text-changed-expected-android.txt b/content/test/data/accessibility/event/text-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/text-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/text-indent-changed-expected-android.txt b/content/test/data/accessibility/event/text-indent-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/text-indent-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/tfoot-focus-expected-android.txt b/content/test/data/accessibility/event/tfoot-focus-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/tfoot-focus-expected-android.txt
diff --git a/content/test/data/accessibility/event/thead-focus-expected-android.txt b/content/test/data/accessibility/event/thead-focus-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/thead-focus-expected-android.txt
diff --git a/content/test/data/accessibility/event/value-is-readonly-changed-expected-android.txt b/content/test/data/accessibility/event/value-is-readonly-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/value-is-readonly-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/value-value-changed-expected-android.txt b/content/test/data/accessibility/event/value-value-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/value-value-changed-expected-android.txt
diff --git a/content/test/data/accessibility/event/visibility-hidden-changed-expected-android.txt b/content/test/data/accessibility/event/visibility-hidden-changed-expected-android.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/content/test/data/accessibility/event/visibility-hidden-changed-expected-android.txt
diff --git a/docs/experiments/prompt-api-for-extension.md b/docs/experiments/prompt-api-for-extension.md index af1eafb..c75eb93 100644 --- a/docs/experiments/prompt-api-for-extension.md +++ b/docs/experiments/prompt-api-for-extension.md
@@ -1,27 +1,18 @@ # Prompt API for extension -- Contact: builtin-ai@chromium.org - This document describes the status of the current implementation of the -[**Prompt API**](https://github.com/explainers-by-googlers/prompt-api) -for Chrome extension, and how to verify. - -Note that this API is not available by default. Chrome plans to do an -extension origin trial starting from M131 to evaluate its effectiveness -and to allow extension authors to give feedback. - +[**Prompt API**](https://github.com/webmachinelearning/prompt-api) for Chrome +extensions, and how to verify. ## What’s supported -The API is implemented according to the -[explainer](https://github.com/explainers-by-googlers/prompt-api), but the -API namespace will be under `chrome.aiOriginTrial.languageModel` for the -extension origin trial. +The implementation generally intends to follow the +[explainer](https://github.com/explainers-by-googlers/prompt-api). ## Activation The API can be enabled by participating in the -[extension origin trial](https://developer.chrome.com/docs/web-platform/origin-trials#extensions) +[extension origin trial](https://developer.chrome.com/blog/prompt-api-origin-trial) named `AIPromptAPIForExtension`. After obtaining the trial token, the extension authors need to configure it in the `manifest.json` together with the `aiLanguageModelOriginTrial` permission. @@ -31,20 +22,21 @@ "permissions": ["aiLanguageModelOriginTrial"], "trial_tokens": [<GENERATED_TOKEN>], } - ``` ## Verifying the API is working -The extension authors can verify if the API is available by checking the -`chrome.aiOriginTrial.languageModel` from the service worker script. -If the `AILanguageModel` object is defined, the authors can follow the -[explainer](https://github.com/explainers-by-googlers/prompt-api) to test -the APIs usage. +The extension authors can verify if the API is available by checking for the +presence of `LanguageModel` or `chrome.aiOriginTrial.languageModel` entrypoints +from extension window and worker scripts. If the object is defined, the authors +can follow the [explainer](https://github.com/explainers-by-googlers/prompt-api) +and [developer docs](https://developer.chrome.com/docs/extensions/ai/prompt-api) +to check availability and test the APIs usage. ## Related Links -- [Prompt API Explainer on GitHub](https://github.com/explainers-by-googlers/prompt-api) -- [Reporting bugs](https://g-issues.chromium.org/issues/new?component=1583624&priority=P2&type=feature_request&template=0&noWizard=true) -- [API Feedback](https://github.com/explainers-by-googlers/prompt-api/issues) -<!-- TODO: link the DevRel doc with more details once it's published --> +- [Explainer on GitHub](https://github.com/webmachinelearning/prompt-api) +- [API feedback](https://github.com/webmachinelearning/prompt-api/issues) +- [Reporting bugs](https://issues.chromium.org/issues/new?component=1583624) +- [Extension origin trial](https://developer.chrome.com/blog/prompt-api-origin-trial) +- [Developer docs](https://developer.chrome.com/docs/extensions/ai/prompt-api)
diff --git a/extensions/browser/sandboxed_unpacker_unittest.cc b/extensions/browser/sandboxed_unpacker_unittest.cc index b13617b..394cc3d 100644 --- a/extensions/browser/sandboxed_unpacker_unittest.cc +++ b/extensions/browser/sandboxed_unpacker_unittest.cc
@@ -14,6 +14,7 @@ #include "base/files/file_util.h" #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" +#include "base/json/json_reader.h" #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "base/path_service.h" @@ -509,10 +510,17 @@ // Check that there is no _locales folder. base::FilePath install_path = GetInstallPath().Append(kLocaleFolder); EXPECT_FALSE(base::PathExists(install_path)); - EXPECT_TRUE(base::MatchPattern(GetInstallErrorMessage(), - u"*_locales?en_US?messages.json': EOF while " - u"parsing a string at line 4*")) - << GetInstallErrorMessage(); + if (base::JSONReader::UsingRust()) { + EXPECT_TRUE(base::MatchPattern(GetInstallErrorMessage(), + u"*_locales?en_US?messages.json': EOF while " + u"parsing a string at line 4*")) + << GetInstallErrorMessage(); + } else { + EXPECT_TRUE(base::MatchPattern( + GetInstallErrorMessage(), + u"*_locales?en_US?messages.json': Line: 4, column: 1,*")) + << GetInstallErrorMessage(); + } ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE, GetInstallErrorType()); EXPECT_EQ(static_cast<int>( @@ -558,6 +566,21 @@ GetInstallErrorDetail()); } +TEST_F(SandboxedUnpackerTest, JsonParserFails) { + // Disable the Rust JSON parser, as it is in-process and cannot crash. + base::test::ScopedFeatureList feature_list; + feature_list.InitWithFeatureState(base::features::kUseRustJsonParser, false); + + in_process_data_decoder().SimulateJsonParserCrash(true); + InitSandboxedUnpacker(); + + SetupUnpacker("good_package.crx", ""); + EXPECT_FALSE(InstallSucceeded()); + EXPECT_FALSE(GetInstallErrorMessage().empty()); + ASSERT_EQ(CrxInstallErrorType::SANDBOXED_UNPACKER_FAILURE, + GetInstallErrorType()); +} + TEST_F(SandboxedUnpackerTest, ImageDecoderFails) { in_process_data_decoder().SimulateImageDecoderCrash(true); InitSandboxedUnpacker();
diff --git a/extensions/browser/service_worker/service_worker_task_queue.cc b/extensions/browser/service_worker/service_worker_task_queue.cc index 3cc60628..49ea2de 100644 --- a/extensions/browser/service_worker/service_worker_task_queue.cc +++ b/extensions/browser/service_worker/service_worker_task_queue.cc
@@ -95,14 +95,14 @@ DCHECK(!process_manager->HasServiceWorker(*worker_id_) || g_allow_multiple_workers_per_extension); // Clear stale renderer state if there's any. - renderer_state_ = RendererState::kInitial; + renderer_state_ = RendererState::kNotActive; } worker_id_ = worker_id; } bool ServiceWorkerTaskQueue::WorkerState::ready() const { return browser_state_ == BrowserState::kStarted && - renderer_state_ == RendererState::kStarted && worker_id_.has_value(); + renderer_state_ == RendererState::kActive && worker_id_.has_value(); } ServiceWorkerTaskQueue::TestObserver::TestObserver() = default; @@ -298,10 +298,10 @@ // // TODO(lazyboy): Update the renderer state in RenderProcessExited() and // uncomment the following DCHECK: - // DCHECK_NE(RendererState::kStarted, worker_state->renderer_state_) + // DCHECK_NE(RendererState::kActive, worker_state->renderer_state_) // << "Worker already started"; worker_state->SetWorkerId(worker_id, ProcessManager::Get(browser_context_)); - worker_state->SetRendererState(RendererState::kStarted); + worker_state->SetRendererState(RendererState::kActive); RunPendingTasksIfWorkerReady(context_id); } @@ -334,8 +334,8 @@ return; } - DCHECK_NE(RendererState::kStopped, worker_state->renderer_state()); - worker_state->SetRendererState(RendererState::kStopped); + DCHECK_NE(RendererState::kNotActive, worker_state->renderer_state()); + worker_state->SetRendererState(RendererState::kNotActive); worker_state->ResetWorkerId(); if (g_test_observer) { @@ -405,7 +405,7 @@ if (worker_state->browser_state() != BrowserState::kReady) { return false; } - if (worker_state->renderer_state() != RendererState::kStarted) { + if (worker_state->renderer_state() != RendererState::kActive) { return false; } @@ -554,7 +554,7 @@ // receive tasks/events again and the renderer stop notifications are not 100% // reliable. worker_state->SetBrowserState(BrowserState::kInitial); - worker_state->SetRendererState(RendererState::kInitial); + worker_state->SetRendererState(RendererState::kNotActive); worker_state->ResetWorkerId(); }
diff --git a/extensions/browser/service_worker/service_worker_task_queue.h b/extensions/browser/service_worker/service_worker_task_queue.h index 08f6ff7..f1d667be 100644 --- a/extensions/browser/service_worker/service_worker_task_queue.h +++ b/extensions/browser/service_worker/service_worker_task_queue.h
@@ -168,12 +168,10 @@ // Render process worker state of an activated extension. enum class RendererState { - // Initial state, neither started nor stopped. - kInitial, - // Worker thread has started. - kStarted, - // Worker thread has not started or has been stopped. - kStopped, + // Worker thread has not started or has been stopped/terminated. + kNotActive, + // Worker thread has started and it's running. + kActive, }; // The current worker related state of an activated extension. @@ -204,7 +202,7 @@ private: BrowserState browser_state_ = BrowserState::kInitial; - RendererState renderer_state_ = RendererState::kInitial; + RendererState renderer_state_ = RendererState::kNotActive; // Contains the worker's WorkerId associated with this WorkerState, once we // have discovered info about the worker.
diff --git a/extensions/common/extension_l10n_util_unittest.cc b/extensions/common/extension_l10n_util_unittest.cc index 1210f71..7792f41 100644 --- a/extensions/common/extension_l10n_util_unittest.cc +++ b/extensions/common/extension_l10n_util_unittest.cc
@@ -10,6 +10,7 @@ #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" +#include "base/json/json_reader.h" #include "base/path_service.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -105,10 +106,19 @@ errors::kLocalesInvalidLocale, base::UTF16ToUTF8(de_messages_file.LossyDisplayName()), "Variable $VAR$ used but not defined."))); - EXPECT_THAT(error, testing::HasSubstr(ErrorUtils::FormatErrorMessage( - errors::kLocalesInvalidLocale, - base::UTF16ToUTF8(es_messages_file.LossyDisplayName()), - "expected value at line 1 column 24"))); + if (base::JSONReader::UsingRust()) { + EXPECT_THAT(error, + testing::HasSubstr(ErrorUtils::FormatErrorMessage( + errors::kLocalesInvalidLocale, + base::UTF16ToUTF8(es_messages_file.LossyDisplayName()), + "expected value at line 1 column 24"))); + } else { + EXPECT_THAT(error, + testing::HasSubstr(ErrorUtils::FormatErrorMessage( + errors::kLocalesInvalidLocale, + base::UTF16ToUTF8(es_messages_file.LossyDisplayName()), + "Line: 1, column: 24, Unexpected token."))); + } EXPECT_THAT(error, testing::HasSubstr(ErrorUtils::FormatErrorMessage( errors::kLocalesInvalidLocale, base::UTF16ToUTF8(fr_messages_file.LossyDisplayName()), @@ -267,11 +277,19 @@ std::string error; EXPECT_FALSE(extension_l10n_util::LoadMessageCatalogs( src_path, "en_US", GzippedMessagesPermission::kDisallow, &error)); - EXPECT_NE(std::string::npos, - error.find(ErrorUtils::FormatErrorMessage( - errors::kLocalesInvalidLocale, - base::UTF16ToUTF8(messages_file.LossyDisplayName()), - "EOF while parsing a value at line 1 column 9"))); + if (base::JSONReader::UsingRust()) { + EXPECT_NE(std::string::npos, + error.find(ErrorUtils::FormatErrorMessage( + errors::kLocalesInvalidLocale, + base::UTF16ToUTF8(messages_file.LossyDisplayName()), + "EOF while parsing a value at line 1 column 9"))); + } else { + EXPECT_NE(std::string::npos, + error.find(ErrorUtils::FormatErrorMessage( + errors::kLocalesInvalidLocale, + base::UTF16ToUTF8(messages_file.LossyDisplayName()), + "Line: 1, column: 10,"))); + } } TEST(ExtensionL10nUtil, LoadMessageCatalogsDuplicateKeys) {
diff --git a/extensions/common/file_util_unittest.cc b/extensions/common/file_util_unittest.cc index c9b390b..a590e3c 100644 --- a/extensions/common/file_util_unittest.cc +++ b/extensions/common/file_util_unittest.cc
@@ -442,10 +442,16 @@ install_dir, ManifestLocation::kUnpacked, Extension::NO_FLAGS, &error)); ASSERT_TRUE(extension.get() == nullptr); ASSERT_FALSE(error.empty()); - ASSERT_NE( - std::string::npos, - error.find(manifest_errors::kManifestParseError + - std::string(" expected `,` or `}` at line 2 column 16"))); + if (base::JSONReader::UsingRust()) { + ASSERT_NE( + std::string::npos, + error.find(manifest_errors::kManifestParseError + + std::string(" expected `,` or `}` at line 2 column 16"))); + } else { + ASSERT_NE(std::string::npos, + error.find(manifest_errors::kManifestParseError + + std::string(" Line: 2, column: 16,"))); + } } TEST_F(FileUtilTest, ValidateThemeUTF8) {
diff --git a/extensions/common/user_scripts_allowed_state.h b/extensions/common/user_scripts_allowed_state.h index cd45923..c257379 100644 --- a/extensions/common/user_scripts_allowed_state.h +++ b/extensions/common/user_scripts_allowed_state.h
@@ -5,6 +5,8 @@ #ifndef EXTENSIONS_COMMON_USER_SCRIPTS_ALLOWED_STATE_H_ #define EXTENSIONS_COMMON_USER_SCRIPTS_ALLOWED_STATE_H_ +#include <optional> + #include "extensions/common/extension_id.h" namespace extensions {
diff --git a/extensions/renderer/native_extension_bindings_system.cc b/extensions/renderer/native_extension_bindings_system.cc index f5ef0b9a..cc4f6517 100644 --- a/extensions/renderer/native_extension_bindings_system.cc +++ b/extensions/renderer/native_extension_bindings_system.cc
@@ -87,6 +87,7 @@ constexpr char kStringNameAIOriginTrial[] = "aiOriginTrial"; constexpr char kStringNameLanguageModel[] = "languageModel"; +constexpr char kStringNameGlobalLanguageModel[] = "LanguageModel"; // Returns true if the given |api| is a "prefixed" api of the |root_api|; that // is, if the api begins with the root. @@ -1165,9 +1166,8 @@ v8::HandleScope handle_scope(isolate); v8::Local<v8::Context> v8_context = context->v8_context(); - // If the extension has requested for `kAILanguageModelOriginTrial` - // permission, we will set the `chrome.aiOriginTrial.languageModel` as a - // mirror of `self.ai.languageModel`. + // Extensions with `kAILanguageModelOriginTrial` permission may access global + // `chrome.aiOriginTrial.languageModel` and `LanguageModel` entrypoints. if (!context->extension() || !context->extension() ->permissions_data() @@ -1195,6 +1195,21 @@ success = chrome_ai_object->CreateDataProperty( v8_context, language_model_name, language_model_value); CHECK(success.IsJust() && success.FromJust()); + + // Also ensure extensions with an OT token and permission support the + // experimental Web API's `LanguageModel` entrypoint, even when Web-specific + // flags aren't enabled. This approach should be simplified through API IDL + // extended attributes, as Web and Extension configuration states are aligned, + // and bindings for aiOriginTrial are aligned with other Built-In AI APIs. + v8::Local<v8::String> global_language_model_name = + gin::StringToSymbol(isolate, kStringNameGlobalLanguageModel); + if (!v8_context->Global() + ->HasRealNamedProperty(v8_context, global_language_model_name) + .FromJust()) { + success = v8_context->Global()->CreateDataProperty( + v8_context, global_language_model_name, language_model_value); + CHECK(success.IsJust() && success.FromJust()); + } } } // namespace extensions
diff --git a/internal b/internal index 4c4da7a..f968a67 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit 4c4da7a117aa9100f7a27e9f37a7e92b4bfcde60 +Subproject commit f968a67f8ed26827ecdbf84d5cb239dc600692f8
diff --git a/media/base/win/d3d11_mocks.cc b/media/base/win/d3d11_mocks.cc index a57f9707..5247e122a 100644 --- a/media/base/win/d3d11_mocks.cc +++ b/media/base/win/d3d11_mocks.cc
@@ -21,6 +21,9 @@ DXGIFactoryMock::DXGIFactoryMock() = default; DXGIFactoryMock::~DXGIFactoryMock() = default; +DXGIFactory2Mock::DXGIFactory2Mock() = default; +DXGIFactory2Mock::~DXGIFactory2Mock() = default; + DXGIDeviceMock::DXGIDeviceMock() = default; DXGIDeviceMock::~DXGIDeviceMock() = default; @@ -56,4 +59,7 @@ D3D11FenceMock::D3D11FenceMock() = default; D3D11FenceMock::~D3D11FenceMock() = default; +DXGISwapChain1Mock::DXGISwapChain1Mock() = default; +DXGISwapChain1Mock::~DXGISwapChain1Mock() = default; + } // namespace media \ No newline at end of file
diff --git a/media/base/win/d3d11_mocks.h b/media/base/win/d3d11_mocks.h index 43ac36f..3afb76f1 100644 --- a/media/base/win/d3d11_mocks.h +++ b/media/base/win/d3d11_mocks.h
@@ -349,6 +349,64 @@ MOCK_STDCALL_METHOD3(GetPrivateData, HRESULT(REFGUID, UINT*, void*)); }; +class DXGIFactory2Mock + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, + IDXGIFactory2> { + public: + DXGIFactory2Mock(); + ~DXGIFactory2Mock() override; + + // IDXGIFactory (inherited) + MOCK_STDCALL_METHOD2(CreateSoftwareAdapter, HRESULT(HMODULE, IDXGIAdapter**)); + MOCK_STDCALL_METHOD3(CreateSwapChain, + HRESULT(IUnknown*, + DXGI_SWAP_CHAIN_DESC*, + IDXGISwapChain**)); + MOCK_STDCALL_METHOD2(EnumAdapters, HRESULT(UINT, IDXGIAdapter**)); + MOCK_STDCALL_METHOD1(GetWindowAssociation, HRESULT(HWND*)); + MOCK_STDCALL_METHOD2(MakeWindowAssociation, HRESULT(HWND, UINT)); + MOCK_STDCALL_METHOD3(SetPrivateData, HRESULT(REFGUID, UINT, const void*)); + MOCK_STDCALL_METHOD2(SetPrivateDataInterface, + HRESULT(REFGUID, const IUnknown*)); + MOCK_STDCALL_METHOD2(GetParent, HRESULT(REFIID, void**)); + MOCK_STDCALL_METHOD3(GetPrivateData, HRESULT(REFGUID, UINT*, void*)); + + // IDXGIFactory1 + MOCK_STDCALL_METHOD2(EnumAdapters1, + HRESULT(UINT Adapter, IDXGIAdapter1** ppAdapter)); + MOCK_STDCALL_METHOD0(IsCurrent, BOOL()); + + // IDXGIFactory2 + MOCK_STDCALL_METHOD0(IsWindowedStereoEnabled, BOOL()); + MOCK_STDCALL_METHOD6(CreateSwapChainForHwnd, + HRESULT(IUnknown*, + HWND, + const DXGI_SWAP_CHAIN_DESC1*, + const DXGI_SWAP_CHAIN_FULLSCREEN_DESC*, + IDXGIOutput*, + IDXGISwapChain1**)); + MOCK_STDCALL_METHOD5(CreateSwapChainForCoreWindow, + HRESULT(IUnknown*, + IUnknown*, + const DXGI_SWAP_CHAIN_DESC1*, + IDXGIOutput*, + IDXGISwapChain1**)); + MOCK_STDCALL_METHOD2(GetSharedResourceAdapterLuid, HRESULT(HANDLE, LUID*)); + MOCK_STDCALL_METHOD3(RegisterStereoStatusWindow, HRESULT(HWND, UINT, DWORD*)); + MOCK_STDCALL_METHOD2(RegisterStereoStatusEvent, HRESULT(HANDLE, DWORD*)); + MOCK_STDCALL_METHOD1(UnregisterStereoStatus, void(DWORD)); + MOCK_STDCALL_METHOD3(RegisterOcclusionStatusWindow, + HRESULT(HWND, UINT, DWORD*)); + MOCK_STDCALL_METHOD2(RegisterOcclusionStatusEvent, HRESULT(HANDLE, DWORD*)); + MOCK_STDCALL_METHOD1(UnregisterOcclusionStatus, void(DWORD)); + MOCK_STDCALL_METHOD4(CreateSwapChainForComposition, + HRESULT(IUnknown*, + const DXGI_SWAP_CHAIN_DESC1*, + IDXGIOutput*, + IDXGISwapChain1**)); +}; + class DXGIDeviceMock : public Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, @@ -1576,6 +1634,58 @@ MOCK_STDCALL_METHOD2(SetEventOnCompletion, HRESULT(UINT64, HANDLE)); }; +class DXGISwapChain1Mock + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, + IDXGISwapChain1> { + public: + DXGISwapChain1Mock(); + ~DXGISwapChain1Mock() override; + + // IUnknown + MOCK_STDCALL_METHOD2(QueryInterface, HRESULT(REFIID, void**)); + MOCK_STDCALL_METHOD0(AddRef, ULONG()); + MOCK_STDCALL_METHOD0(Release, ULONG()); + + // IDXGIObject + MOCK_STDCALL_METHOD3(SetPrivateData, HRESULT(REFGUID, UINT, const void*)); + MOCK_STDCALL_METHOD2(SetPrivateDataInterface, + HRESULT(REFGUID, const IUnknown*)); + MOCK_STDCALL_METHOD3(GetPrivateData, HRESULT(REFGUID, UINT*, void*)); + MOCK_STDCALL_METHOD2(GetParent, HRESULT(REFIID, void**)); + + // IDXGIDeviceSubObject + MOCK_STDCALL_METHOD2(GetDevice, HRESULT(REFIID, void**)); + + // IDXGISwapChain + MOCK_STDCALL_METHOD2(Present, HRESULT(UINT, UINT)); + MOCK_STDCALL_METHOD3(GetBuffer, HRESULT(UINT, REFIID, void**)); + MOCK_STDCALL_METHOD2(SetFullscreenState, HRESULT(BOOL, IDXGIOutput*)); + MOCK_STDCALL_METHOD2(GetFullscreenState, HRESULT(BOOL*, IDXGIOutput**)); + MOCK_STDCALL_METHOD1(GetDesc, HRESULT(DXGI_SWAP_CHAIN_DESC*)); + MOCK_STDCALL_METHOD5(ResizeBuffers, + HRESULT(UINT, UINT, UINT, DXGI_FORMAT, UINT)); + MOCK_STDCALL_METHOD1(ResizeTarget, HRESULT(const DXGI_MODE_DESC*)); + MOCK_STDCALL_METHOD1(GetContainingOutput, HRESULT(IDXGIOutput**)); + MOCK_STDCALL_METHOD1(GetFrameStatistics, HRESULT(DXGI_FRAME_STATISTICS*)); + MOCK_STDCALL_METHOD1(GetLastPresentCount, HRESULT(UINT*)); + + // IDXGISwapChain1 + MOCK_STDCALL_METHOD3(Present1, + HRESULT(UINT, UINT, const DXGI_PRESENT_PARAMETERS*)); + MOCK_STDCALL_METHOD0(IsTemporaryMonoSupported, BOOL()); + MOCK_STDCALL_METHOD1(GetRestrictToOutput, HRESULT(IDXGIOutput**)); + MOCK_STDCALL_METHOD1(SetBackgroundColor, HRESULT(const DXGI_RGBA*)); + MOCK_STDCALL_METHOD1(GetBackgroundColor, HRESULT(DXGI_RGBA*)); + MOCK_STDCALL_METHOD1(SetRotation, HRESULT(DXGI_MODE_ROTATION)); + MOCK_STDCALL_METHOD1(GetRotation, HRESULT(DXGI_MODE_ROTATION*)); + MOCK_STDCALL_METHOD1(GetDesc1, HRESULT(DXGI_SWAP_CHAIN_DESC1* pDesc)); + MOCK_STDCALL_METHOD1(GetFullscreenDesc, + HRESULT(DXGI_SWAP_CHAIN_FULLSCREEN_DESC* pDesc)); + MOCK_STDCALL_METHOD1(GetHwnd, HRESULT(HWND* pHwnd)); + MOCK_STDCALL_METHOD2(GetCoreWindow, HRESULT(REFIID refiid, void** ppUnk)); +}; + } // namespace media #endif // MEDIA_BASE_WIN_D3D11_MOCKS_H_
diff --git a/media/filters/ffmpeg_aac_bitstream_converter.cc b/media/filters/ffmpeg_aac_bitstream_converter.cc index 45e87a3a9..7fd37e9 100644 --- a/media/filters/ffmpeg_aac_bitstream_converter.cc +++ b/media/filters/ffmpeg_aac_bitstream_converter.cc
@@ -183,8 +183,8 @@ int header_plus_packet_size = packet->size + kAdtsHeaderSize; if (!stream_codec_parameters_->extradata) { - DLOG(ERROR) << "extradata is null"; - return false; + DVLOG(3) << "extradata is null"; + return true; } if (stream_codec_parameters_->extradata_size < 2) { DLOG(ERROR) << "extradata too small to contain MP4A header";
diff --git a/media/filters/ffmpeg_aac_bitstream_converter_unittest.cc b/media/filters/ffmpeg_aac_bitstream_converter_unittest.cc index 61b2890..0e56a6e 100644 --- a/media/filters/ffmpeg_aac_bitstream_converter_unittest.cc +++ b/media/filters/ffmpeg_aac_bitstream_converter_unittest.cc
@@ -23,7 +23,7 @@ namespace { const int kAacMainProfile = 0; const int kAacLowComplexityProfile = 1; -} // namespace +} // namespace // Class for testing the FFmpegAACBitstreamConverter. class FFmpegAACBitstreamConverterTest : public testing::Test { @@ -69,7 +69,7 @@ for (size_t i = 0; i < (dummy_packet.size() * sizeof(decltype(dummy_packet)::value_type)); i++) { - dummy_packet[i] = i & 0xFF; // Repeated sequences of 0-255 + dummy_packet[i] = i & 0xFF; // Repeated sequences of 0-255 } auto test_packet = ScopedAVPacket::Allocate(); @@ -111,8 +111,9 @@ auto test_packet = ScopedAVPacket::Allocate(); CreatePacket(test_packet.get(), dummy_packet, sizeof(dummy_packet)); - // Try out the actual conversion. This should fail due to missing extradata. - EXPECT_FALSE(converter.ConvertPacket(test_packet.get())); + // Try out the actual conversion. This should not fail - conversion is + // necessary only when we have `extradata`. + EXPECT_TRUE(converter.ConvertPacket(test_packet.get())); } TEST_F(FFmpegAACBitstreamConverterTest, Conversion_AudioProfileType) { @@ -121,8 +122,7 @@ uint8_t dummy_packet[1000] = {}; auto test_packet = ScopedAVPacket::Allocate(); - CreatePacket(test_packet.get(), dummy_packet, - sizeof(dummy_packet)); + CreatePacket(test_packet.get(), dummy_packet, sizeof(dummy_packet)); EXPECT_TRUE(converter.ConvertPacket(test_packet.get())); @@ -135,8 +135,7 @@ FFmpegAACBitstreamConverter converter_he(&test_parameters_); test_packet = ScopedAVPacket::Allocate(); - CreatePacket(test_packet.get(), dummy_packet, - sizeof(dummy_packet)); + CreatePacket(test_packet.get(), dummy_packet, sizeof(dummy_packet)); EXPECT_TRUE(converter_he.ConvertPacket(test_packet.get())); @@ -148,8 +147,7 @@ FFmpegAACBitstreamConverter converter_eld(&test_parameters_); test_packet = ScopedAVPacket::Allocate(); - CreatePacket(test_packet.get(), dummy_packet, - sizeof(dummy_packet)); + CreatePacket(test_packet.get(), dummy_packet, sizeof(dummy_packet)); EXPECT_FALSE(converter_eld.ConvertPacket(test_packet.get())); } @@ -160,8 +158,7 @@ uint8_t dummy_packet[1000]; auto test_packet = ScopedAVPacket::Allocate(); - CreatePacket(test_packet.get(), dummy_packet, - sizeof(dummy_packet)); + CreatePacket(test_packet.get(), dummy_packet, sizeof(dummy_packet)); // Try out the actual conversion (should be successful and allocate new // packet and destroy the old one).
diff --git a/net/base/lookup_string_in_fixed_set.cc b/net/base/lookup_string_in_fixed_set.cc index e062044..925f0f48 100644 --- a/net/base/lookup_string_in_fixed_set.cc +++ b/net/base/lookup_string_in_fixed_set.cc
@@ -4,10 +4,11 @@ #include "net/base/lookup_string_in_fixed_set.h" -#include <cstdint> +#include <stdint.h> + +#include <string_view> #include "base/check.h" -#include "base/compiler_specific.h" #include "base/containers/span.h" namespace net { @@ -186,16 +187,14 @@ } int LookupStringInFixedSet(base::span<const uint8_t> graph, - const char* key, - size_t key_length) { + std::string_view key) { // Do an incremental lookup until either the end of the graph is reached, or - // until every character in |key| is consumed. + // until every character in `key` is consumed. FixedSetIncrementalLookup lookup(graph); - const char* key_end = UNSAFE_TODO(key + key_length); - while (key != key_end) { - if (!lookup.Advance(*key)) + for (char input : key) { + if (!lookup.Advance(input)) { return kDafsaNotFound; - UNSAFE_TODO(key++); + } } // The entire input was consumed without reaching the end of the graph. Return // the result code (if present) for the current position, or kDafsaNotFound.
diff --git a/net/base/lookup_string_in_fixed_set.h b/net/base/lookup_string_in_fixed_set.h index d8a4357..e4b492a 100644 --- a/net/base/lookup_string_in_fixed_set.h +++ b/net/base/lookup_string_in_fixed_set.h
@@ -6,8 +6,8 @@ #define NET_BASE_LOOKUP_STRING_IN_FIXED_SET_H_ #include <stddef.h> +#include <stdint.h> -#include <cstdint> #include <string_view> #include "base/containers/span.h" @@ -27,20 +27,19 @@ kDafsaPrivateRule = 4, // key matched a private rule }; -// Looks up the string |key| with length |key_length| in a fixed set of -// strings. The set of strings must be known at compile time. It is converted to -// a graph structure named a DAFSA (Deterministic Acyclic Finite State -// Automaton) by the script make_dafsa.py during compilation. This permits -// efficient (in time and space) lookup. The graph generated by make_dafsa.py -// takes the form of a constant byte array which should be supplied via the -// |graph| parameter. The return value is kDafsaNotFound, kDafsaFound, or a -// bitmap consisting of one or more of kDafsaExceptionRule, kDafsaWildcardRule -// and kDafsaPrivateRule ORed together. +// Looks up the string `key` with in a fixed set of strings. The set of strings +// must be known at compile time. It is converted to a graph structure named a +// DAFSA (Deterministic Acyclic Finite State Automaton) by the script +// make_dafsa.py during compilation. This permits efficient (in time and space) +// lookup. The graph generated by make_dafsa.py takes the form of a constant +// byte array which should be supplied via the |graph| parameter. The return +// value is kDafsaNotFound, kDafsaFound, or a bitmap consisting of one or more +// of kDafsaExceptionRule, kDafsaWildcardRule and kDafsaPrivateRule ORed +// together. // // TODO(nick): Replace this with FixedSetIncrementalLookup everywhere. NET_EXPORT int LookupStringInFixedSet(base::span<const uint8_t> graph, - const char* key, - size_t key_length); + std::string_view key); // Looks up the longest matching suffix for |host| with length |length| in a // reversed DAFSA. Partial matches must begin at a new component, i.e. host
diff --git a/net/base/lookup_string_in_fixed_set_fuzzer.cc b/net/base/lookup_string_in_fixed_set_fuzzer.cc index bb547a2..2a8ba7a5 100644 --- a/net/base/lookup_string_in_fixed_set_fuzzer.cc +++ b/net/base/lookup_string_in_fixed_set_fuzzer.cc
@@ -2,10 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "net/base/lookup_string_in_fixed_set.h" + #include <stddef.h> #include <stdint.h> -#include "net/base/lookup_string_in_fixed_set.h" +#include <string_view> + +#include "base/compiler_specific.h" namespace { #include "net/base/registry_controlled_domains/effective_tld_names-inc.cc" @@ -13,7 +17,8 @@ // Entry point for LibFuzzer. extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { - net::LookupStringInFixedSet(kDafsa, reinterpret_cast<const char*>(data), - size); + net::LookupStringInFixedSet( + kDafsa, UNSAFE_BUFFERS( + std::string_view(reinterpret_cast<const char*>(data), size))); return 0; }
diff --git a/net/base/lookup_string_in_fixed_set_unittest.cc b/net/base/lookup_string_in_fixed_set_unittest.cc index e516b23..e0fbbfa 100644 --- a/net/base/lookup_string_in_fixed_set_unittest.cc +++ b/net/base/lookup_string_in_fixed_set_unittest.cc
@@ -9,12 +9,12 @@ #include "net/base/lookup_string_in_fixed_set.h" -#include <string.h> - #include <algorithm> #include <cstdint> #include <limits> #include <ostream> +#include <string> +#include <string_view> #include <utility> #include <vector> @@ -46,7 +46,7 @@ } struct Expectation { - const char* const key; + std::string_view key; int value; }; @@ -56,8 +56,8 @@ class LookupStringInFixedSetTest : public testing::TestWithParam<Expectation> { protected: - int LookupInGraph(base::span<const uint8_t> graph, const char* key) { - return LookupStringInFixedSet(graph, key, strlen(key)); + int LookupInGraph(base::span<const uint8_t> graph, std::string_view key) { + return LookupStringInFixedSet(graph, key); } };
diff --git a/printing/android/java/src/org/chromium/printing/PrintingControllerImpl.java b/printing/android/java/src/org/chromium/printing/PrintingControllerImpl.java index 0e567b5..2f938210 100644 --- a/printing/android/java/src/org/chromium/printing/PrintingControllerImpl.java +++ b/printing/android/java/src/org/chromium/printing/PrintingControllerImpl.java
@@ -16,6 +16,7 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.Log; +import org.chromium.base.ResettersForTesting; import org.chromium.base.ThreadUtils; import org.chromium.build.annotations.NullMarked; import org.chromium.build.annotations.Nullable; @@ -58,6 +59,8 @@ /** The singleton instance for this class. */ @VisibleForTesting protected static @Nullable PrintingController sInstance; + private static @Nullable PrintingController sInstanceForTesting; + private @Nullable String mErrorMessage; private int mRenderProcessId; @@ -103,6 +106,11 @@ mPrintDocumentAdapterWrapper = new PrintDocumentAdapterWrapper(this); } + public static void setInstanceForTesting(PrintingController instanceForTesting) { + sInstanceForTesting = instanceForTesting; + ResettersForTesting.register(() -> sInstanceForTesting = null); + } + /** * Returns the singleton instance, lazily creating one if needed. * @@ -111,6 +119,8 @@ public static PrintingController getInstance() { ThreadUtils.assertOnUiThread(); + if (sInstanceForTesting != null) return sInstanceForTesting; + if (sInstance == null) { sInstance = new PrintingControllerImpl(); } @@ -152,6 +162,11 @@ return mIsBusy; } + @VisibleForTesting + public @Nullable Printable getPrintable() { + return mPrintable; + } + @Override public void setPendingPrint( final Printable printable,
diff --git a/remoting/protocol/webrtc_audio_source_adapter.cc b/remoting/protocol/webrtc_audio_source_adapter.cc index e7849d7..f09ccca 100644 --- a/remoting/protocol/webrtc_audio_source_adapter.cc +++ b/remoting/protocol/webrtc_audio_source_adapter.cc
@@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "remoting/protocol/webrtc_audio_source_adapter.h" +#include <algorithm> #include <utility> +#include <vector> #include "base/check_op.h" +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/observer_list.h" #include "base/synchronization/lock.h" @@ -23,12 +21,28 @@ namespace remoting::protocol { +namespace { + static const int kChannels = 2; static const int kBytesPerSample = 2; // Frame size expected by webrtc::AudioTrackSinkInterface. static constexpr base::TimeDelta kAudioFrameDuration = base::Milliseconds(10); +// Notify all audio sinks about a new audio frame. +void NotifyAudioSinks( + base::ObserverList<webrtc::AudioTrackSinkInterface>::Unchecked& audio_sinks, + base::span<const uint8_t> frame, + int sampling_rate, + size_t samples_per_frame) { + for (auto& observer : audio_sinks) { + observer.OnData(frame.data(), kBytesPerSample * 8, sampling_rate, kChannels, + samples_per_frame); + } +} + +} // namespace + class WebrtcAudioSourceAdapter::Core { public: Core(); @@ -112,44 +126,43 @@ partial_frame_.clear(); } - size_t samples_per_frame = (kAudioFrameDuration * sampling_rate_).InSeconds(); - size_t bytes_per_frame = kBytesPerSample * kChannels * samples_per_frame; + const size_t samples_per_frame = + (kAudioFrameDuration * sampling_rate_).InSeconds(); + const size_t bytes_per_frame = + kBytesPerSample * kChannels * samples_per_frame; - const std::string& data = packet->data(0); - - size_t position = 0; + base::span<const uint8_t> input_data = base::as_byte_span(packet->data(0)); base::AutoLock lock(audio_sinks_lock_); + // Stage 1: Fill and send |partial_frame_|. if (!partial_frame_.empty()) { - size_t bytes_to_append = - std::min(bytes_per_frame - partial_frame_.size(), data.size()); - position += bytes_to_append; - partial_frame_.insert(partial_frame_.end(), data.data(), - data.data() + bytes_to_append); - if (partial_frame_.size() < bytes_per_frame) { - // Still don't have full frame. - return; - } + const size_t needed_bytes = bytes_per_frame - partial_frame_.size(); + const size_t copy_bytes = std::min(needed_bytes, input_data.size()); - // Here |partial_frame_| always contains a full frame. - DCHECK_EQ(partial_frame_.size(), bytes_per_frame); + partial_frame_.insert(partial_frame_.end(), input_data.begin(), + input_data.begin() + copy_bytes); + input_data = input_data.subspan(copy_bytes); - for (auto& observer : audio_sinks_) { - observer.OnData(&partial_frame_.front(), kBytesPerSample * 8, - sampling_rate_, kChannels, samples_per_frame); + if (partial_frame_.size() == bytes_per_frame) { + NotifyAudioSinks(audio_sinks_, base::span<const uint8_t>(partial_frame_), + sampling_rate_, samples_per_frame); + partial_frame_.clear(); } } - while (position + bytes_per_frame <= data.size()) { - for (auto& observer : audio_sinks_) { - observer.OnData(data.data() + position, kBytesPerSample * 8, - sampling_rate_, kChannels, samples_per_frame); - } - position += bytes_per_frame; + // Stage 2: Processing of |full_frames|. + const size_t full_frames = input_data.size() / bytes_per_frame; + for (size_t i = 0; i < full_frames; ++i) { + const auto frame = input_data.subspan(i * bytes_per_frame, bytes_per_frame); + NotifyAudioSinks(audio_sinks_, frame, sampling_rate_, samples_per_frame); } - partial_frame_.assign(data.data() + position, data.data() + data.size()); + // Stage 3: Save remaining data. + const size_t processed_bytes = full_frames * bytes_per_frame; + const auto remaining = input_data.subspan(processed_bytes); + partial_frame_.insert(partial_frame_.end(), remaining.begin(), + remaining.end()); } WebrtcAudioSourceAdapter::WebrtcAudioSourceAdapter(
diff --git a/remoting/protocol/webrtc_audio_source_adapter_unittest.cc b/remoting/protocol/webrtc_audio_source_adapter_unittest.cc index 4af3ba2..8973f12 100644 --- a/remoting/protocol/webrtc_audio_source_adapter_unittest.cc +++ b/remoting/protocol/webrtc_audio_source_adapter_unittest.cc
@@ -2,16 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif - #include "remoting/protocol/webrtc_audio_source_adapter.h" +#include <algorithm> +#include <iterator> #include <numeric> #include <vector> +#include "base/containers/span.h" #include "base/memory/ptr_util.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" @@ -48,9 +46,10 @@ EXPECT_EQ(kChannels, static_cast<int>(number_of_channels)); EXPECT_EQ((kSampleRate * kFrameDuration).InSeconds(), static_cast<int>(number_of_samples)); - const int16_t* samples = reinterpret_cast<const int16_t*>(audio_data); - samples_.insert(samples_.end(), samples, - samples + number_of_samples * kChannels); + const int16_t* samples = static_cast<const int16_t*>(audio_data); + size_t sample_count = number_of_samples * kChannels; + samples_.reserve(samples_.size() + sample_count); + std::copy_n(samples, sample_count, std::back_inserter(samples_)); } const std::vector<int16_t>& samples() { return samples_; } @@ -98,8 +97,8 @@ } std::unique_ptr<AudioPacket> packet(new AudioPacket()); - packet->add_data(reinterpret_cast<char*>(&(data[0])), - num_samples * kChannels * sizeof(int16_t)); + auto bytes = base::as_bytes(base::span(data)); + packet->add_data(reinterpret_cast<const char*>(bytes.data()), bytes.size()); packet->set_encoding(AudioPacket::ENCODING_RAW); packet->set_sampling_rate(AudioPacket::SAMPLING_RATE_48000); packet->set_bytes_per_sample(AudioPacket::BYTES_PER_SAMPLE_2);
diff --git a/services/data_decoder/BUILD.gn b/services/data_decoder/BUILD.gn index 878f77a..e9edd2c 100644 --- a/services/data_decoder/BUILD.gn +++ b/services/data_decoder/BUILD.gn
@@ -118,6 +118,22 @@ } } +if (use_blink) { + test("json_sanitizer_fuzztests") { + sources = [ "public/cpp/json_sanitizer_fuzztests.cc" ] + + fuzztests = + [ "JsonSanitizerFuzzTest.SanitizerAndBaseJsonReaderDecoderMatch" ] + + deps = [ + "//base", + "//base/test:test_support", + "//services/data_decoder/public/cpp", + "//third_party/fuzztest:fuzztest_gtest_main", + ] + } +} + # This is a separate target because //third_party/libxml:libxml_utils # wants to limit its visibility to a select number of target, but the # "fuzzer_test" template expands on iOS to many targets that need to
diff --git a/services/data_decoder/DEPS b/services/data_decoder/DEPS index d6423a26..c624c628 100644 --- a/services/data_decoder/DEPS +++ b/services/data_decoder/DEPS
@@ -7,6 +7,7 @@ "+net", "+services/data_decoder/public/cpp/android/safe_json_jni_headers", "+skia", + "+third_party/fuzztest", "+third_party/libxml/chromium", "+third_party/blink/public", "+third_party/skia",
diff --git a/services/data_decoder/public/cpp/data_decoder.cc b/services/data_decoder/public/cpp/data_decoder.cc index 512b48a..44884fc4 100644 --- a/services/data_decoder/public/cpp/data_decoder.cc +++ b/services/data_decoder/public/cpp/data_decoder.cc
@@ -8,6 +8,7 @@ #include <string> #include <utility> +#include "base/features.h" #include "base/functional/callback.h" #include "base/json/json_reader.h" #include "base/memory/ref_counted.h" @@ -27,6 +28,11 @@ #include "services/data_decoder/public/mojom/structured_headers_parser.mojom.h" #include "services/data_decoder/public/mojom/xml_parser.mojom.h" +#if BUILDFLAG(IS_ANDROID) +#include "base/types/expected_macros.h" +#include "services/data_decoder/public/cpp/json_sanitizer.h" +#endif + #if !BUILDFLAG(USE_BLINK) #include "services/data_decoder/data_decoder_service.h" // nogncheck #endif @@ -198,11 +204,62 @@ }, base::ElapsedTimer(), std::move(callback)); - base::JSONReader::Result result = - base::JSONReader::ReadAndReturnValueWithError(json, base::JSON_PARSE_RFC); - base::SequencedTaskRunner::GetCurrentDefault()->PostTask( - FROM_HERE, base::BindOnce(&ParsingComplete, cancel_requests_, - std::move(callback), std::move(result))); + if (base::JSONReader::UsingRust()) { + if (base::features::kUseRustJsonParserInCurrentSequence.Get()) { + base::JSONReader::Result result = + base::JSONReader::ReadAndReturnValueWithError(json, + base::JSON_PARSE_RFC); + base::SequencedTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(&ParsingComplete, cancel_requests_, + std::move(callback), std::move(result))); + } else { + base::ThreadPool::PostTaskAndReplyWithResult( + FROM_HERE, {base::TaskPriority::USER_VISIBLE}, + base::BindOnce( + [](const std::string& json) { + return base::JSONReader::ReadAndReturnValueWithError( + json, base::JSON_PARSE_RFC); + }, + json), + base::BindOnce(&ParsingComplete, cancel_requests_, + std::move(callback))); + } + return; + } + +#if BUILDFLAG(IS_ANDROID) + // For Android, if the full Rust parser is not available, we use the + // in-process sanitizer and then parse in-process. + JsonSanitizer::Sanitize( + json, base::BindOnce( + [](ValueParseCallback callback, + scoped_refptr<CancellationFlag> is_cancelled, + JsonSanitizer::Result result) { + if (is_cancelled->data) { + return; + } + + RETURN_IF_ERROR(result, [&](std::string error) { + std::move(callback).Run(base::unexpected(std::move(error))); + }); + + ParsingComplete(is_cancelled, std::move(callback), + base::JSONReader::ReadAndReturnValueWithError( + result.value(), base::JSON_PARSE_RFC)); + }, + std::move(callback), cancel_requests_)); +#else // BUILDFLAG(IS_ANDROID) + // Parse JSON out-of-process. + auto request = + base::MakeRefCounted<ValueParseRequest<mojom::JsonParser, base::Value>>( + std::move(callback), cancel_requests_); + GetService()->BindJsonParser(request->BindRemote()); + request->remote()->Parse( + json, base::JSON_PARSE_RFC, + base::BindOnce(&ValueParseRequest<mojom::JsonParser, + base::Value>::OnServiceValueOrError, + request)); +#endif // BUILDFLAG(IS_ANDROID) } // static
diff --git a/services/data_decoder/public/cpp/data_decoder_unittest.cc b/services/data_decoder/public/cpp/data_decoder_unittest.cc index 0e8cf67..2eb9bf9 100644 --- a/services/data_decoder/public/cpp/data_decoder_unittest.cc +++ b/services/data_decoder/public/cpp/data_decoder_unittest.cc
@@ -6,11 +6,13 @@ #include <memory> +#include "base/features.h" #include "base/functional/bind.h" #include "base/run_loop.h" #include "base/task/thread_pool/thread_pool_instance.h" #include "base/test/bind.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/types/expected.h" #include "base/values.h" @@ -206,33 +208,63 @@ class DataDecoderMultiThreadTest : public testing::Test { protected: + void TestJSONDecode() { + base::RunLoop run_loop; + DataDecoder decoder; + DataDecoder::ValueOrError result; + decoder.ParseJson( + // The magic 122.416294033786585 number comes from + // https://github.com/serde-rs/json/issues/707 + "[ 122.416294033786585 ]", + base::BindLambdaForTesting( + [&run_loop, &result](DataDecoder::ValueOrError value_or_error) { + result = std::move(value_or_error); + run_loop.Quit(); + })); + run_loop.Run(); + histogram_tester_.ExpectTotalCount("Security.DataDecoder.Json.DecodingTime", + 1); + ASSERT_TRUE(result.has_value()); + ASSERT_TRUE(result->is_list()); + base::Value::List& list = result->GetList(); + ASSERT_EQ(1u, list.size()); + EXPECT_TRUE(list[0].is_double()); + EXPECT_EQ(122.416294033786585, list[0].GetDouble()); + } + base::test::TaskEnvironment task_environment_; base::HistogramTester histogram_tester_; }; +// Test basic JSON decoding without using Rust. We test only on Android, +// because otherwise this would result in spawning a process. +#if BUILDFLAG(IS_ANDROID) +#define MAYBE_JSONDecodeNonRust JSONDecodeNonRust +#else // BUILDFLAG(IS_ANDROID) +#define MAYBE_JSONDecodeNonRust DISABLED_JSONDecodeNonRust +#endif // BUILDFLAG(IS_ANDROID) +TEST_F(DataDecoderMultiThreadTest, MAYBE_JSONDecodeNonRust) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndDisableFeature(base::features::kUseRustJsonParser); + TestJSONDecode(); +} + // Test basic JSON decoding using Rust, in a threadpool. -TEST_F(DataDecoderMultiThreadTest, JSONDecode) { - base::RunLoop run_loop; - DataDecoder decoder; - DataDecoder::ValueOrError result; - decoder.ParseJson( - // The magic 122.416294033786585 number comes from - // https://github.com/serde-rs/json/issues/707 - "[ 122.416294033786585 ]", - base::BindLambdaForTesting( - [&run_loop, &result](DataDecoder::ValueOrError value_or_error) { - result = std::move(value_or_error); - run_loop.Quit(); - })); - run_loop.Run(); - histogram_tester_.ExpectTotalCount("Security.DataDecoder.Json.DecodingTime", - 1); - ASSERT_TRUE(result.has_value()); - ASSERT_TRUE(result->is_list()); - base::Value::List& list = result->GetList(); - ASSERT_EQ(1u, list.size()); - EXPECT_TRUE(list[0].is_double()); - EXPECT_EQ(122.416294033786585, list[0].GetDouble()); +TEST_F(DataDecoderMultiThreadTest, JSONDecodeRustThreadpool) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeatureWithParameters( + base::features::kUseRustJsonParser, + {{"UseRustJsonParserInCurrentSequence", "false"}}); + TestJSONDecode(); +} + +// Test basic JSON decoding using Rust, in the main thread. +TEST_F(DataDecoderMultiThreadTest, JSONDecodeRustCurrentSequence) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeatureWithParameters( + base::features::kUseRustJsonParser, + {{"UseRustJsonParserInCurrentSequence", "true"}}); + TestJSONDecode(); } } // namespace data_decoder
diff --git a/services/data_decoder/public/cpp/json_sanitizer_fuzztests.cc b/services/data_decoder/public/cpp/json_sanitizer_fuzztests.cc new file mode 100644 index 0000000..38163ce --- /dev/null +++ b/services/data_decoder/public/cpp/json_sanitizer_fuzztests.cc
@@ -0,0 +1,62 @@ +// Copyright 2025 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <mutex> +#include <optional> +#include <string> +#include <string_view> + +#include "base/check_op.h" +#include "base/command_line.h" +#include "base/json/json_reader.h" +#include "base/run_loop.h" +#include "base/test/bind.h" +#include "base/test/task_environment.h" +#include "base/test/test_timeouts.h" +#include "base/types/expected.h" +#include "base/values.h" +#include "build/buildflag.h" +#include "services/data_decoder/public/cpp/json_sanitizer.h" +#include "third_party/fuzztest/src/fuzztest/fuzztest.h" + +namespace data_decoder { +namespace { + +void SanitizerAndBaseJsonReaderDecoderMatch(std::string_view input) { + [[maybe_unused]] static bool initialized = [] { +#if BUILDFLAG(IS_WIN) + base::CommandLine::InitUsingArgvForTesting(0, nullptr); +#else + CHECK(base::CommandLine::Init(0, nullptr)); +#endif + TestTimeouts::Initialize(); + // Note that the documentation says not to call this in tests and to use + // base::test::ScopedCommandLine instead; however, that doesn't actually + // work until the current process's command line is first initialized at + // least once, which it never is in fuzz tests. + base::CommandLine::Reset(); + return true; + }(); + std::optional<base::Value> value = + base::JSONReader::Read(input, base::JSON_PARSE_RFC); + base::test::TaskEnvironment task_environment; + base::RunLoop loop; + JsonSanitizer::Result result; + JsonSanitizer::Sanitize(std::string(input), base::BindLambdaForTesting( + [&](JsonSanitizer::Result r) { + result = r; + loop.Quit(); + })); + loop.Run(); + // The JSON parser and the JSON sanitizer should agree on whether or not a + // given blob of JSON is valid. Additionally, the JSON sanitizer considers + // something to be invalid JSON if it does not decode to a dict or a list. + CHECK_EQ(value.has_value() && (value->is_dict() || value->is_list()), + result.has_value()); +} + +FUZZ_TEST(JsonSanitizerFuzzTest, SanitizerAndBaseJsonReaderDecoderMatch); + +} // namespace +} // namespace data_decoder
diff --git a/services/data_decoder/public/cpp/test_support/in_process_data_decoder.cc b/services/data_decoder/public/cpp/test_support/in_process_data_decoder.cc index 9ddde27..4ce31f3 100644 --- a/services/data_decoder/public/cpp/test_support/in_process_data_decoder.cc +++ b/services/data_decoder/public/cpp/test_support/in_process_data_decoder.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/features.h" #include "base/task/sequenced_task_runner.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" @@ -26,6 +27,12 @@ return nullptr; } +void InProcessDataDecoder::SimulateJsonParserCrash(bool drop) { + CHECK(!base::FeatureList::IsEnabled(base::features::kUseRustJsonParser)) + << "Rust JSON parser is in-process and cannot crash."; + drop_json_parsers_ = drop; +} + void InProcessDataDecoder::BindDataDecoderService( mojo::PendingReceiver<mojom::DataDecoderService> receiver) { if (!task_runner_->RunsTasksInCurrentSequence()) { @@ -61,7 +68,9 @@ void InProcessDataDecoder::BindJsonParser( mojo::PendingReceiver<mojom::JsonParser> receiver) { - GetForwardingInterface()->BindJsonParser(std::move(receiver)); + if (!drop_json_parsers_) { + GetForwardingInterface()->BindJsonParser(std::move(receiver)); + } } void InProcessDataDecoder::BindWebBundleParserFactory(
diff --git a/services/data_decoder/public/cpp/test_support/in_process_data_decoder.h b/services/data_decoder/public/cpp/test_support/in_process_data_decoder.h index 7169bad..87ebf4a6 100644 --- a/services/data_decoder/public/cpp/test_support/in_process_data_decoder.h +++ b/services/data_decoder/public/cpp/test_support/in_process_data_decoder.h
@@ -44,6 +44,9 @@ // them. Useful for tests simulating service failures. void SimulateImageDecoderCrash(bool drop) { drop_image_decoders_ = drop; } + // Same as above but for JsonParser receivers. + void SimulateJsonParserCrash(bool drop); + // Configures the service to use |binder| to bind // WebBundleParserFactory in subsequent // BindWebBundleParserFactory() calls. @@ -79,6 +82,7 @@ ::data_decoder::DataDecoderService service_; mojo::ReceiverSet<mojom::DataDecoderService> receivers_; bool drop_image_decoders_ = false; + bool drop_json_parsers_ = false; base::RepeatingCallback<void( mojo::PendingReceiver<web_package::mojom::WebBundleParserFactory>)> web_bundle_parser_factory_binder_;
diff --git a/services/screen_ai/public/mojom/screen_ai_factory.mojom b/services/screen_ai/public/mojom/screen_ai_factory.mojom index d214aed..7ff8de1 100644 --- a/services/screen_ai/public/mojom/screen_ai_factory.mojom +++ b/services/screen_ai/public/mojom/screen_ai_factory.mojom
@@ -60,7 +60,4 @@ // Sets the shutdown handler. BindShutdownHandler( pending_remote<ScreenAIServiceShutdownHandler> shutdown_handler); - - // Shuts down the service if there are no connected remotes. - ShutDownIfNoClients(); };
diff --git a/services/screen_ai/screen_ai_service_impl.cc b/services/screen_ai/screen_ai_service_impl.cc index 813993a5..68a53fbd 100644 --- a/services/screen_ai/screen_ai_service_impl.cc +++ b/services/screen_ai/screen_ai_service_impl.cc
@@ -53,7 +53,9 @@ constexpr int kMaxOcrDimension = 2048; // How often it would be checked that the service is idle and can be shutdown. +// LINT.IfChange(kIdleCheckingDelay) constexpr base::TimeDelta kIdleCheckingDelay = base::Seconds(3); +// LINT.ThenChange(//chrome/browser/screen_ai/optical_character_recognizer_browsertest.cc:kServiceIdleCheckingDelay) // How long to wait for a request to the library be responded, before assuming // that the library is not responsive. @@ -266,7 +268,7 @@ model_data_holder_ = std::make_unique<ModelDataHolder>(); idle_checking_timer_ = std::make_unique<base::RepeatingTimer>(); idle_checking_timer_->Start(FROM_HERE, kIdleCheckingDelay, this, - &ScreenAIService::ShutDownIfNoClients); + &ScreenAIService::ShutDownOnIdle); background_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner( {base::TaskPriority::BEST_EFFORT, @@ -666,18 +668,12 @@ return ComputeMainNode(tree, content_node_ids); } -void ScreenAIService::ShutDownIfNoClients() { +void ScreenAIService::ShutDownOnIdle() { const base::TimeTicks kIdlenessThreshold = base::TimeTicks::Now() - kIdleCheckingDelay; - bool ocr_not_needed = - !screen_ai_annotators_.size() || ocr_last_used_ < kIdlenessThreshold; - bool main_content_extractioncan_not_needed = - !screen2x_main_content_extractors_.size() || - mce_last_used_ < kIdlenessThreshold; - - if (ocr_not_needed && main_content_extractioncan_not_needed) { + if (ocr_last_used_ < kIdlenessThreshold && + mce_last_used_ < kIdlenessThreshold) { screen_ai_shutdown_handler_->ShuttingDownOnIdle(); - VLOG(2) << "Shutting down since no client or idle."; base::Process::TerminateCurrentProcessImmediately(0); } }
diff --git a/services/screen_ai/screen_ai_service_impl.h b/services/screen_ai/screen_ai_service_impl.h index c4a5a19..5be7a8c 100644 --- a/services/screen_ai/screen_ai_service_impl.h +++ b/services/screen_ai/screen_ai_service_impl.h
@@ -98,9 +98,6 @@ InitializeOCRCallback callback) override; // mojom::ScreenAIServiceFactory: - void ShutDownIfNoClients() override; - - // mojom::ScreenAIServiceFactory: void BindShutdownHandler( mojo::PendingRemote<mojom::ScreenAIServiceShutdownHandler> shutdown_handler) override; @@ -130,6 +127,8 @@ void OcrReceiverDisconnected(); void MceReceiverDisconnected(); + void ShutDownOnIdle(); + // Last time the feature is used. A null value means never, it is set when the // feature is initialized, and each time it is used. base::TimeTicks ocr_last_used_;
diff --git a/services/webnn/webnn_graph_builder_impl_unittest.cc b/services/webnn/webnn_graph_builder_impl_unittest.cc index 6e622f2..7b7293e 100644 --- a/services/webnn/webnn_graph_builder_impl_unittest.cc +++ b/services/webnn/webnn_graph_builder_impl_unittest.cc
@@ -17,6 +17,7 @@ #include "mojo/public/cpp/test_support/test_utils.h" #include "services/webnn/error.h" #include "services/webnn/public/cpp/operand_descriptor.h" +#include "services/webnn/public/cpp/webnn_types.h" #include "services/webnn/public/mojom/features.mojom-features.h" #include "services/webnn/public/mojom/webnn_tensor.mojom.h" #include "services/webnn/webnn_constant_operand.h" @@ -35,9 +36,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder>& graph_builder_remote) { // Build a simple graph. GraphInfoBuilder builder(graph_builder_remote); - uint64_t input_operand_id = builder.BuildInput("input", /*dimensions=*/{2, 3}, - OperandDataType::kFloat32); - uint64_t output_operand_id = builder.BuildOutput( + OperandId input_operand_id = builder.BuildInput( + "input", /*dimensions=*/{2, 3}, OperandDataType::kFloat32); + OperandId output_operand_id = builder.BuildOutput( "output", /*dimensions=*/{2, 3}, OperandDataType::kFloat32); builder.BuildClamp(input_operand_id, output_operand_id, /*min_value=*/0.0, /*max_value=*/1.0); @@ -89,7 +90,7 @@ mojo::PendingAssociatedReceiver<mojom::WebNNGraph> receiver, mojom::GraphInfoPtr graph_info, WebNNGraphImpl::ComputeResourceInfo compute_resource_info, - base::flat_map<uint64_t, std::unique_ptr<WebNNConstantOperand>> + base::flat_map<OperandId, std::unique_ptr<WebNNConstantOperand>> /*constant_operands*/, CreateGraphImplCallback callback) override { // Asynchronously resolve `callback` so there's an opportunity for @@ -233,10 +234,10 @@ const std::array<float, 6> kConstantData{3.0, 4.0, 5.0, 6.0, 7.0, 8.0}; GraphInfoBuilder builder(graph_builder_remote()); - uint64_t constant_operand_id = builder.BuildConstant( + OperandId constant_operand_id = builder.BuildConstant( /*dimensions=*/{2, 3}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, kConstantData)); - uint64_t output_operand_id = builder.BuildOutput( + OperandId output_operand_id = builder.BuildOutput( "output", /*dimensions=*/{2, 3}, OperandDataType::kFloat32); builder.BuildClamp(constant_operand_id, output_operand_id, /*min_value=*/5.0, /*max_value=*/7.0); @@ -315,10 +316,10 @@ base::checked_cast<uint32_t>(std::numeric_limits<int32_t>::max() / 4), 2}; GraphInfoBuilder builder(graph_builder_remote()); - uint64_t input_operand_id = builder.BuildInput("input", large_tensor_shape, - OperandDataType::kFloat32); - uint64_t output_operand_id = builder.BuildOutput("output", large_tensor_shape, - OperandDataType::kFloat32); + OperandId input_operand_id = builder.BuildInput("input", large_tensor_shape, + OperandDataType::kFloat32); + OperandId output_operand_id = builder.BuildOutput( + "output", large_tensor_shape, OperandDataType::kFloat32); builder.BuildClamp(input_operand_id, output_operand_id, /*min_value=*/0.0, /*max_value=*/1.0); EXPECT_FALSE(
diff --git a/services/webnn/webnn_graph_impl.cc b/services/webnn/webnn_graph_impl.cc index f28ae2e..3ba556a 100644 --- a/services/webnn/webnn_graph_impl.cc +++ b/services/webnn/webnn_graph_impl.cc
@@ -15,6 +15,7 @@ #include "base/types/pass_key.h" #include "services/webnn/error.h" #include "services/webnn/public/cpp/operand_descriptor.h" +#include "services/webnn/public/cpp/webnn_types.h" #include "services/webnn/webnn_context_impl.h" #include "services/webnn/webnn_tensor_impl.h" @@ -68,9 +69,9 @@ WebNNGraphImpl::ComputeResourceInfo::ComputeResourceInfo( base::flat_map<std::string, OperandDescriptor> input_names_to_descriptors, base::flat_map<std::string, OperandDescriptor> output_names_to_descriptors, - base::flat_map<uint64_t, base::flat_set<size_t>> + base::flat_map<OperandId, base::flat_set<OperationId>> operand_to_dependent_operations, - base::flat_map<uint64_t, size_t> operand_to_producing_operation, + base::flat_map<OperandId, OperationId> operand_to_producing_operation, base::PassKey<WebNNGraphBuilderImpl> pass_key) : input_names_to_descriptors(std::move(input_names_to_descriptors)), output_names_to_descriptors(std::move(output_names_to_descriptors)),
diff --git a/services/webnn/webnn_graph_impl.h b/services/webnn/webnn_graph_impl.h index 9e7d693..aff0840 100644 --- a/services/webnn/webnn_graph_impl.h +++ b/services/webnn/webnn_graph_impl.h
@@ -13,6 +13,7 @@ #include "mojo/public/cpp/bindings/associated_receiver.h" #include "mojo/public/cpp/bindings/pending_associated_receiver.h" #include "services/webnn/public/cpp/operand_descriptor.h" +#include "services/webnn/public/cpp/webnn_types.h" #include "services/webnn/public/mojom/webnn_graph.mojom.h" #include "services/webnn/webnn_object_impl.h" @@ -33,9 +34,9 @@ input_names_to_descriptors, base::flat_map<std::string, OperandDescriptor> output_names_to_descriptors, - base::flat_map<uint64_t, base::flat_set<size_t>> + base::flat_map<OperandId, base::flat_set<OperationId>> operand_to_dependent_operations, - base::flat_map<uint64_t, size_t> operand_to_producing_operation, + base::flat_map<OperandId, OperationId> operand_to_producing_operation, base::PassKey<WebNNGraphBuilderImpl> pass_key); ~ComputeResourceInfo(); @@ -47,9 +48,9 @@ base::flat_map<std::string, OperandDescriptor> input_names_to_descriptors; base::flat_map<std::string, OperandDescriptor> output_names_to_descriptors; - base::flat_map<uint64_t, base::flat_set<size_t>> + base::flat_map<OperandId, base::flat_set<OperationId>> operand_to_dependent_operations; - base::flat_map<uint64_t, size_t> operand_to_producing_operation; + base::flat_map<OperandId, OperationId> operand_to_producing_operation; }; // Constructs a graph where the receiever and implementation is owned by the
diff --git a/services/webnn/webnn_graph_impl_backend_test.cc b/services/webnn/webnn_graph_impl_backend_test.cc index e3a886e..8ddeb79 100644 --- a/services/webnn/webnn_graph_impl_backend_test.cc +++ b/services/webnn/webnn_graph_impl_backend_test.cc
@@ -27,6 +27,7 @@ #include "mojo/public/cpp/bindings/associated_remote.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/webnn/buildflags.h" +#include "services/webnn/public/cpp/webnn_types.h" #include "services/webnn/public/mojom/features.mojom-features.h" #include "services/webnn/public/mojom/webnn_context.mojom.h" #include "services/webnn/public/mojom/webnn_context_provider.mojom.h" @@ -129,7 +130,7 @@ named_input_remotes_and_handles; named_input_remotes_and_handles.reserve(graph_info->input_operands.size()); - for (uint64_t operand_id : graph_info->input_operands) { + for (OperandId operand_id : graph_info->input_operands) { const mojom::Operand& operand = *graph_info->id_to_operand_map.at(operand_id); EXPECT_TRUE(operand.name.has_value()); @@ -157,7 +158,7 @@ named_output_remotes_and_handles; named_output_remotes_and_handles.reserve(graph_info->output_operands.size()); - for (uint64_t operand_id : graph_info->output_operands) { + for (OperandId operand_id : graph_info->output_operands) { const mojom::Operand& operand = *graph_info->id_to_operand_map.at(operand_id); EXPECT_TRUE(operand.name.has_value()); @@ -509,8 +510,8 @@ void BuildFusibleOperation(GraphInfoBuilder& builder, const FusibleOperationDescriptor& operation, - uint64_t input_operand_id, - uint64_t output_operand_id) { + OperandId input_operand_id, + OperandId output_operand_id) { switch (operation.kind) { case mojom::Operation::Tag::kElu: { CHECK(operation.alpha.has_value()); @@ -566,8 +567,8 @@ std::optional<OperandInfo<T>> scale; std::optional<OperandInfo<T>> bias; struct BatchNormalizationAttributes { - std::optional<uint64_t> scale_operand_id; - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> scale_operand_id; + std::optional<OperandId> bias_operand_id; uint32_t axis = 1; float epsilon = 1e-5; }; @@ -581,13 +582,13 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t mean_operand_id = + OperandId mean_operand_id = builder.BuildInput("mean", mean.dimensions, mean.type); - uint64_t variance_operand_id = + OperandId variance_operand_id = builder.BuildInput("variance", variance.dimensions, variance.type); - uint64_t intermediate_operand_id = + OperandId intermediate_operand_id = builder.BuildIntermediateOperand(output.dimensions, output.type); if (scale.has_value()) { attributes.scale_operand_id = @@ -602,7 +603,7 @@ input_operand_id, mean_operand_id, variance_operand_id, intermediate_operand_id, std::move(attributes)); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); BuildFusibleOperation(builder, fusible_operation, intermediate_operand_id, output_operand_id); @@ -785,15 +786,15 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t filter_operand_id = builder.BuildConstant( + OperandId filter_operand_id = builder.BuildConstant( filter.dimensions, filter.type, base::as_byte_span(base::allow_nonunique_obj, filter.values)); - uint64_t conv2d_output_operand_id = + OperandId conv2d_output_operand_id = builder.BuildIntermediateOperand(output.dimensions, output.type); - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> bias_operand_id; if (attributes.bias.has_value()) { bias_operand_id = builder.BuildConstant( attributes.bias->dimensions, attributes.bias->type, @@ -805,7 +806,7 @@ conv2d_output_operand_id, std::move(attributes), bias_operand_id); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); BuildFusibleOperation(builder, fusible_operation, conv2d_output_operand_id, output_operand_id); @@ -1049,9 +1050,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = helper.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t lhs_operand_id = + OperandId lhs_operand_id = builder.BuildInput("lhs", lhs.dimensions, lhs.type); - uint64_t rhs_operand_id = + OperandId rhs_operand_id = builder.BuildInput("rhs", rhs.dimensions, rhs.type); auto graph_output_type = output.type; #if BUILDFLAG(IS_MAC) @@ -1062,9 +1063,9 @@ graph_output_type = OperandDataType::kInt32; } #endif // BUILDFLAG(IS_MAC) - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, graph_output_type); - uint64_t element_wise_binary_output_operand_id = output_operand_id; + OperandId element_wise_binary_output_operand_id = output_operand_id; #if BUILDFLAG(IS_MAC) if (output.type == OperandDataType::kUint8) { element_wise_binary_output_operand_id = builder.BuildIntermediateOperand( @@ -1107,17 +1108,17 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t lhs_operand_id = + OperandId lhs_operand_id = builder.BuildInput("lhs", lhs.dimensions, lhs.type); - uint64_t rhs_operand_id = + OperandId rhs_operand_id = builder.BuildInput("rhs", rhs.dimensions, rhs.type); - uint64_t intermediate_operand_id = + OperandId intermediate_operand_id = builder.BuildIntermediateOperand(output.dimensions, output.type); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kAdd, lhs_operand_id, rhs_operand_id, intermediate_operand_id); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); BuildFusibleOperation(builder, fusible_operation, intermediate_operand_id, output_operand_id); @@ -1185,16 +1186,16 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 5}, OperandDataType::kFloat32); - uint64_t output1_operand_id = + OperandId output1_operand_id = builder.BuildOutput("output1", {2, 2}, OperandDataType::kFloat32); - uint64_t split_operand_id = + OperandId split_operand_id = builder.BuildIntermediateOperand({2, 3}, OperandDataType::kFloat32); builder.BuildSplit(input_operand_id, {output1_operand_id, split_operand_id}, 1); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output2", {3, 2}, OperandDataType::kFloat32); builder.BuildReshape(split_operand_id, output_operand_id); @@ -1236,9 +1237,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); switch (tag) { case mojom::Operation::Tag::kClamp: @@ -1376,12 +1377,12 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t relu1_output_id = + OperandId relu1_output_id = builder.BuildIntermediateOperand({1, 2, 3, 4}, OperandDataType::kFloat32); builder.BuildRelu(input_operand_id, relu1_output_id); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 2, 3, 4}, OperandDataType::kFloat32); builder.BuildRelu(relu1_output_id, output_operand_id); @@ -1411,12 +1412,12 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t relu_output_id = + OperandId relu_output_id = builder.BuildIntermediateOperand({1, 2, 3, 4}, OperandDataType::kFloat32); builder.BuildRelu(input_operand_id, relu_output_id); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 1, 6, 4}, OperandDataType::kFloat32); builder.BuildReshape(relu_output_id, output_operand_id); @@ -1445,12 +1446,12 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t reshape_output_id = + OperandId reshape_output_id = builder.BuildIntermediateOperand({1, 1, 6, 4}, OperandDataType::kFloat32); builder.BuildReshape(input_operand_id, reshape_output_id); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 1, 6, 4}, OperandDataType::kFloat32); builder.BuildRelu(reshape_output_id, output_operand_id); @@ -1477,12 +1478,12 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t reshape_output_id = + OperandId reshape_output_id = builder.BuildIntermediateOperand({1, 1, 6, 4}, OperandDataType::kFloat32); builder.BuildReshape(input_operand_id, reshape_output_id); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 2, 3, 4}, OperandDataType::kFloat32); builder.BuildReshape(reshape_output_id, output_operand_id); @@ -1509,12 +1510,12 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t output1_operand_id = + OperandId output1_operand_id = builder.BuildOutput("output1", {1, 1, 6, 4}, OperandDataType::kFloat32); builder.BuildReshape(input_operand_id, output1_operand_id); - uint64_t output2_operand_id = + OperandId output2_operand_id = builder.BuildOutput("output2", {1, 2, 3, 4}, OperandDataType::kFloat32); builder.BuildRelu(input_operand_id, output2_operand_id); @@ -1536,7 +1537,7 @@ } struct GemmAttributes { - std::optional<uint64_t> c_operand_id; + std::optional<OperandId> c_operand_id; // TODO(crbug.com/40206287): Add test cases for below attributes. float alpha = 1.0; float beta = 1.0; @@ -1559,11 +1560,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", input_a.dimensions, input_a.type); - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", input_b.dimensions, input_b.type); - uint64_t intermediate_operand_id = + OperandId intermediate_operand_id = builder.BuildIntermediateOperand(output.dimensions, output.type); if (input_c.has_value()) { attributes.c_operand_id = @@ -1573,7 +1574,7 @@ builder.BuildGemm(input_a_operand_id, input_b_operand_id, intermediate_operand_id, std::move(attributes)); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); BuildFusibleOperation(builder, fusible_operation, intermediate_operand_id, output_operand_id); @@ -1635,9 +1636,9 @@ template <typename T> struct GruTester { struct GruAttributes { - std::optional<uint64_t> bias_operand_id; - std::optional<uint64_t> recurrent_bias_operand_id; - std::optional<uint64_t> initial_hidden_state_operand_id; + std::optional<OperandId> bias_operand_id; + std::optional<OperandId> recurrent_bias_operand_id; + std::optional<OperandId> initial_hidden_state_operand_id; bool reset_after = true; bool return_sequence = false; mojom::RecurrentNetworkDirection direction = @@ -1666,11 +1667,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = helper.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t weight_operand_id = + OperandId weight_operand_id = builder.BuildInput("weight", weight.dimensions, weight.type); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", recurrent_weight.dimensions, recurrent_weight.type); if (bias.has_value()) { @@ -1688,7 +1689,7 @@ initial_hidden_state->values)); } - std::vector<uint64_t> output_operand_ids; + std::vector<OperandId> output_operand_ids; output_operand_ids.reserve(outputs.size()); for (size_t i = 0; i < outputs.size(); ++i) { const auto& output = outputs[i]; @@ -1981,8 +1982,8 @@ template <typename T> struct GruCellTester { struct GruCellAttributes { - std::optional<uint64_t> bias_operand_id; - std::optional<uint64_t> recurrent_bias_operand_id; + std::optional<OperandId> bias_operand_id; + std::optional<OperandId> recurrent_bias_operand_id; bool reset_after = true; mojom::GruWeightLayout layout = mojom::GruWeightLayout::kZrn; std::vector<mojom::RecurrentNetworkActivation> activations{ @@ -2007,13 +2008,13 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = helper.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t weight_operand_id = + OperandId weight_operand_id = builder.BuildInput("weight", weight.dimensions, weight.type); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", recurrent_weight.dimensions, recurrent_weight.type); - uint64_t hidden_state_operand_id = builder.BuildInput( + OperandId hidden_state_operand_id = builder.BuildInput( "hiddenState", hidden_state.dimensions, hidden_state.type); if (bias.has_value()) { @@ -2025,7 +2026,7 @@ "recurrentBias", recurrent_bias->dimensions, recurrent_bias->type); } - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildGruCell(input_operand_id, weight_operand_id, @@ -2139,19 +2140,19 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {2, 2}, OperandDataType::kFloat32); - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", {2, 2}, OperandDataType::kFloat32); - uint64_t intermediate_1_operand_id = + OperandId intermediate_1_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(input_a_operand_id, input_b_operand_id, intermediate_1_operand_id, GemmAttributes()); - uint64_t intermediate_2_operand_id = + OperandId intermediate_2_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(input_a_operand_id, input_b_operand_id, intermediate_2_operand_id, GemmAttributes()); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kFloat32); builder.BuildGemm(intermediate_1_operand_id, intermediate_2_operand_id, output_operand_id, GemmAttributes()); @@ -2175,12 +2176,12 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {2, 2}, OperandDataType::kFloat32); - uint64_t input_b_operand_id = builder.BuildConstant( + OperandId input_b_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kFloat32); builder.BuildGemm(input_a_operand_id, input_b_operand_id, output_operand_id, GemmAttributes()); @@ -2201,8 +2202,8 @@ std::optional<OperandInfo<T>> scale; std::optional<OperandInfo<T>> bias; struct InstanceNormalizationAttributes { - std::optional<uint64_t> scale_operand_id; - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> scale_operand_id; + std::optional<OperandId> bias_operand_id; float epsilon = 1e-5; }; InstanceNormalizationAttributes attributes; @@ -2215,9 +2216,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t intermediate_operand_id = + OperandId intermediate_operand_id = builder.BuildIntermediateOperand(output.dimensions, output.type); if (scale.has_value()) { attributes.scale_operand_id = @@ -2231,7 +2232,7 @@ builder.BuildInstanceNormalization( input_operand_id, intermediate_operand_id, std::move(attributes)); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); BuildFusibleOperation(builder, fusible_operation, intermediate_operand_id, output_operand_id); @@ -2278,8 +2279,8 @@ std::optional<OperandInfo<T>> scale; std::optional<OperandInfo<T>> bias; struct LayerNormalizationAttributes { - std::optional<uint64_t> scale_operand_id; - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> scale_operand_id; + std::optional<OperandId> bias_operand_id; std::vector<uint32_t> axes; float epsilon = 1e-5; }; @@ -2293,9 +2294,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); if (scale.has_value()) { attributes.scale_operand_id = @@ -2333,9 +2334,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t intermediate_operand_id = + OperandId intermediate_operand_id = builder.BuildIntermediateOperand(output.dimensions, output.type); if (scale.has_value()) { attributes.scale_operand_id = @@ -2349,7 +2350,7 @@ builder.BuildLayerNormalization(input_operand_id, intermediate_operand_id, std::move(attributes)); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); BuildFusibleOperation(builder, fusible_operation, intermediate_operand_id, output_operand_id); @@ -2442,11 +2443,11 @@ std::optional<OperandInfo<T>> initial_hidden_state; std::optional<OperandInfo<T>> initial_cell_state; struct LstmAttributes { - std::optional<uint64_t> bias_operand_id; - std::optional<uint64_t> recurrent_bias_operand_id; - std::optional<uint64_t> peephole_weight_operand_id; - std::optional<uint64_t> initial_hidden_state_operand_id; - std::optional<uint64_t> initial_cell_state_operand_id; + std::optional<OperandId> bias_operand_id; + std::optional<OperandId> recurrent_bias_operand_id; + std::optional<OperandId> peephole_weight_operand_id; + std::optional<OperandId> initial_hidden_state_operand_id; + std::optional<OperandId> initial_cell_state_operand_id; bool return_sequence = false; mojom::RecurrentNetworkDirection direction = mojom::RecurrentNetworkDirection::kForward; @@ -2466,11 +2467,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = helper.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t weight_operand_id = + OperandId weight_operand_id = builder.BuildInput("weight", weight.dimensions, weight.type); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", recurrent_weight.dimensions, recurrent_weight.type); if (bias.has_value()) { @@ -2496,7 +2497,7 @@ initial_cell_state->type); } - std::vector<uint64_t> output_operand_ids; + std::vector<OperandId> output_operand_ids; output_operand_ids.reserve(outputs.size()); for (size_t i = 0; i < outputs.size(); ++i) { const auto& output = outputs[i]; @@ -2646,14 +2647,14 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = builder.BuildConstant( + OperandId input_operand_id = builder.BuildConstant( {steps, batch_size, input_size}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, input_data)); - uint64_t weight_operand_id = builder.BuildConstant( + OperandId weight_operand_id = builder.BuildConstant( {direction_count, 4 * hidden_size, input_size}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, weight_data)); - uint64_t recurrent_weight_operand_id = builder.BuildConstant( + OperandId recurrent_weight_operand_id = builder.BuildConstant( {direction_count, 4 * hidden_size, hidden_size}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, recurrent_weight_data)); @@ -2673,14 +2674,14 @@ mojom::RecurrentNetworkActivation::kRelu, mojom::RecurrentNetworkActivation::kRelu}; - uint64_t output_a_operand_id = builder.BuildOutput( + OperandId output_a_operand_id = builder.BuildOutput( "output0", {direction_count, batch_size, hidden_size}, OperandDataType::kFloat32); - uint64_t output_b_operand_id = builder.BuildOutput( + OperandId output_b_operand_id = builder.BuildOutput( "output1", {direction_count, batch_size, hidden_size}, OperandDataType::kFloat32); - std::vector<uint64_t> output_operand_ids{output_a_operand_id, - output_b_operand_id}; + std::vector<OperandId> output_operand_ids{output_a_operand_id, + output_b_operand_id}; builder.BuildLstm(input_operand_id, weight_operand_id, recurrent_weight_operand_id, std::move(output_operand_ids), steps, hidden_size, @@ -2698,9 +2699,9 @@ } struct LstmCellAttributes { - std::optional<uint64_t> bias_operand_id; - std::optional<uint64_t> recurrent_bias_operand_id; - std::optional<uint64_t> peephole_weight_operand_id; + std::optional<OperandId> bias_operand_id; + std::optional<OperandId> recurrent_bias_operand_id; + std::optional<OperandId> peephole_weight_operand_id; mojom::LstmWeightLayout layout = mojom::LstmWeightLayout::kIofg; std::vector<mojom::RecurrentNetworkActivation> activations = { mojom::RecurrentNetworkActivation::kSigmoid, @@ -2726,16 +2727,16 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = builder.BuildInput( + OperandId input_operand_id = builder.BuildInput( "input", {batch_size, input_size}, OperandDataType::kFloat32); - uint64_t weight_operand_id = builder.BuildInput( + OperandId weight_operand_id = builder.BuildInput( "weight", {4 * hidden_size, input_size}, OperandDataType::kFloat32); - uint64_t recurrent_weight_operand_id = + OperandId recurrent_weight_operand_id = builder.BuildInput("recurrentWeight", {4 * hidden_size, hidden_size}, OperandDataType::kFloat32); - uint64_t hidden_state_operand_id = builder.BuildInput( + OperandId hidden_state_operand_id = builder.BuildInput( "hiddenState", {batch_size, hidden_size}, OperandDataType::kFloat32); - uint64_t cell_state_operand_id = builder.BuildInput( + OperandId cell_state_operand_id = builder.BuildInput( "cellState", {batch_size, hidden_size}, OperandDataType::kFloat32); LstmCellAttributes attributes; @@ -2743,12 +2744,12 @@ mojom::RecurrentNetworkActivation::kRelu, mojom::RecurrentNetworkActivation::kRelu}; - uint64_t output_a_operand_id = builder.BuildOutput( + OperandId output_a_operand_id = builder.BuildOutput( "output0", {batch_size, hidden_size}, OperandDataType::kFloat32); - uint64_t output_b_operand_id = builder.BuildOutput( + OperandId output_b_operand_id = builder.BuildOutput( "output1", {batch_size, hidden_size}, OperandDataType::kFloat32); - std::vector<uint64_t> output_operand_ids{output_a_operand_id, - output_b_operand_id}; + std::vector<OperandId> output_operand_ids{output_a_operand_id, + output_b_operand_id}; builder.BuildLstmCell(input_operand_id, weight_operand_id, recurrent_weight_operand_id, hidden_state_operand_id, cell_state_operand_id, std::move(output_operand_ids), @@ -2784,30 +2785,30 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", input_a.dimensions, input_a.type); if (permutation_a) { std::vector<uint32_t> transposed_input_a_shape = PermuteArray(input_a.dimensions, permutation_a.value()); - uint64_t transposed_input_a_id = builder.BuildIntermediateOperand( + OperandId transposed_input_a_id = builder.BuildIntermediateOperand( transposed_input_a_shape, input_a.type); builder.BuildTranspose(input_a_operand_id, transposed_input_a_id, permutation_a.value()); input_a_operand_id = transposed_input_a_id; } - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", input_b.dimensions, input_b.type); if (permutation_b) { std::vector<uint32_t> transposed_input_b_shape = PermuteArray(input_b.dimensions, permutation_b.value()); - uint64_t transposed_input_b_id = builder.BuildIntermediateOperand( + OperandId transposed_input_b_id = builder.BuildIntermediateOperand( transposed_input_b_shape, input_b.type); builder.BuildTranspose(input_b_operand_id, transposed_input_b_id, permutation_b.value()); input_b_operand_id = transposed_input_b_id; } - uint64_t output_operand_id; + OperandId output_operand_id; if (fusible_operation) { output_operand_id = builder.BuildIntermediateOperand(output.dimensions, output.type); @@ -2820,7 +2821,7 @@ output_operand_id); if (fusible_operation) { - uint64_t intermediate_operand_id = output_operand_id; + OperandId intermediate_operand_id = output_operand_id; output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); BuildFusibleOperation(builder, fusible_operation.value(), @@ -2964,28 +2965,28 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {2, 2}, OperandDataType::kFloat32); - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", {2, 2}, OperandDataType::kFloat32); std::vector<float> constant_data = {1, 1, 1, 1}; - uint64_t constant_a_operand_id = builder.BuildConstant( + OperandId constant_a_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); - uint64_t constant_b_operand_id = builder.BuildConstant( + OperandId constant_b_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); // The order of inputs are [input_a, constant_a, input_b, constant_b]. - uint64_t intermediate_1_operand_id = + OperandId intermediate_1_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(input_a_operand_id, constant_a_operand_id, intermediate_1_operand_id, GemmAttributes()); - uint64_t intermediate_2_operand_id = + OperandId intermediate_2_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(input_b_operand_id, constant_b_operand_id, intermediate_2_operand_id, GemmAttributes()); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kFloat32); builder.BuildGemm(intermediate_1_operand_id, intermediate_2_operand_id, output_operand_id, GemmAttributes()); @@ -3013,28 +3014,28 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {2, 2}, OperandDataType::kFloat32); - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", {2, 2}, OperandDataType::kFloat32); std::vector<float> constant_data = {1, 2, 3, 4}; - uint64_t constant_a_operand_id = builder.BuildConstant( + OperandId constant_a_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); - uint64_t constant_b_operand_id = builder.BuildConstant( + OperandId constant_b_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); // The order of inputs are [constant_a, input_a, constant_b, input_b]. - uint64_t intermediate_1_operand_id = + OperandId intermediate_1_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(constant_a_operand_id, input_a_operand_id, intermediate_1_operand_id, GemmAttributes()); - uint64_t intermediate_2_operand_id = + OperandId intermediate_2_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(constant_b_operand_id, input_b_operand_id, intermediate_2_operand_id, GemmAttributes()); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kFloat32); builder.BuildGemm(intermediate_1_operand_id, intermediate_2_operand_id, output_operand_id, GemmAttributes()); @@ -3065,21 +3066,21 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {2, 2}, OperandDataType::kFloat32); - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", {2, 2}, OperandDataType::kFloat32); std::vector<float> constant_data = {1, 1}; - uint64_t constant_c_operand_id = builder.BuildConstant( + OperandId constant_c_operand_id = builder.BuildConstant( {2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); // Reshape constant_c from [2] to [1, 2] and use it as operand c for gemm. - uint64_t reshape_operand_id = + OperandId reshape_operand_id = builder.BuildIntermediateOperand({1, 2}, OperandDataType::kFloat32); builder.BuildReshape(constant_c_operand_id, reshape_operand_id); GemmAttributes gemm_attributes; gemm_attributes.c_operand_id = reshape_operand_id; - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kFloat32); builder.BuildGemm(input_a_operand_id, input_b_operand_id, output_operand_id, gemm_attributes); @@ -3107,17 +3108,17 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {1, 1, 2, 2}, OperandDataType::kFloat32); std::vector<float> constant_data = {1, 1}; - uint64_t constant_b_operand_id = builder.BuildConstant( + OperandId constant_b_operand_id = builder.BuildConstant( {2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); // Reshape constant_b from [2] to [1, 2] and use it as operand b for add. - uint64_t reshape_operand_id = + OperandId reshape_operand_id = builder.BuildIntermediateOperand({1, 2}, OperandDataType::kFloat32); builder.BuildReshape(constant_b_operand_id, reshape_operand_id); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kAdd, input_a_operand_id, reshape_operand_id, @@ -3143,10 +3144,10 @@ BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); std::vector<float> constant_data = {-1, 0, 1}; - uint64_t constant_operand_id = builder.BuildConstant( + OperandId constant_operand_id = builder.BuildConstant( {3}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {3}, OperandDataType::kFloat32); builder.BuildRelu(constant_operand_id, output_operand_id); @@ -3168,14 +3169,14 @@ BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); std::vector<float> constant_a_data = {1, 1, 1, 1}; - uint64_t constant_a_operand_id = builder.BuildConstant( + OperandId constant_a_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_a_data)); std::vector<float> constant_b_data = {2, 2, 2, 2}; - uint64_t constant_b_operand_id = builder.BuildConstant( + OperandId constant_b_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_b_data)); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kFloat32); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kAdd, constant_a_operand_id, constant_b_operand_id, @@ -3202,23 +3203,23 @@ BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); std::vector<float> constant_a_data = {1, 1, 1, 1}; - uint64_t constant_a_operand_id = builder.BuildConstant( + OperandId constant_a_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_a_data)); std::vector<float> constant_b_data = {2, 2, 2, 2}; - uint64_t constant_b_operand_id = builder.BuildConstant( + OperandId constant_b_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_b_data)); - uint64_t intermediate_operand_id = + OperandId intermediate_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kAdd, constant_a_operand_id, constant_b_operand_id, intermediate_operand_id); std::vector<float> constant_c_data = {3, 3, 3, 3}; - uint64_t constant_c_operand_id = builder.BuildConstant( + OperandId constant_c_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_c_data)); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kFloat32); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kMul, intermediate_operand_id, constant_c_operand_id, @@ -3251,23 +3252,23 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {1, 1, 2, 2}, OperandDataType::kFloat32); - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", {1, 1, 2, 2}, OperandDataType::kFloat32); - uint64_t intermediate_1_operand_id = + OperandId intermediate_1_operand_id = builder.BuildIntermediateOperand({1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kAdd, input_a_operand_id, input_b_operand_id, intermediate_1_operand_id); // Relu. - uint64_t intermediate_2_operand_id = + OperandId intermediate_2_operand_id = builder.BuildIntermediateOperand({1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildRelu(intermediate_1_operand_id, intermediate_2_operand_id); // Max pooling. - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildPool2d(mojom::Pool2d::Kind::kMaxPool2d, intermediate_2_operand_id, output_operand_id, @@ -3299,18 +3300,18 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {1, 1, 2, 2}, OperandDataType::kFloat32); - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", {1, 1, 2, 2}, OperandDataType::kFloat32); - uint64_t intermediate_1_operand_id = + OperandId intermediate_1_operand_id = builder.BuildIntermediateOperand({1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kAdd, input_a_operand_id, input_b_operand_id, intermediate_1_operand_id); // Max pooling. - uint64_t intermediate_2_operand_id = + OperandId intermediate_2_operand_id = builder.BuildIntermediateOperand({1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildPool2d(mojom::Pool2d::Kind::kMaxPool2d, intermediate_1_operand_id, intermediate_2_operand_id, @@ -3320,7 +3321,7 @@ .dilations = {1, 1}}); // Relu. - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildRelu(intermediate_2_operand_id, output_operand_id); @@ -3348,9 +3349,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {1, 1, 2, 2}, OperandDataType::kFloat32); - uint64_t intermediate_1_operand_id = + OperandId intermediate_1_operand_id = builder.BuildIntermediateOperand({1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildPool2d(mojom::Pool2d::Kind::kMaxPool2d, input_a_operand_id, intermediate_1_operand_id, @@ -3360,16 +3361,16 @@ .dilations = {1, 1}}); // Add operation. - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", {1, 1, 2, 2}, OperandDataType::kFloat32); - uint64_t intermediate_2_operand_id = + OperandId intermediate_2_operand_id = builder.BuildIntermediateOperand({1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kAdd, intermediate_1_operand_id, input_b_operand_id, intermediate_2_operand_id); // Relu. - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 1, 2, 2}, OperandDataType::kFloat32); builder.BuildRelu(intermediate_2_operand_id, output_operand_id); @@ -3397,21 +3398,21 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id1 = + OperandId input_operand_id1 = builder.BuildInput("input_a", {4, 3}, OperandDataType::kFloat16); - uint64_t input_operand_id2 = + OperandId input_operand_id2 = builder.BuildInput("input_b", {1, 1, 2, 3}, OperandDataType::kFloat16); - uint64_t reshape_operand_id = + OperandId reshape_operand_id = builder.BuildIntermediateOperand({1, 2, 2, 3}, OperandDataType::kFloat16); builder.BuildReshape(input_operand_id1, reshape_operand_id); - uint64_t concat_operand_id = + OperandId concat_operand_id = builder.BuildIntermediateOperand({1, 3, 2, 3}, OperandDataType::kFloat16); builder.BuildConcat({reshape_operand_id, input_operand_id2}, concat_operand_id, 1); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 3, 2, 3}, OperandDataType::kFloat16); builder.BuildClamp(concat_operand_id, output_operand_id, 1.25, 8.75); @@ -3458,28 +3459,28 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 1, 3}, OperandDataType::kFloat32); // [[[[1 2 3]]]] with shape (1, 1, 1, 3) std::vector<float> constant_data_a = {1, 2, 3}; - uint64_t constant_a_operand_id = builder.BuildConstant( + OperandId constant_a_operand_id = builder.BuildConstant( {1, 1, 1, 3}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data_a)); // [[[[-1 -2 -3] // [-4 -5 -6]]]] with shape (1, 1, 2, 3) std::vector<float> constant_data_b = {-1, -2, -3, -4, -5, -6}; - uint64_t constant_b_operand_id = builder.BuildConstant( + OperandId constant_b_operand_id = builder.BuildConstant( {1, 1, 2, 3}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data_b)); - uint64_t concat_operand_id = + OperandId concat_operand_id = builder.BuildIntermediateOperand({1, 1, 2, 3}, OperandDataType::kFloat32); builder.BuildConcat({input_operand_id, constant_a_operand_id}, concat_operand_id, 2); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {1, 2, 2, 3}, OperandDataType::kFloat32); builder.BuildConcat({concat_operand_id, constant_b_operand_id}, output_operand_id, 1); @@ -3517,9 +3518,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildResample2d(input_operand_id, output_operand_id, attributes); @@ -3577,14 +3578,14 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t transpose_operand_id = + OperandId transpose_operand_id = builder.BuildIntermediateOperand({2, 1, 3, 4}, OperandDataType::kFloat32); builder.BuildTranspose(input_operand_id, transpose_operand_id, {1, 0, 2, 3}); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {4, 3, 1, 2}, OperandDataType::kFloat32); builder.BuildTranspose(transpose_operand_id, output_operand_id, {3, 2, 1, 0}); @@ -3631,14 +3632,14 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t transpose_operand_id = + OperandId transpose_operand_id = builder.BuildIntermediateOperand({4, 3, 1, 2}, OperandDataType::kFloat32); builder.BuildTranspose(input_operand_id, transpose_operand_id, {3, 2, 0, 1}); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {4, 3, 1, 2}, OperandDataType::kFloat32); builder.BuildRelu(transpose_operand_id, output_operand_id); @@ -3689,22 +3690,22 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t transpose_operand_id = + OperandId transpose_operand_id = builder.BuildIntermediateOperand({4, 3, 1, 2}, OperandDataType::kFloat32); builder.BuildTranspose(input_operand_id, transpose_operand_id, {3, 2, 0, 1}); - uint64_t reshape_operand_id1 = + OperandId reshape_operand_id1 = builder.BuildIntermediateOperand({2, 2, 6}, OperandDataType::kFloat32); builder.BuildReshape(transpose_operand_id, reshape_operand_id1); - uint64_t reshape_operand_id2 = + OperandId reshape_operand_id2 = builder.BuildIntermediateOperand({12, 2}, OperandDataType::kFloat32); builder.BuildReshape(reshape_operand_id1, reshape_operand_id2); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 12}, OperandDataType::kFloat32); builder.BuildTranspose(reshape_operand_id2, output_operand_id, {1, 0}); @@ -3744,15 +3745,15 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 2}, OperandDataType::kFloat32); - uint64_t relu_operand_id = + OperandId relu_operand_id = builder.BuildIntermediateOperand({1, 2, 3, 2}, OperandDataType::kFloat32); builder.BuildRelu(input_operand_id, relu_operand_id); - uint64_t output1_operand_id = + OperandId output1_operand_id = builder.BuildOutput("output1", {3, 4}, OperandDataType::kFloat32); - uint64_t output2_operand_id = + OperandId output2_operand_id = builder.BuildOutput("output2", {1, 2, 2, 3}, OperandDataType::kFloat32); builder.BuildReshape(relu_operand_id, output1_operand_id); builder.BuildTranspose(relu_operand_id, output2_operand_id, {0, 3, 1, 2}); @@ -3799,14 +3800,14 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 5, 5}, OperandDataType::kFloat32); - uint64_t filter_operand_id = builder.BuildConstant( + OperandId filter_operand_id = builder.BuildConstant( {1, 1, 3, 3}, OperandDataType::kFloat32, base::as_byte_span( base::allow_nonunique_obj, {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f})); - uint64_t conv2d_output_operand_id = builder.BuildIntermediateOperand( + OperandId conv2d_output_operand_id = builder.BuildIntermediateOperand( {1, 1, 5, 5}, OperandDataType::kFloat32); Conv2dTester<float>::Conv2dAttributes attributes{ @@ -3816,7 +3817,7 @@ .values = {-100}}, }; - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> bias_operand_id; if (attributes.bias.has_value()) { bias_operand_id = builder.BuildConstant( attributes.bias->dimensions, attributes.bias->type, @@ -3828,11 +3829,11 @@ filter_operand_id, conv2d_output_operand_id, std::move(attributes), bias_operand_id); - uint64_t relu1_output_operand_id = + OperandId relu1_output_operand_id = builder.BuildOutput("output1", {1, 1, 5, 5}, OperandDataType::kFloat32); builder.BuildRelu(conv2d_output_operand_id, relu1_output_operand_id); - uint64_t relu2_output_operand_id = + OperandId relu2_output_operand_id = builder.BuildOutput("output2", {1, 1, 5, 5}, OperandDataType::kFloat32); builder.BuildRelu(conv2d_output_operand_id, relu2_output_operand_id); @@ -3864,14 +3865,14 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 5, 5}, OperandDataType::kFloat32); - uint64_t filter_operand_id = builder.BuildConstant( + OperandId filter_operand_id = builder.BuildConstant( {1, 1, 3, 3}, OperandDataType::kFloat32, base::as_byte_span( base::allow_nonunique_obj, {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f})); - uint64_t conv2d_output_operand_id = builder.BuildIntermediateOperand( + OperandId conv2d_output_operand_id = builder.BuildIntermediateOperand( {1, 1, 5, 5}, OperandDataType::kFloat32); Conv2dTester<float>::Conv2dAttributes attributes{ @@ -3881,7 +3882,7 @@ .values = {-100}}, }; - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> bias_operand_id; if (attributes.bias.has_value()) { bias_operand_id = builder.BuildConstant( attributes.bias->dimensions, attributes.bias->type, @@ -3893,11 +3894,11 @@ filter_operand_id, conv2d_output_operand_id, std::move(attributes), bias_operand_id); - uint64_t reshape_output_operand_id = + OperandId reshape_output_operand_id = builder.BuildOutput("output1", {1, 5, 1, 5}, OperandDataType::kFloat32); builder.BuildReshape(conv2d_output_operand_id, reshape_output_operand_id); - uint64_t relu_output_operand_id = + OperandId relu_output_operand_id = builder.BuildOutput("output2", {1, 1, 5, 5}, OperandDataType::kFloat32); builder.BuildRelu(conv2d_output_operand_id, relu_output_operand_id); @@ -3931,14 +3932,14 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 5, 5}, OperandDataType::kFloat32); - uint64_t filter_operand_id = builder.BuildConstant( + OperandId filter_operand_id = builder.BuildConstant( {1, 1, 3, 3}, OperandDataType::kFloat32, base::as_byte_span( base::allow_nonunique_obj, {1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f})); - uint64_t conv2d_output_operand_id = builder.BuildIntermediateOperand( + OperandId conv2d_output_operand_id = builder.BuildIntermediateOperand( {1, 1, 5, 5}, OperandDataType::kFloat32); Conv2dTester<float>::Conv2dAttributes attributes{ @@ -3948,7 +3949,7 @@ .values = {-100}}, }; - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> bias_operand_id; if (attributes.bias.has_value()) { bias_operand_id = builder.BuildConstant( attributes.bias->dimensions, attributes.bias->type, @@ -3961,7 +3962,7 @@ std::move(attributes), bias_operand_id); builder.AddOutput("output2", conv2d_output_operand_id); - uint64_t relu_output_operand_id = + OperandId relu_output_operand_id = builder.BuildOutput("output1", {1, 1, 5, 5}, OperandDataType::kFloat32); builder.BuildRelu(conv2d_output_operand_id, relu_output_operand_id);
diff --git a/services/webnn/webnn_graph_impl_unittest.cc b/services/webnn/webnn_graph_impl_unittest.cc index 14d11b1d..f140df17 100644 --- a/services/webnn/webnn_graph_impl_unittest.cc +++ b/services/webnn/webnn_graph_impl_unittest.cc
@@ -27,6 +27,7 @@ #include "services/webnn/public/cpp/operand_descriptor.h" #include "services/webnn/public/cpp/supported_data_types.h" #include "services/webnn/public/cpp/webnn_errors.h" +#include "services/webnn/public/cpp/webnn_types.h" #include "services/webnn/public/mojom/features.mojom-features.h" #include "services/webnn/public/mojom/webnn_context_provider.mojom.h" #include "services/webnn/public/mojom/webnn_graph.mojom.h" @@ -118,7 +119,7 @@ mojom::GraphInfoPtr graph_info, WebNNGraphImpl::ComputeResourceInfo compute_resource_info, base::flat_map< - uint64_t, + OperandId, std::unique_ptr<WebNNConstantOperand>> /*constant_operands*/, CreateGraphImplCallback callback) override { FakeWebNNGraphImpl::CreateAndBuild(std::move(receiver), this, *graph_info, @@ -324,9 +325,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildArgMinMax(kind, input_operand_id, output_operand_id, axis, keep_dimensions); @@ -406,7 +407,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3, 4, 5}, OperandDataType::kInt32); builder.BuildArgMinMax(kind, input_operand_id, input_operand_id, /*axis=*/0, @@ -433,9 +434,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildClamp(input_operand_id, output_operand_id, attributes.min_value, attributes.max_value); @@ -540,9 +541,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildHardSigmoid(input_operand_id, output_operand_id, alpha, beta); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -603,8 +604,8 @@ std::optional<OperandInfo> scale; std::optional<OperandInfo> bias; struct BatchNormalizationAttributes { - std::optional<uint64_t> scale_operand_id; - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> scale_operand_id; + std::optional<OperandId> bias_operand_id; uint32_t axis = 1; float epsilon = 1e-5; }; @@ -619,13 +620,13 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t mean_operand_id = + OperandId mean_operand_id = builder.BuildInput("mean", mean.dimensions, mean.type); - uint64_t variance_operand_id = + OperandId variance_operand_id = builder.BuildInput("variance", variance.dimensions, variance.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); if (scale) { @@ -854,11 +855,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t mean_operand_id = + OperandId mean_operand_id = builder.BuildInput("mean", {2}, OperandDataType::kFloat32); - uint64_t variance_operand_id = + OperandId variance_operand_id = builder.BuildInput("variance", {2}, OperandDataType::kFloat32); builder.BuildBatchNormalization( input_operand_id, mean_operand_id, variance_operand_id, @@ -872,11 +873,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t mean_operand_id = + OperandId mean_operand_id = builder.BuildInput("mean", {2}, OperandDataType::kFloat32); - uint64_t variance_operand_id = + OperandId variance_operand_id = builder.BuildInput("variance", {2}, OperandDataType::kFloat32); builder.BuildBatchNormalization( input_operand_id, mean_operand_id, variance_operand_id, mean_operand_id, @@ -889,11 +890,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t mean_operand_id = + OperandId mean_operand_id = builder.BuildInput("mean", {2}, OperandDataType::kFloat32); - uint64_t variance_operand_id = + OperandId variance_operand_id = builder.BuildInput("variance", {2}, OperandDataType::kFloat32); builder.BuildBatchNormalization( input_operand_id, mean_operand_id, variance_operand_id, @@ -916,14 +917,14 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - std::vector<uint64_t> input_operand_ids; + std::vector<OperandId> input_operand_ids; input_operand_ids.reserve(inputs.size()); for (size_t i = 0; i < inputs.size(); ++i) { input_operand_ids.push_back( builder.BuildInput(base::StringPrintf("input%zu", i), inputs[i].dimensions, inputs[i].type)); } - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildConcat(std::move(input_operand_ids), output_operand_id, axis); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -1063,18 +1064,18 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t filter_operand_id = + OperandId filter_operand_id = builder.BuildInput("filter", filter.dimensions, filter.type); - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> bias_operand_id; if (attributes.bias) { bias_operand_id = builder.BuildInput("bias", attributes.bias->dimensions, attributes.bias->type); } - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildConv2d(type, input_operand_id, filter_operand_id, output_operand_id, std::move(attributes), @@ -1270,9 +1271,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 5, 5}, OperandDataType::kFloat32); - uint64_t filter_operand_id = + OperandId filter_operand_id = builder.BuildInput("filter", {1, 1, 3, 3}, OperandDataType::kFloat32); builder.BuildConv2d(mojom::Conv2d::Kind::kDirect, input_operand_id, @@ -1287,9 +1288,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 5, 5}, OperandDataType::kFloat32); - uint64_t filter_operand_id = + OperandId filter_operand_id = builder.BuildInput("filter", {1, 1, 3, 3}, OperandDataType::kFloat32); builder.BuildConv2d(mojom::Conv2d::Kind::kDirect, input_operand_id, @@ -1491,9 +1492,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 3, 3}, OperandDataType::kFloat32); - uint64_t filter_operand_id = + OperandId filter_operand_id = builder.BuildInput("filter", {1, 1, 3, 3}, OperandDataType::kFloat32); builder.BuildConv2d(mojom::Conv2d::Kind::kTransposed, input_operand_id, @@ -1508,9 +1509,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 3, 3}, OperandDataType::kFloat32); - uint64_t filter_operand_id = + OperandId filter_operand_id = builder.BuildInput("filter", {1, 1, 3, 3}, OperandDataType::kFloat32); builder.BuildConv2d(mojom::Conv2d::Kind::kTransposed, input_operand_id, @@ -1536,9 +1537,9 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildCumulativeSum(input_operand_id, output_operand_id, axis, exclusive, reversed); @@ -1614,7 +1615,7 @@ uint32_t axis = 0; bool exclusive = false; bool reversed = false; - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 3, 3}, OperandDataType::kFloat32); builder.BuildCumulativeSum(input_operand_id, input_operand_id, axis, exclusive, reversed); @@ -1636,13 +1637,13 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", scale.dimensions, scale.type); - uint64_t zero_point_operand_id = builder.BuildInput( + OperandId zero_point_operand_id = builder.BuildInput( "zero_point", zero_point.dimensions, zero_point.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildDequantizeLinear(input_operand_id, scale_operand_id, zero_point_operand_id, output_operand_id); @@ -1741,11 +1742,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kInt8); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", {2, 3}, OperandDataType::kFloat32); - uint64_t zero_point_operand_id = + OperandId zero_point_operand_id = builder.BuildInput("zero_point", {2, 3}, OperandDataType::kInt8); builder.BuildDequantizeLinear(input_operand_id, scale_operand_id, zero_point_operand_id, input_operand_id); @@ -1757,11 +1758,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kInt8); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", {2, 3}, OperandDataType::kFloat32); - uint64_t zero_point_operand_id = + OperandId zero_point_operand_id = builder.BuildInput("zero_point", {2, 3}, OperandDataType::kInt8); builder.BuildDequantizeLinear(input_operand_id, scale_operand_id, zero_point_operand_id, scale_operand_id); @@ -1773,11 +1774,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kInt8); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", {2, 3}, OperandDataType::kFloat32); - uint64_t zero_point_operand_id = + OperandId zero_point_operand_id = builder.BuildInput("zero_point", {2, 3}, OperandDataType::kInt8); builder.BuildDequantizeLinear(input_operand_id, scale_operand_id, zero_point_operand_id, zero_point_operand_id); @@ -1865,11 +1866,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t lhs_operand_id = + OperandId lhs_operand_id = builder.BuildInput("lhs", lhs.dimensions, lhs.type); - uint64_t rhs_operand_id = + OperandId rhs_operand_id = builder.BuildInput("rhs", rhs.dimensions, rhs.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildElementWiseBinary(kind, lhs_operand_id, rhs_operand_id, output_operand_id); @@ -1989,9 +1990,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildElementWiseUnary(kind, input_operand_id, output_operand_id); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -2313,9 +2314,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildElu(input_operand_id, output_operand_id, alpha); @@ -2369,7 +2370,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2}, OperandDataType::kFloat32); builder.BuildElu(input_operand_id, input_operand_id, /*alpha*/ 1.0); EXPECT_FALSE(builder.IsValidGraphForTesting(context_properties)); @@ -2388,9 +2389,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildExpand(input_operand_id, output_operand_id); @@ -2456,7 +2457,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2}, OperandDataType::kFloat32); builder.BuildExpand(input_operand_id, input_operand_id); EXPECT_FALSE(builder.IsValidGraphForTesting(context_properties)); @@ -2481,11 +2482,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t indices_operand_id = builder.BuildInput( + OperandId indices_operand_id = builder.BuildInput( "indices", attributes.indices.dimensions, attributes.indices.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildGather(input_operand_id, indices_operand_id, output_operand_id, attributes.axis); @@ -2573,9 +2574,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kFloat32); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", {2}, OperandDataType::kUint32); builder.BuildGather(input_operand_id, indices_operand_id, input_operand_id, /*axis*/ 0); @@ -2587,9 +2588,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {3}, OperandDataType::kUint32); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", {3}, OperandDataType::kUint32); builder.BuildGather(input_operand_id, indices_operand_id, indices_operand_id, /*axis*/ 0); @@ -2610,11 +2611,11 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t indices_operand_id = builder.BuildInput( + OperandId indices_operand_id = builder.BuildInput( "indices", attributes.indices.dimensions, attributes.indices.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildGatherElements(input_operand_id, indices_operand_id, output_operand_id, attributes.axis); @@ -2708,9 +2709,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kFloat32); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", {2, 3}, OperandDataType::kUint32); builder.BuildGatherElements(input_operand_id, indices_operand_id, input_operand_id, @@ -2723,9 +2724,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {3}, OperandDataType::kUint32); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", {3}, OperandDataType::kUint32); builder.BuildGatherElements(input_operand_id, indices_operand_id, indices_operand_id, /*axis=*/0); @@ -2746,11 +2747,11 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", indices.dimensions, indices.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildGatherND(input_operand_id, indices_operand_id, output_operand_id); @@ -2828,9 +2829,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kUint32); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", {2, 1}, OperandDataType::kUint32); builder.BuildGatherND(input_operand_id, indices_operand_id, input_operand_id); @@ -2842,9 +2843,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 1}, OperandDataType::kUint32); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", {2, 1}, OperandDataType::kUint32); builder.BuildGatherND(input_operand_id, indices_operand_id, indices_operand_id); @@ -2864,9 +2865,9 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildGelu(input_operand_id, output_operand_id); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -2910,7 +2911,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1}, OperandDataType::kFloat16); builder.BuildGelu(input_operand_id, input_operand_id); EXPECT_FALSE(builder.IsValidGraphForTesting(context_properties)); @@ -2922,7 +2923,7 @@ OperandInfo b; std::optional<OperandInfo> c; struct GemmAttributes { - std::optional<uint64_t> c_operand_id; + std::optional<OperandId> c_operand_id; float alpha = 1.0; float beta = 1.0; bool a_transpose = false; @@ -2939,9 +2940,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t a_operand_id = builder.BuildInput("a", a.dimensions, a.type); - uint64_t b_operand_id = builder.BuildInput("b", b.dimensions, b.type); - uint64_t output_operand_id = + OperandId a_operand_id = builder.BuildInput("a", a.dimensions, a.type); + OperandId b_operand_id = builder.BuildInput("b", b.dimensions, b.type); + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); if (c) { @@ -3066,9 +3067,9 @@ struct GruTester { struct GruAttributes { - std::optional<uint64_t> bias_operand_id; - std::optional<uint64_t> recurrent_bias_operand_id; - std::optional<uint64_t> initial_hidden_state_operand_id; + std::optional<OperandId> bias_operand_id; + std::optional<OperandId> recurrent_bias_operand_id; + std::optional<OperandId> initial_hidden_state_operand_id; bool reset_after = true; bool return_sequence = false; mojom::RecurrentNetworkDirection direction = @@ -3098,14 +3099,14 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t weight_operand_id = + OperandId weight_operand_id = builder.BuildInput("weight", weight.dimensions, weight.type); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", recurrent_weight.dimensions, recurrent_weight.type); - std::vector<uint64_t> output_operand_ids; + std::vector<OperandId> output_operand_ids; output_operand_ids.reserve(outputs.size()); for (size_t i = 0; i < outputs.size(); ++i) { output_operand_ids.push_back( @@ -3255,16 +3256,16 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = builder.BuildInput( + OperandId input_operand_id = builder.BuildInput( "input", {steps, batch_size, input_size}, OperandDataType::kFloat32); - uint64_t weight_operand_id = builder.BuildInput( + OperandId weight_operand_id = builder.BuildInput( "weight", {num_directions, 3 * hidden_size, input_size}, OperandDataType::kFloat32); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", {num_directions, 3 * hidden_size, hidden_size}, OperandDataType::kFloat32); - uint64_t initial_hidden_state_operand_id = builder.BuildInput( + OperandId initial_hidden_state_operand_id = builder.BuildInput( "initialHiddenState", {num_directions, batch_size, hidden_size}, OperandDataType::kFloat32); @@ -3279,8 +3280,8 @@ struct GruCellTester { struct GruCellAttributes { - std::optional<uint64_t> bias_operand_id; - std::optional<uint64_t> recurrent_bias_operand_id; + std::optional<OperandId> bias_operand_id; + std::optional<OperandId> recurrent_bias_operand_id; bool reset_after = true; mojom::GruWeightLayout layout = mojom::GruWeightLayout::kZrn; std::vector<mojom::RecurrentNetworkActivation> activations = { @@ -3306,13 +3307,13 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t weight_operand_id = + OperandId weight_operand_id = builder.BuildInput("weight", weight.dimensions, weight.type); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", recurrent_weight.dimensions, recurrent_weight.type); - uint64_t hidden_state_operand_id = builder.BuildInput( + OperandId hidden_state_operand_id = builder.BuildInput( "hiddenState", hidden_state.dimensions, hidden_state.type); if (bias.has_value()) { @@ -3324,7 +3325,7 @@ "recurrentBias", recurrent_bias->dimensions, recurrent_bias->type); } - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildGruCell(input_operand_id, weight_operand_id, @@ -3670,15 +3671,15 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = builder.BuildInput( + OperandId input_operand_id = builder.BuildInput( "input", {batch_size, input_size}, OperandDataType::kFloat32); - uint64_t weight_operand_id = builder.BuildInput( + OperandId weight_operand_id = builder.BuildInput( "weight", {3 * hidden_size, input_size}, OperandDataType::kFloat32); - uint64_t recurrent_weight_operand_id = + OperandId recurrent_weight_operand_id = builder.BuildInput("recurrentWeight", {3 * hidden_size, hidden_size}, OperandDataType::kFloat32); - uint64_t hidden_state_operand_id = builder.BuildInput( + OperandId hidden_state_operand_id = builder.BuildInput( "hiddenState", {batch_size, hidden_size}, OperandDataType::kFloat32); builder.BuildGruCell(input_operand_id, weight_operand_id, @@ -3694,8 +3695,8 @@ std::optional<OperandInfo> scale; std::optional<OperandInfo> bias; struct InstanceNormalizationAttributes { - std::optional<uint64_t> scale_operand_id; - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> scale_operand_id; + std::optional<OperandId> bias_operand_id; float epsilon = 1e-5; }; InstanceNormalizationAttributes attributes; @@ -3711,9 +3712,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); if (scale) { @@ -3853,7 +3854,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); builder.BuildInstanceNormalization( input_operand_id, input_operand_id, @@ -3866,9 +3867,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", {2}, OperandDataType::kFloat32); InstanceNormalizationTester::InstanceNormalizationAttributes attributes; @@ -3884,9 +3885,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t bias_operand_id = + OperandId bias_operand_id = builder.BuildInput("bias", {2}, OperandDataType::kFloat32); InstanceNormalizationTester::InstanceNormalizationAttributes attributes; @@ -3903,8 +3904,8 @@ std::optional<OperandInfo> scale; std::optional<OperandInfo> bias; struct LayerNormalizationAttributes { - std::optional<uint64_t> scale_operand_id; - std::optional<uint64_t> bias_operand_id; + std::optional<OperandId> scale_operand_id; + std::optional<OperandId> bias_operand_id; std::vector<uint32_t> axes; float epsilon = 1e-5; }; @@ -3919,9 +3920,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); if (scale.has_value()) { @@ -4053,7 +4054,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); builder.BuildLayerNormalization( input_operand_id, input_operand_id, @@ -4066,9 +4067,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", {1, 2, 3, 4}, OperandDataType::kFloat32); LayerNormalizationTester::LayerNormalizationAttributes attributes; @@ -4085,9 +4086,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 2, 3, 4}, OperandDataType::kFloat32); - uint64_t bias_operand_id = + OperandId bias_operand_id = builder.BuildInput("bias", {1, 2, 3, 4}, OperandDataType::kFloat32); LayerNormalizationTester::LayerNormalizationAttributes attributes; @@ -4102,11 +4103,11 @@ struct LstmTester { struct LstmAttributes { - std::optional<uint64_t> bias_operand_id; - std::optional<uint64_t> recurrent_bias_operand_id; - std::optional<uint64_t> peephole_weight_operand_id; - std::optional<uint64_t> initial_hidden_state_operand_id; - std::optional<uint64_t> initial_cell_state_operand_id; + std::optional<OperandId> bias_operand_id; + std::optional<OperandId> recurrent_bias_operand_id; + std::optional<OperandId> peephole_weight_operand_id; + std::optional<OperandId> initial_hidden_state_operand_id; + std::optional<OperandId> initial_cell_state_operand_id; bool return_sequence = false; mojom::RecurrentNetworkDirection direction = mojom::RecurrentNetworkDirection::kForward; @@ -4138,14 +4139,14 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t weight_operand_id = + OperandId weight_operand_id = builder.BuildInput("weight", weight.dimensions, weight.type); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", recurrent_weight.dimensions, recurrent_weight.type); - std::vector<uint64_t> output_operand_ids; + std::vector<OperandId> output_operand_ids; output_operand_ids.reserve(outputs.size()); for (size_t i = 0; i < outputs.size(); ++i) { output_operand_ids.push_back( @@ -4293,16 +4294,16 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = builder.BuildInput( + OperandId input_operand_id = builder.BuildInput( "input", {steps, batch_size, input_size}, OperandDataType::kFloat32); - uint64_t weight_operand_id = builder.BuildInput( + OperandId weight_operand_id = builder.BuildInput( "weight", {direction_count, 4 * hidden_size, input_size}, OperandDataType::kFloat32); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", {direction_count, 4 * hidden_size, hidden_size}, OperandDataType::kFloat32); - uint64_t output_operand_id = builder.BuildOutput( + OperandId output_operand_id = builder.BuildOutput( "output", {direction_count, batch_size, hidden_size}, OperandDataType::kFloat32); builder.BuildLstm(input_operand_id, weight_operand_id, @@ -4324,19 +4325,19 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = builder.BuildInput( + OperandId input_operand_id = builder.BuildInput( "input", {steps, batch_size, input_size}, OperandDataType::kFloat32); - uint64_t weight_operand_id = builder.BuildInput( + OperandId weight_operand_id = builder.BuildInput( "weight", {direction_count, 4 * hidden_size, input_size}, OperandDataType::kFloat32); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", {direction_count, 4 * hidden_size, hidden_size}, OperandDataType::kFloat32); - uint64_t initial_cell_state_operand_id = builder.BuildInput( + OperandId initial_cell_state_operand_id = builder.BuildInput( "initialCellState", {direction_count, batch_size, hidden_size}, OperandDataType::kFloat32); - uint64_t output_operand_id = builder.BuildOutput( + OperandId output_operand_id = builder.BuildOutput( "output", {direction_count, batch_size, hidden_size}, OperandDataType::kFloat32); @@ -4351,9 +4352,9 @@ struct LstmCellTester { struct LstmCellAttributes { - std::optional<uint64_t> bias_operand_id; - std::optional<uint64_t> recurrent_bias_operand_id; - std::optional<uint64_t> peephole_weight_operand_id; + std::optional<OperandId> bias_operand_id; + std::optional<OperandId> recurrent_bias_operand_id; + std::optional<OperandId> peephole_weight_operand_id; mojom::LstmWeightLayout layout = mojom::LstmWeightLayout::kIofg; std::vector<mojom::RecurrentNetworkActivation> activations = { mojom::RecurrentNetworkActivation::kSigmoid, @@ -4381,18 +4382,18 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t weight_operand_id = + OperandId weight_operand_id = builder.BuildInput("weight", weight.dimensions, weight.type); - uint64_t recurrent_weight_operand_id = builder.BuildInput( + OperandId recurrent_weight_operand_id = builder.BuildInput( "recurrentWeight", recurrent_weight.dimensions, recurrent_weight.type); - uint64_t hidden_state_operand_id = builder.BuildInput( + OperandId hidden_state_operand_id = builder.BuildInput( "hiddenState", hidden_state.dimensions, hidden_state.type); - uint64_t cell_state_operand_id = + OperandId cell_state_operand_id = builder.BuildInput("cellState", cell_state.dimensions, cell_state.type); - std::vector<uint64_t> output_operand_ids; + std::vector<OperandId> output_operand_ids; output_operand_ids.reserve(outputs.size()); for (size_t i = 0; i < outputs.size(); ++i) { output_operand_ids.push_back( @@ -4598,18 +4599,18 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = builder.BuildInput( + OperandId input_operand_id = builder.BuildInput( "input", {batch_size, input_size}, OperandDataType::kFloat32); - uint64_t weight_operand_id = builder.BuildInput( + OperandId weight_operand_id = builder.BuildInput( "weight", {4 * hidden_size, input_size}, OperandDataType::kFloat32); - uint64_t recurrent_weight_operand_id = + OperandId recurrent_weight_operand_id = builder.BuildInput("recurrentWeight", {4 * hidden_size, hidden_size}, OperandDataType::kFloat32); - uint64_t hidden_state_operand_id = builder.BuildInput( + OperandId hidden_state_operand_id = builder.BuildInput( "hiddenState", {batch_size, hidden_size}, OperandDataType::kFloat32); - uint64_t cell_state_operand_id = builder.BuildInput( + OperandId cell_state_operand_id = builder.BuildInput( "cellState", {batch_size, hidden_size}, OperandDataType::kFloat32); - uint64_t output_operand_id = builder.BuildOutput( + OperandId output_operand_id = builder.BuildOutput( "output", {batch_size, hidden_size}, OperandDataType::kFloat32); builder.BuildLstmCell(input_operand_id, weight_operand_id, @@ -4634,9 +4635,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t a_operand_id = builder.BuildInput("a", a.dimensions, a.type); - uint64_t b_operand_id = builder.BuildInput("b", b.dimensions, b.type); - uint64_t output_operand_id = + OperandId a_operand_id = builder.BuildInput("a", a.dimensions, a.type); + OperandId b_operand_id = builder.BuildInput("b", b.dimensions, b.type); + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildMatmul(a_operand_id, b_operand_id, output_operand_id); @@ -4744,9 +4745,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t a_operand_id = + OperandId a_operand_id = builder.BuildInput("a", {2, 3}, OperandDataType::kFloat32); - uint64_t b_operand_id = + OperandId b_operand_id = builder.BuildInput("b", {3, 4}, OperandDataType::kFloat32); builder.BuildMatmul(a_operand_id, b_operand_id, a_operand_id); EXPECT_FALSE(builder.IsValidGraphForTesting(context_properties)); @@ -4769,9 +4770,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildPad(input_operand_id, output_operand_id, beginning_padding, ending_padding, mode, value); @@ -4843,7 +4844,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kFloat32); builder.BuildPad(input_operand_id, input_operand_id, {1, 1}, {1, 1}, mojom::PaddingMode::Tag::kConstant, 0); @@ -4878,9 +4879,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildPool2d(kind, input_operand_id, output_operand_id, std::move(attributes)); @@ -5042,11 +5043,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t slope_operand_id = + OperandId slope_operand_id = builder.BuildInput("slope", slope.dimensions, slope.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildPrelu(input_operand_id, slope_operand_id, output_operand_id); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -5153,9 +5154,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kFloat32); - uint64_t slope_operand_id = + OperandId slope_operand_id = builder.BuildInput("slope", {2, 3}, OperandDataType::kFloat32); builder.BuildPrelu(input_operand_id, slope_operand_id, input_operand_id); EXPECT_FALSE(builder.IsValidGraphForTesting(context_properties)); @@ -5166,9 +5167,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kFloat32); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 3}, OperandDataType::kFloat32); builder.BuildPrelu(input_operand_id, output_operand_id, output_operand_id); EXPECT_FALSE(builder.IsValidGraphForTesting(context_properties)); @@ -5189,13 +5190,13 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", scale.dimensions, scale.type); - uint64_t zero_point_operand_id = builder.BuildInput( + OperandId zero_point_operand_id = builder.BuildInput( "zero_point", zero_point.dimensions, zero_point.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildQuantizeLinear(input_operand_id, scale_operand_id, zero_point_operand_id, output_operand_id); @@ -5293,11 +5294,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kFloat32); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", {2, 3}, OperandDataType::kFloat32); - uint64_t zero_point_operand_id = + OperandId zero_point_operand_id = builder.BuildInput("zero_point", {2, 3}, OperandDataType::kInt8); builder.BuildQuantizeLinear(input_operand_id, scale_operand_id, zero_point_operand_id, input_operand_id); @@ -5309,11 +5310,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kFloat32); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", {2, 3}, OperandDataType::kFloat32); - uint64_t zero_point_operand_id = + OperandId zero_point_operand_id = builder.BuildInput("zero_point", {2, 3}, OperandDataType::kInt8); builder.BuildQuantizeLinear(input_operand_id, scale_operand_id, zero_point_operand_id, scale_operand_id); @@ -5325,11 +5326,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kFloat32); - uint64_t scale_operand_id = + OperandId scale_operand_id = builder.BuildInput("scale", {2, 3}, OperandDataType::kFloat32); - uint64_t zero_point_operand_id = + OperandId zero_point_operand_id = builder.BuildInput("zero_point", {2, 3}, OperandDataType::kInt8); builder.BuildQuantizeLinear(input_operand_id, scale_operand_id, zero_point_operand_id, zero_point_operand_id); @@ -5352,9 +5353,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildReduce(kind, input_operand_id, output_operand_id, axes, keep_dimensions); @@ -5611,7 +5612,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2, 3}, OperandDataType::kFloat32); builder.BuildReduce(mojom::Reduce::Kind::kSumSquare, input_operand_id, input_operand_id, {0}, false); @@ -5631,9 +5632,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildRelu(input_operand_id, output_operand_id); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -5702,9 +5703,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildResample2d(input_operand_id, output_operand_id, attributes); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -5911,7 +5912,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {1, 1, 2, 4}, OperandDataType::kFloat32); builder.BuildResample2d(input_operand_id, input_operand_id, Resample2dTester::Resample2dAttributes{}); @@ -5932,9 +5933,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildReshape(input_operand_id, output_operand_id); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -5990,9 +5991,9 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildReverse(input_operand_id, output_operand_id, std::move(axes)); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -6043,7 +6044,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {3, 3}, OperandDataType::kFloat32); builder.BuildReverse(input_operand_id, input_operand_id, /*axes=*/{1}); EXPECT_FALSE(builder.IsValidGraphForTesting(context_properties)); @@ -6065,13 +6066,13 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", indices.dimensions, indices.type); - uint64_t updates_operand_id = + OperandId updates_operand_id = builder.BuildInput("updates", updates.dimensions, updates.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildScatterElements(input_operand_id, indices_operand_id, updates_operand_id, output_operand_id, axis); @@ -6210,11 +6211,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {3, 3}, OperandDataType::kFloat32); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", {2, 3}, OperandDataType::kUint32); - uint64_t updates_operand_id = + OperandId updates_operand_id = builder.BuildInput("updates", {2, 3}, OperandDataType::kFloat32); builder.BuildScatterElements(input_operand_id, indices_operand_id, updates_operand_id, input_operand_id, @@ -6237,13 +6238,13 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", indices.dimensions, indices.type); - uint64_t updates_operand_id = + OperandId updates_operand_id = builder.BuildInput("updates", updates.dimensions, updates.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildScatterND(input_operand_id, indices_operand_id, updates_operand_id, output_operand_id); @@ -6342,11 +6343,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {4, 4, 4}, OperandDataType::kFloat32); - uint64_t indices_operand_id = + OperandId indices_operand_id = builder.BuildInput("indices", {2, 1}, OperandDataType::kUint32); - uint64_t updates_operand_id = + OperandId updates_operand_id = builder.BuildInput("updates", {2, 4, 4}, OperandDataType::kFloat32); builder.BuildScatterND(input_operand_id, indices_operand_id, updates_operand_id, input_operand_id); @@ -6374,9 +6375,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildSlice(input_operand_id, output_operand_id, attributes.starts, attributes.sizes, attributes.strides); @@ -6480,9 +6481,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); switch (kind) { case FloatingPointUnaryKind::kHardSwish: @@ -6556,7 +6557,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2}, OperandDataType::kFloat32); builder.BuildLeakyRelu(input_operand_id, input_operand_id, /*alpha*/ 1.0); @@ -6569,9 +6570,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2}, OperandDataType::kFloat32); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2}, OperandDataType::kFloat32); builder.BuildLeakyRelu(input_operand_id, output_operand_id, /*alpha*/ NAN); @@ -6584,7 +6585,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2}, OperandDataType::kFloat32); builder.BuildLinear(input_operand_id, input_operand_id, /*alpha*/ 1.0, /*beta*/ 0.0); @@ -6597,9 +6598,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2}, OperandDataType::kFloat32); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2}, OperandDataType::kFloat32); builder.BuildLinear(input_operand_id, output_operand_id, /*alpha*/ NAN, /*beta*/ 0.0); @@ -6612,9 +6613,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2}, OperandDataType::kFloat32); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2}, OperandDataType::kFloat32); builder.BuildLinear(input_operand_id, output_operand_id, /*alpha*/ 1.0, /*beta*/ NAN); @@ -6628,7 +6629,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2}, OperandDataType::kFloat32); builder.BuildSigmoid(input_operand_id, input_operand_id); @@ -6640,7 +6641,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {2}, OperandDataType::kFloat32); builder.BuildTanh(input_operand_id, input_operand_id); @@ -6661,9 +6662,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildSoftmax(input_operand_id, output_operand_id, axis); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -6749,9 +6750,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildSoftplus(input_operand_id, output_operand_id); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -6797,7 +6798,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {4, 6}, OperandDataType::kFloat32); builder.BuildSoftplus(input_operand_id, input_operand_id); EXPECT_FALSE(builder.IsValidGraphForTesting(context_properties)); @@ -6816,9 +6817,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildSoftsign(input_operand_id, output_operand_id); EXPECT_EQ(builder.IsValidGraphForTesting(context_properties), expected); @@ -6865,7 +6866,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {4, 6}, OperandDataType::kFloat32); builder.BuildSoftsign(input_operand_id, input_operand_id); EXPECT_FALSE(builder.IsValidGraphForTesting(context_properties)); @@ -6885,10 +6886,10 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - std::vector<uint64_t> output_operand_ids; + std::vector<OperandId> output_operand_ids; for (size_t i = 0; i < outputs.size(); ++i) { output_operand_ids.push_back( builder.BuildOutput("output" + base::NumberToString(i), @@ -6975,7 +6976,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = builder.BuildInput("input", {4, 6}, kFloat32); + OperandId input_operand_id = builder.BuildInput("input", {4, 6}, kFloat32); builder.BuildSplit(input_operand_id, {input_operand_id}, 0); builder.BuildSplit(input_operand_id, @@ -6997,9 +6998,9 @@ // Build the graph with mojo type. GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildTile(input_operand_id, output_operand_id, std::move(repetitions)); @@ -7085,7 +7086,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {4, 6}, OperandDataType::kFloat32); builder.BuildTile(input_operand_id, input_operand_id, std::vector<uint32_t>{1, 2}); @@ -7106,9 +7107,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildTranspose(input_operand_id, output_operand_id, std::move(permutation)); @@ -7196,9 +7197,9 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", input.dimensions, input.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildTriangular(input_operand_id, output_operand_id, upper, diagonal); @@ -7239,7 +7240,7 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input", {4, 6}, OperandDataType::kFloat32); builder.BuildTriangular(input_operand_id, input_operand_id, @@ -7262,13 +7263,13 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = test.BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t condition_operand_id = + OperandId condition_operand_id = builder.BuildInput("condition", condition.dimensions, condition.type); - uint64_t true_value_operand_id = builder.BuildInput( + OperandId true_value_operand_id = builder.BuildInput( "true_value", true_value.dimensions, true_value.type); - uint64_t false_value_operand_id = builder.BuildInput( + OperandId false_value_operand_id = builder.BuildInput( "false_value", false_value.dimensions, false_value.type); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", output.dimensions, output.type); builder.BuildWhere(condition_operand_id, true_value_operand_id, false_value_operand_id, output_operand_id); @@ -7403,11 +7404,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t condition_operand_id = + OperandId condition_operand_id = builder.BuildInput("condition", {2, 4}, OperandDataType::kUint8); - uint64_t true_value_operand_id = + OperandId true_value_operand_id = builder.BuildInput("true_value", {2, 4}, OperandDataType::kFloat32); - uint64_t false_value_operand_id = + OperandId false_value_operand_id = builder.BuildInput("false_value", {2, 4}, OperandDataType::kFloat32); builder.BuildWhere(condition_operand_id, true_value_operand_id, false_value_operand_id, condition_operand_id); @@ -7419,11 +7420,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t condition_operand_id = + OperandId condition_operand_id = builder.BuildInput("condition", {2, 4}, OperandDataType::kUint8); - uint64_t true_value_operand_id = + OperandId true_value_operand_id = builder.BuildInput("true_value", {2, 4}, OperandDataType::kFloat32); - uint64_t false_value_operand_id = + OperandId false_value_operand_id = builder.BuildInput("false_value", {2, 4}, OperandDataType::kFloat32); builder.BuildWhere(condition_operand_id, true_value_operand_id, false_value_operand_id, true_value_operand_id); @@ -7435,11 +7436,11 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t condition_operand_id = + OperandId condition_operand_id = builder.BuildInput("condition", {2, 4}, OperandDataType::kUint8); - uint64_t true_value_operand_id = + OperandId true_value_operand_id = builder.BuildInput("true_value", {2, 4}, OperandDataType::kFloat32); - uint64_t false_value_operand_id = + OperandId false_value_operand_id = builder.BuildInput("false_value", {2, 4}, OperandDataType::kFloat32); builder.BuildWhere(condition_operand_id, true_value_operand_id, false_value_operand_id, false_value_operand_id); @@ -7457,16 +7458,16 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - const uint64_t lhs_operand_id = + const OperandId lhs_operand_id = builder.BuildInput("lhs", kShape, kMojoDataType); - const uint64_t rhs_operand_id = + const OperandId rhs_operand_id = builder.BuildInput("rhs", kShape, kMojoDataType); - const uint64_t output_1_operand_id = + const OperandId output_1_operand_id = builder.BuildOutput("output1", kShape, kMojoDataType); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kAdd, lhs_operand_id, rhs_operand_id, output_1_operand_id); - const uint64_t output_2_operand_id = + const OperandId output_2_operand_id = builder.BuildOutput("output2", kShape, kMojoDataType); builder.BuildElementWiseBinary(mojom::ElementWiseBinary::Kind::kAdd, lhs_operand_id, rhs_operand_id, @@ -7695,26 +7696,26 @@ BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); // The graph outputs are built first, and then inputs / constants. - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kFloat32); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {2, 2}, OperandDataType::kFloat32); std::vector<float> constant_data = {5.0, 6.0, 7.0, 8.0}; - uint64_t constant_a_operand_id = builder.BuildConstant( + OperandId constant_a_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); - uint64_t intermediate_1_operand_id = + OperandId intermediate_1_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(input_a_operand_id, constant_a_operand_id, intermediate_1_operand_id, GemmTester::GemmAttributes()); - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", {2, 2}, OperandDataType::kFloat32); - uint64_t constant_b_operand_id = builder.BuildConstant( + OperandId constant_b_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); - uint64_t intermediate_2_operand_id = + OperandId intermediate_2_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(input_b_operand_id, constant_b_operand_id, intermediate_2_operand_id, GemmTester::GemmAttributes()); @@ -7737,25 +7738,25 @@ BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); // The graph outputs are built first, and then inputs / constants. - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kFloat32); std::vector<float> constant_data = {5.0, 6.0, 7.0, 8.0}; - uint64_t constant_a_operand_id = builder.BuildConstant( + OperandId constant_a_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); - uint64_t input_a_operand_id = + OperandId input_a_operand_id = builder.BuildInput("input_a", {2, 2}, OperandDataType::kFloat32); - uint64_t intermediate_1_operand_id = + OperandId intermediate_1_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(constant_a_operand_id, input_a_operand_id, intermediate_1_operand_id, GemmTester::GemmAttributes()); - uint64_t input_b_operand_id = + OperandId input_b_operand_id = builder.BuildInput("input_b", {2, 2}, OperandDataType::kFloat32); - uint64_t constant_b_operand_id = builder.BuildConstant( + OperandId constant_b_operand_id = builder.BuildConstant( {2, 2}, OperandDataType::kFloat32, base::as_byte_span(base::allow_nonunique_obj, constant_data)); - uint64_t intermediate_2_operand_id = + OperandId intermediate_2_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); builder.BuildGemm(constant_b_operand_id, input_b_operand_id, intermediate_2_operand_id, GemmTester::GemmAttributes()); @@ -7770,12 +7771,12 @@ mojo::AssociatedRemote<mojom::WebNNGraphBuilder> remote = BindNewGraphBuilderRemote(); GraphInfoBuilder builder(remote); - uint64_t input_operand_id = + OperandId input_operand_id = builder.BuildInput("input_a", {2, 2}, OperandDataType::kFloat32); - uint64_t intermediate_operand_id = + OperandId intermediate_operand_id = builder.BuildIntermediateOperand({2, 2}, OperandDataType::kFloat32); - uint64_t output_operand_id = + OperandId output_operand_id = builder.BuildOutput("output", {2, 2}, OperandDataType::kUint8); builder.BuildRelu(intermediate_operand_id, output_operand_id); builder.BuildRelu(input_operand_id, intermediate_operand_id);
diff --git a/services/webnn/webnn_test_utils.cc b/services/webnn/webnn_test_utils.cc index 302f598..ce9b75ec 100644 --- a/services/webnn/webnn_test_utils.cc +++ b/services/webnn/webnn_test_utils.cc
@@ -11,6 +11,7 @@ #include "base/unguessable_token.h" #include "services/webnn/public/cpp/context_properties.h" #include "services/webnn/public/cpp/supported_tensors.h" +#include "services/webnn/public/cpp/webnn_types.h" #include "services/webnn/webnn_context_impl.h" #include "third_party/blink/public/common/tokens/tokens.h" @@ -23,43 +24,44 @@ GraphInfoBuilder::~GraphInfoBuilder() = default; -uint64_t GraphInfoBuilder::BuildOperand(const std::vector<uint32_t>& dimensions, - OperandDataType type, - mojom::Operand::Kind kind) { +OperandId GraphInfoBuilder::BuildOperand( + const std::vector<uint32_t>& dimensions, + OperandDataType type, + mojom::Operand::Kind kind) { mojom::OperandPtr operand = mojom::Operand::New(); operand->descriptor = OperandDescriptor::UnsafeCreateForTesting(type, dimensions); operand->kind = kind; - CHECK(graph_info_->id_to_operand_map.find(operand_id_) == - graph_info_->id_to_operand_map.end()); - graph_info_->id_to_operand_map[operand_id_] = std::move(operand); - return operand_id_++; + CHECK(graph_info_->id_to_operand_map + .insert({next_operand_id_, std::move(operand)}) + .second); + return next_operand_id_++; } -uint64_t GraphInfoBuilder::BuildIntermediateOperand( +OperandId GraphInfoBuilder::BuildIntermediateOperand( const std::vector<uint32_t>& dimensions, OperandDataType type) { return BuildOperand(dimensions, type, mojom::Operand::Kind::kOutput); } -uint64_t GraphInfoBuilder::BuildInput(const std::string& name, - const std::vector<uint32_t>& dimensions, - OperandDataType type) { - uint64_t operand_id = +OperandId GraphInfoBuilder::BuildInput(const std::string& name, + const std::vector<uint32_t>& dimensions, + OperandDataType type) { + OperandId operand_id = BuildOperand(dimensions, type, mojom::Operand::Kind::kInput); graph_info_->id_to_operand_map[operand_id]->name = name; graph_info_->input_operands.push_back(operand_id); return operand_id; } -uint64_t GraphInfoBuilder::BuildConstant( +OperandId GraphInfoBuilder::BuildConstant( const std::vector<uint32_t>& dimensions, OperandDataType type, base::span<const uint8_t> values, blink::WebNNPendingConstantToken handle) { - uint64_t operand_id = + OperandId operand_id = BuildOperand(dimensions, type, mojom::Operand::Kind::kConstant); graph_builder_remote_->get()->CreatePendingConstant( @@ -68,22 +70,23 @@ return operand_id; } -void GraphInfoBuilder::AddOutput(const std::string& name, uint64_t operand_id) { +void GraphInfoBuilder::AddOutput(const std::string& name, + OperandId operand_id) { graph_info_->id_to_operand_map[operand_id]->name = name; graph_info_->output_operands.push_back(operand_id); } -uint64_t GraphInfoBuilder::BuildOutput(const std::string& name, - const std::vector<uint32_t>& dimensions, - OperandDataType type) { - uint64_t operand_id = BuildOperand(dimensions, type); +OperandId GraphInfoBuilder::BuildOutput(const std::string& name, + const std::vector<uint32_t>& dimensions, + OperandDataType type) { + OperandId operand_id = BuildOperand(dimensions, type); AddOutput(name, operand_id); return operand_id; } void GraphInfoBuilder::BuildArgMinMax(mojom::ArgMinMax::Kind kind, - uint64_t input_operand_id, - uint64_t output_operand_id, + OperandId input_operand_id, + OperandId output_operand_id, uint32_t axis, bool keep_dimensions) { mojom::ArgMinMaxPtr arg_min_max = mojom::ArgMinMax::New(); @@ -96,8 +99,8 @@ mojom::Operation::NewArgMinMax(std::move(arg_min_max))); } -void GraphInfoBuilder::BuildElu(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildElu(OperandId input_operand_id, + OperandId output_operand_id, float alpha) { mojom::EluPtr elu = mojom::Elu::New(); elu->input_operand_id = input_operand_id; @@ -106,8 +109,8 @@ graph_info_->operations.push_back(mojom::Operation::NewElu(std::move(elu))); } -void GraphInfoBuilder::BuildLeakyRelu(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildLeakyRelu(OperandId input_operand_id, + OperandId output_operand_id, float alpha) { mojom::LeakyReluPtr leaky_relu = mojom::LeakyRelu::New(); leaky_relu->input_operand_id = input_operand_id; @@ -117,8 +120,8 @@ mojom::Operation::NewLeakyRelu(std::move(leaky_relu))); } -void GraphInfoBuilder::BuildLinear(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildLinear(OperandId input_operand_id, + OperandId output_operand_id, float alpha, float beta) { mojom::LinearPtr linear = mojom::Linear::New(); @@ -130,8 +133,8 @@ mojom::Operation::NewLinear(std::move(linear))); } -void GraphInfoBuilder::BuildPad(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildPad(OperandId input_operand_id, + OperandId output_operand_id, const std::vector<uint32_t>& beginning_padding, const std::vector<uint32_t>& ending_padding, mojom::PaddingMode::Tag mode, @@ -165,8 +168,8 @@ } void GraphInfoBuilder::BuildSplit( - uint64_t input_operand_id, - const std::vector<uint64_t>& output_operand_ids, + OperandId input_operand_id, + const std::vector<OperandId>& output_operand_ids, uint32_t axis) { mojom::SplitPtr split = mojom::Split::New(); split->input_operand_id = input_operand_id; @@ -177,8 +180,8 @@ mojom::Operation::NewSplit(std::move(split))); } -void GraphInfoBuilder::BuildClamp(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildClamp(OperandId input_operand_id, + OperandId output_operand_id, float min_value, float max_value) { mojom::ClampPtr clamp = mojom::Clamp::New(); @@ -190,8 +193,8 @@ mojom::Operation::NewClamp(std::move(clamp))); } -void GraphInfoBuilder::BuildConcat(std::vector<uint64_t> input_operand_ids, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildConcat(std::vector<OperandId> input_operand_ids, + OperandId output_operand_id, uint32_t axis) { mojom::ConcatPtr concat = mojom::Concat::New(); concat->input_operand_ids = std::move(input_operand_ids); @@ -201,8 +204,8 @@ mojom::Operation::NewConcat(std::move(concat))); } -void GraphInfoBuilder::BuildCumulativeSum(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildCumulativeSum(OperandId input_operand_id, + OperandId output_operand_id, uint32_t axis, std::optional<bool> exclusive, std::optional<bool> reversed) { @@ -220,10 +223,10 @@ mojom::Operation::NewCumulativeSum(std::move(cumulative_sum))); } -void GraphInfoBuilder::BuildDequantizeLinear(uint64_t input_operand_id, - uint64_t scale_operand_id, - uint64_t zero_point_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildDequantizeLinear(OperandId input_operand_id, + OperandId scale_operand_id, + OperandId zero_point_operand_id, + OperandId output_operand_id) { mojom::DequantizeLinearPtr dequantize_linear = mojom::DequantizeLinear::New(); dequantize_linear->input_operand_id = input_operand_id; dequantize_linear->scale_operand_id = scale_operand_id; @@ -235,9 +238,9 @@ void GraphInfoBuilder::BuildElementWiseBinary( mojom::ElementWiseBinary::Kind kind, - uint64_t lhs_operand, - uint64_t rhs_operand, - uint64_t output_operand) { + OperandId lhs_operand, + OperandId rhs_operand, + OperandId output_operand) { mojom::ElementWiseBinaryPtr binary = mojom::ElementWiseBinary::New(); binary->kind = kind; binary->lhs_operand_id = lhs_operand; @@ -247,15 +250,15 @@ mojom::Operation::NewElementWiseBinary(std::move(binary))); } -void GraphInfoBuilder::BuildExpand(uint64_t input_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildExpand(OperandId input_operand_id, + OperandId output_operand_id) { graph_info_->operations.push_back(mojom::Operation::NewExpand( mojom::Expand::New(input_operand_id, output_operand_id, ""))); } -void GraphInfoBuilder::BuildMatmul(uint64_t a_operand_id, - uint64_t b_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildMatmul(OperandId a_operand_id, + OperandId b_operand_id, + OperandId output_operand_id) { mojom::MatmulPtr matmul = mojom::Matmul::New(); matmul->a_operand_id = a_operand_id; matmul->b_operand_id = b_operand_id; @@ -265,8 +268,8 @@ } void GraphInfoBuilder::BuildElementWiseUnary(mojom::ElementWiseUnary::Kind kind, - uint64_t input_operand, - uint64_t output_operand) { + OperandId input_operand, + OperandId output_operand) { mojom::ElementWiseUnaryPtr unary = mojom::ElementWiseUnary::New(); unary->kind = kind; unary->input_operand_id = input_operand; @@ -275,9 +278,9 @@ mojom::Operation::NewElementWiseUnary(std::move(unary))); } -void GraphInfoBuilder::BuildGather(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildGather(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId output_operand_id, uint32_t axis) { mojom::GatherPtr gather = mojom::Gather::New(); gather->input_operand_id = input_operand_id; @@ -288,9 +291,9 @@ mojom::Operation::NewGather(std::move(gather))); } -void GraphInfoBuilder::BuildGatherElements(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildGatherElements(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId output_operand_id, uint32_t axis) { auto gather_elements = mojom::GatherElements::New(); gather_elements->input_operand_id = input_operand_id; @@ -301,24 +304,24 @@ mojom::Operation::NewGatherElements(std::move(gather_elements))); } -void GraphInfoBuilder::BuildGatherND(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildGatherND(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId output_operand_id) { auto gather_nd = mojom::GatherND::New(input_operand_id, indices_operand_id, output_operand_id, ""); graph_info_->operations.push_back( mojom::Operation::NewGatherNd(std::move(gather_nd))); } -void GraphInfoBuilder::BuildGelu(uint64_t input_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildGelu(OperandId input_operand_id, + OperandId output_operand_id) { mojom::GeluPtr gelu = mojom::Gelu::New(input_operand_id, output_operand_id, ""); graph_info_->operations.push_back(mojom::Operation::NewGelu(std::move(gelu))); } -void GraphInfoBuilder::BuildHardSigmoid(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildHardSigmoid(OperandId input_operand_id, + OperandId output_operand_id, std::optional<float> alpha, std::optional<float> beta) { mojom::HardSigmoidPtr hard_sigmoid = mojom::HardSigmoid::New(); @@ -334,8 +337,8 @@ mojom::Operation::NewHardSigmoid(std::move(hard_sigmoid))); } -void GraphInfoBuilder::BuildHardSwish(uint64_t input_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildHardSwish(OperandId input_operand_id, + OperandId output_operand_id) { mojom::HardSwishPtr hard_swish = mojom::HardSwish::New(); hard_swish->input_operand_id = input_operand_id; hard_swish->output_operand_id = output_operand_id; @@ -343,9 +346,9 @@ mojom::Operation::NewHardSwish(std::move(hard_swish))); } -void GraphInfoBuilder::BuildPrelu(uint64_t input_operand_id, - uint64_t slope_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildPrelu(OperandId input_operand_id, + OperandId slope_operand_id, + OperandId output_operand_id) { mojom::PreluPtr prelu = mojom::Prelu::New(); prelu->input_operand_id = input_operand_id; prelu->slope_operand_id = slope_operand_id; @@ -354,10 +357,10 @@ mojom::Operation::NewPrelu(std::move(prelu))); } -void GraphInfoBuilder::BuildQuantizeLinear(uint64_t input_operand_id, - uint64_t scale_operand_id, - uint64_t zero_point_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildQuantizeLinear(OperandId input_operand_id, + OperandId scale_operand_id, + OperandId zero_point_operand_id, + OperandId output_operand_id) { mojom::QuantizeLinearPtr quantize_linear = mojom::QuantizeLinear::New(); quantize_linear->input_operand_id = input_operand_id; quantize_linear->scale_operand_id = scale_operand_id; @@ -368,8 +371,8 @@ } void GraphInfoBuilder::BuildReduce(mojom::Reduce::Kind kind, - uint64_t input_operand_id, - uint64_t output_operand_id, + OperandId input_operand_id, + OperandId output_operand_id, std::vector<uint32_t> axes, bool keep_dimensions) { mojom::ReducePtr reduce = mojom::Reduce::New(); @@ -382,16 +385,16 @@ mojom::Operation::NewReduce(std::move(reduce))); } -void GraphInfoBuilder::BuildRelu(uint64_t input_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildRelu(OperandId input_operand_id, + OperandId output_operand_id) { mojom::ReluPtr relu = mojom::Relu::New(); relu->input_operand_id = input_operand_id; relu->output_operand_id = output_operand_id; graph_info_->operations.push_back(mojom::Operation::NewRelu(std::move(relu))); } -void GraphInfoBuilder::BuildReshape(uint64_t input_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildReshape(OperandId input_operand_id, + OperandId output_operand_id) { mojom::ReshapePtr reshape = mojom::Reshape::New(); reshape->input_operand_id = input_operand_id; reshape->output_operand_id = output_operand_id; @@ -399,8 +402,8 @@ mojom::Operation::NewReshape(std::move(reshape))); } -void GraphInfoBuilder::BuildReverse(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildReverse(OperandId input_operand_id, + OperandId output_operand_id, std::vector<uint32_t> axes) { auto reverse = mojom::Reverse::New(); reverse->input_operand_id = input_operand_id; @@ -410,10 +413,10 @@ mojom::Operation::NewReverse(std::move(reverse))); } -void GraphInfoBuilder::BuildScatterElements(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t updates_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildScatterElements(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId updates_operand_id, + OperandId output_operand_id, uint32_t axis) { mojom::ScatterElementsPtr scatter_elements = mojom::ScatterElements::New( input_operand_id, indices_operand_id, updates_operand_id, @@ -422,10 +425,10 @@ mojom::Operation::NewScatterElements(std::move(scatter_elements))); } -void GraphInfoBuilder::BuildScatterND(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t updates_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildScatterND(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId updates_operand_id, + OperandId output_operand_id) { mojom::ScatterNDPtr scatter_nd = mojom::ScatterND::New(input_operand_id, indices_operand_id, updates_operand_id, output_operand_id, ""); @@ -433,8 +436,8 @@ mojom::Operation::NewScatterNd(std::move(scatter_nd))); } -void GraphInfoBuilder::BuildSigmoid(uint64_t input_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildSigmoid(OperandId input_operand_id, + OperandId output_operand_id) { mojom::SigmoidPtr sigmoid = mojom::Sigmoid::New(); sigmoid->input_operand_id = input_operand_id; sigmoid->output_operand_id = output_operand_id; @@ -442,8 +445,8 @@ mojom::Operation::NewSigmoid(std::move(sigmoid))); } -void GraphInfoBuilder::BuildSoftmax(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildSoftmax(OperandId input_operand_id, + OperandId output_operand_id, uint32_t axis) { mojom::SoftmaxPtr softmax = mojom::Softmax::New(input_operand_id, output_operand_id, axis, ""); @@ -451,15 +454,15 @@ mojom::Operation::NewSoftmax(std::move(softmax))); } -void GraphInfoBuilder::BuildSoftplus(uint64_t input_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildSoftplus(OperandId input_operand_id, + OperandId output_operand_id) { auto softplus = mojom::Softplus::New(input_operand_id, output_operand_id, ""); graph_info_->operations.push_back( mojom::Operation::NewSoftplus(std::move(softplus))); } -void GraphInfoBuilder::BuildSoftsign(uint64_t input_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildSoftsign(OperandId input_operand_id, + OperandId output_operand_id) { mojom::SoftsignPtr softsign = mojom::Softsign::New(); softsign->input_operand_id = input_operand_id; softsign->output_operand_id = output_operand_id; @@ -467,16 +470,16 @@ mojom::Operation::NewSoftsign(std::move(softsign))); } -void GraphInfoBuilder::BuildTanh(uint64_t input_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildTanh(OperandId input_operand_id, + OperandId output_operand_id) { mojom::TanhPtr tanh = mojom::Tanh::New(); tanh->input_operand_id = input_operand_id; tanh->output_operand_id = output_operand_id; graph_info_->operations.push_back(mojom::Operation::NewTanh(std::move(tanh))); } -void GraphInfoBuilder::BuildTile(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildTile(OperandId input_operand_id, + OperandId output_operand_id, std::vector<uint32_t> repetitions) { mojom::TilePtr tile = mojom::Tile::New(); tile->input_operand_id = input_operand_id; @@ -485,8 +488,8 @@ graph_info_->operations.push_back(mojom::Operation::NewTile(std::move(tile))); } -void GraphInfoBuilder::BuildTranspose(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildTranspose(OperandId input_operand_id, + OperandId output_operand_id, std::vector<uint32_t> permutation) { mojom::TransposePtr transpose = mojom::Transpose::New(); transpose->input_operand_id = input_operand_id; @@ -496,8 +499,8 @@ mojom::Operation::NewTranspose(std::move(transpose))); } -void GraphInfoBuilder::BuildTriangular(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildTriangular(OperandId input_operand_id, + OperandId output_operand_id, bool upper, int32_t diagonal) { mojom::TriangularPtr triangular = mojom::Triangular::New( @@ -506,10 +509,10 @@ mojom::Operation::NewTriangular(std::move(triangular))); } -void GraphInfoBuilder::BuildWhere(uint64_t condition_operand_id, - uint64_t true_value_operand_id, - uint64_t false_value_operand_id, - uint64_t output_operand_id) { +void GraphInfoBuilder::BuildWhere(OperandId condition_operand_id, + OperandId true_value_operand_id, + OperandId false_value_operand_id, + OperandId output_operand_id) { mojom::WherePtr where = mojom::Where::New(); where->condition_operand_id = condition_operand_id; where->true_value_operand_id = true_value_operand_id; @@ -519,8 +522,8 @@ mojom::Operation::NewWhere(std::move(where))); } -void GraphInfoBuilder::BuildSlice(uint64_t input_operand_id, - uint64_t output_operand_id, +void GraphInfoBuilder::BuildSlice(OperandId input_operand_id, + OperandId output_operand_id, base::span<const uint32_t> starts, base::span<const uint32_t> sizes, base::span<const uint32_t> strides) {
diff --git a/services/webnn/webnn_test_utils.h b/services/webnn/webnn_test_utils.h index 2dd4dba5..96d9228 100644 --- a/services/webnn/webnn_test_utils.h +++ b/services/webnn/webnn_test_utils.h
@@ -12,6 +12,7 @@ #include "base/memory/stack_allocated.h" #include "mojo/public/cpp/bindings/associated_remote.h" #include "services/webnn/public/cpp/operand_descriptor.h" +#include "services/webnn/public/cpp/webnn_types.h" #include "services/webnn/public/mojom/webnn_context_provider.mojom.h" #include "services/webnn/public/mojom/webnn_graph.mojom.h" #include "services/webnn/public/mojom/webnn_graph_builder.mojom.h" @@ -36,45 +37,45 @@ GraphInfoBuilder& operator=(const GraphInfoBuilder&) = delete; ~GraphInfoBuilder(); - uint64_t BuildIntermediateOperand(const std::vector<uint32_t>& dimensions, - OperandDataType type); + OperandId BuildIntermediateOperand(const std::vector<uint32_t>& dimensions, + OperandDataType type); - uint64_t BuildInput(const std::string& name, - const std::vector<uint32_t>& dimensions, - OperandDataType type); - - // Optionally provide `handle` to identify this constant operand; otherwise a - // handle will be generated automatically. - uint64_t BuildConstant(const std::vector<uint32_t>& dimensions, - OperandDataType type, - base::span<const uint8_t> values, - blink::WebNNPendingConstantToken handle = - blink::WebNNPendingConstantToken()); - - void AddOutput(const std::string& name, uint64_t operand_id); - - uint64_t BuildOutput(const std::string& name, + OperandId BuildInput(const std::string& name, const std::vector<uint32_t>& dimensions, OperandDataType type); + // Optionally provide `handle` to identify this constant operand; otherwise a + // handle will be generated automatically. + OperandId BuildConstant(const std::vector<uint32_t>& dimensions, + OperandDataType type, + base::span<const uint8_t> values, + blink::WebNNPendingConstantToken handle = + blink::WebNNPendingConstantToken()); + + void AddOutput(const std::string& name, OperandId operand_id); + + OperandId BuildOutput(const std::string& name, + const std::vector<uint32_t>& dimensions, + OperandDataType type); + void BuildArgMinMax(mojom::ArgMinMax::Kind kind, - uint64_t input_operand_id, - uint64_t output_operand_id, + OperandId input_operand_id, + OperandId output_operand_id, uint32_t axis, bool keep_dimensions); // A `BatchNormalizationAttributes` type should have the following members: // struct BatchNormalizationAttributes { - // std::optional<uint64_t> scale_operand_id; - // std::optional<uint64_t> bias_operand_id; + // std::optional<OperandId> scale_operand_id; + // std::optional<OperandId> bias_operand_id; // uint32_t axis = 1; // float epsilon = 1e-5; // }; template <typename BatchNormalizationAttributes> - void BuildBatchNormalization(uint64_t input_operand_id, - uint64_t mean_operand_id, - uint64_t variance_operand_id, - uint64_t output_operand_id, + void BuildBatchNormalization(OperandId input_operand_id, + OperandId mean_operand_id, + OperandId variance_operand_id, + OperandId output_operand_id, const BatchNormalizationAttributes& attributes) { mojom::BatchNormalizationPtr batch_normalization = mojom::BatchNormalization::New(); @@ -92,13 +93,13 @@ std::move(batch_normalization))); } - void BuildClamp(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildClamp(OperandId input_operand_id, + OperandId output_operand_id, float min_value, float max_value); - void BuildConcat(std::vector<uint64_t> input_operand_ids, - uint64_t output_operand_id, + void BuildConcat(std::vector<OperandId> input_operand_ids, + OperandId output_operand_id, uint32_t axis); // A `Conv2dAttributes` type should have the following members: @@ -107,15 +108,15 @@ // std::vector<uint32_t> strides; // std::vector<uint32_t> dilations; // uint32_t groups; - // std::optional<uint64_t> bias_operand_id, + // std::optional<OperandId> bias_operand_id, // }; template <typename Conv2dAttributes> void BuildConv2d(mojom::Conv2d::Kind type, - uint64_t input_operand_id, - uint64_t filter_operand_id, - uint64_t output_operand_id, + OperandId input_operand_id, + OperandId filter_operand_id, + OperandId output_operand_id, const Conv2dAttributes& attributes, - std::optional<uint64_t> bias_operand_id) { + std::optional<OperandId> bias_operand_id) { mojom::Conv2dPtr conv2d = mojom::Conv2d::New(); conv2d->input_operand_id = input_operand_id; conv2d->filter_operand_id = filter_operand_id; @@ -142,60 +143,60 @@ mojom::Operation::NewConv2d(std::move(conv2d))); } - void BuildCumulativeSum(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildCumulativeSum(OperandId input_operand_id, + OperandId output_operand_id, uint32_t axis, std::optional<bool> exclusive, std::optional<bool> reversed); - void BuildDequantizeLinear(uint64_t input_operand_id, - uint64_t scale_operand_id, - uint64_t zero_point_operand_id, - uint64_t output_operand_id); + void BuildDequantizeLinear(OperandId input_operand_id, + OperandId scale_operand_id, + OperandId zero_point_operand_id, + OperandId output_operand_id); void BuildElementWiseBinary(mojom::ElementWiseBinary::Kind kind, - uint64_t lhs_operand, - uint64_t rhs_operand, - uint64_t output_operand); + OperandId lhs_operand, + OperandId rhs_operand, + OperandId output_operand); - void BuildElu(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildElu(OperandId input_operand_id, + OperandId output_operand_id, float alpha); void BuildElementWiseUnary(mojom::ElementWiseUnary::Kind kind, - uint64_t input_operand, - uint64_t output_operand); + OperandId input_operand, + OperandId output_operand); - void BuildExpand(uint64_t input_operand_id, uint64_t output_operand_id); + void BuildExpand(OperandId input_operand_id, OperandId output_operand_id); - void BuildGather(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t output_operand_id, + void BuildGather(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId output_operand_id, uint32_t axis); - void BuildGatherElements(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t output_operand_id, + void BuildGatherElements(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId output_operand_id, uint32_t axis); - void BuildGatherND(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t output_operand_id); + void BuildGatherND(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId output_operand_id); - void BuildGelu(uint64_t input_operand_id, uint64_t output_operand_id); + void BuildGelu(OperandId input_operand_id, OperandId output_operand_id); // A `GemmAttributes` type should have the following members: // struct GemmAttributes { - // std::optional<uint64_t> c_operand_id, + // std::optional<OperandId> c_operand_id, // float alpha = 1.0; // float beta = 1.0; // bool a_transpose = false; // bool b_transpose = false; // }; template <typename GemmAttributes> - void BuildGemm(uint64_t a_operand_id, - uint64_t b_operand_id, - uint64_t output_operand_id, + void BuildGemm(OperandId a_operand_id, + OperandId b_operand_id, + OperandId output_operand_id, const GemmAttributes& attributes) { mojom::GemmPtr gemm = mojom::Gemm::New(); gemm->a_operand_id = a_operand_id; @@ -214,9 +215,9 @@ // A `GruAttributes` type should have the following members: // struct GruAttributes { - // std::optional<uint64_t> bias_operand_id; - // std::optional<uint64_t> recurrent_bias_operand_id; - // std::optional<uint64_t> initial_hidden_state_operand_id; + // std::optional<OperandId> bias_operand_id; + // std::optional<OperandId> recurrent_bias_operand_id; + // std::optional<OperandId> initial_hidden_state_operand_id; // bool reset_after; // bool return_sequence; // mojom::RecurrentNetworkDirection direction; @@ -224,10 +225,10 @@ // std::vector<mojom::RecurrentNetworkActivation> activations; // }; template <typename GruAttributes> - void BuildGru(uint64_t input_operand_id, - uint64_t weight_operand_id, - uint64_t recurrent_weight_operand_id, - std::vector<uint64_t> output_operand_ids, + void BuildGru(OperandId input_operand_id, + OperandId weight_operand_id, + OperandId recurrent_weight_operand_id, + std::vector<OperandId> output_operand_ids, uint32_t steps, uint32_t hidden_size, const GruAttributes& attributes) { @@ -254,18 +255,18 @@ // A `GruCellAttributes` type should have the following members: // struct GruCellAttributes { - // std::optional<uint64_t> bias_operand_id; - // std::optional<uint64_t> recurrent_bias_operand_id; + // std::optional<OperandId> bias_operand_id; + // std::optional<OperandId> recurrent_bias_operand_id; // bool reset_after; // mojom::GruWeightLayout layout; // std::vector<mojom::RecurrentNetworkActivation> activations; // }; template <typename GruCellAttributes> - void BuildGruCell(uint64_t input_operand_id, - uint64_t weight_operand_id, - uint64_t recurrent_weight_operand_id, - uint64_t hidden_state_operand_id, - uint64_t output_operand_id, + void BuildGruCell(OperandId input_operand_id, + OperandId weight_operand_id, + OperandId recurrent_weight_operand_id, + OperandId hidden_state_operand_id, + OperandId output_operand_id, uint32_t hidden_size, const GruCellAttributes& attributes) { mojom::GruCellPtr gru_cell = mojom::GruCell::New( @@ -278,23 +279,23 @@ mojom::Operation::NewGruCell(std::move(gru_cell))); } - void BuildHardSigmoid(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildHardSigmoid(OperandId input_operand_id, + OperandId output_operand_id, std::optional<float> alpha, std::optional<float> beta); - void BuildHardSwish(uint64_t input_operand_id, uint64_t output_operand_id); + void BuildHardSwish(OperandId input_operand_id, OperandId output_operand_id); // A `LayerNormalizationAttributes` type should have the following members: // struct LayerNormalizationAttributes { - // std::optional<uint64_t> scale_operand_id; - // std::optional<uint64_t> bias_operand_id; + // std::optional<OperandId> scale_operand_id; + // std::optional<OperandId> bias_operand_id; // std::vector<uint32_t> axes; // float epsilon = 1e-5; // }; template <typename LayerNormalizationAttributes> - void BuildLayerNormalization(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildLayerNormalization(OperandId input_operand_id, + OperandId output_operand_id, const LayerNormalizationAttributes& attributes) { mojom::LayerNormalizationPtr layer_normalization = mojom::LayerNormalization::New(); @@ -312,21 +313,21 @@ // A `LstmAttributes` type should have the following members: // struct LstmAttributes { - // std::optional<uint64_t> bias_operand_id; - // std::optional<uint64_t> recurrent_bias_operand_id; - // std::optional<uint64_t> peephole_weight_operand_id; - // std::optional<uint64_t> initial_hidden_state_operand_id; - // std::optional<uint64_t> initial_cell_state_operand_id; + // std::optional<OperandId> bias_operand_id; + // std::optional<OperandId> recurrent_bias_operand_id; + // std::optional<OperandId> peephole_weight_operand_id; + // std::optional<OperandId> initial_hidden_state_operand_id; + // std::optional<OperandId> initial_cell_state_operand_id; // bool return_sequence; // mojom::RecurrentNetworkDirection direction; // mojom::LstmWeightLayout layout; // std::vector<mojom::RecurrentNetworkActivation> activations; // }; template <typename LstmAttributes> - void BuildLstm(uint64_t input_operand_id, - uint64_t weight_operand_id, - uint64_t recurrent_weight_operand_id, - std::vector<uint64_t> output_operand_ids, + void BuildLstm(OperandId input_operand_id, + OperandId weight_operand_id, + OperandId recurrent_weight_operand_id, + std::vector<OperandId> output_operand_ids, uint32_t steps, uint32_t hidden_size, const LstmAttributes& attributes) { @@ -356,19 +357,19 @@ // A `LstmCellAttributes` type should have the following members: // struct LstmCellAttributes { - // std::optional<uint64_t> bias_operand_id; - // std::optional<uint64_t> recurrent_bias_operand_id; - // std::optional<uint64_t> peephole_weight_operand_id; + // std::optional<OperandId> bias_operand_id; + // std::optional<OperandId> recurrent_bias_operand_id; + // std::optional<OperandId> peephole_weight_operand_id; // mojom::LstmWeightLayout layout; // std::vector<mojom::RecurrentNetworkActivation> activations; // }; template <typename LstmCellAttributes> - void BuildLstmCell(uint64_t input_operand_id, - uint64_t weight_operand_id, - uint64_t recurrent_weight_operand_id, - uint64_t hidden_state_operand_id, - uint64_t cell_state_operand_id, - std::vector<uint64_t> output_operand_ids, + void BuildLstmCell(OperandId input_operand_id, + OperandId weight_operand_id, + OperandId recurrent_weight_operand_id, + OperandId hidden_state_operand_id, + OperandId cell_state_operand_id, + std::vector<OperandId> output_operand_ids, uint32_t hidden_size, const LstmCellAttributes& attributes) { auto lstm_cell = mojom::LstmCell::New( @@ -385,14 +386,14 @@ // A `InstanceNormalizationAttributes` type should have the following members: // struct InstanceNormalizationAttributes { - // std::optional<uint64_t> scale_operand_id; - // std::optional<uint64_t> bias_operand_id; + // std::optional<OperandId> scale_operand_id; + // std::optional<OperandId> bias_operand_id; // float epsilon = 1e-5; // }; template <typename InstanceNormalizationAttributes> void BuildInstanceNormalization( - uint64_t input_operand_id, - uint64_t output_operand_id, + OperandId input_operand_id, + OperandId output_operand_id, const InstanceNormalizationAttributes& attributes) { mojom::InstanceNormalizationPtr instance_normalization = mojom::InstanceNormalization::New(); @@ -408,21 +409,21 @@ std::move(instance_normalization))); } - void BuildLeakyRelu(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildLeakyRelu(OperandId input_operand_id, + OperandId output_operand_id, float alpha); - void BuildLinear(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildLinear(OperandId input_operand_id, + OperandId output_operand_id, float alpha, float beta); - void BuildMatmul(uint64_t a_operand_id, - uint64_t b_operand_id, - uint64_t output_operand_id); + void BuildMatmul(OperandId a_operand_id, + OperandId b_operand_id, + OperandId output_operand_id); - void BuildPad(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildPad(OperandId input_operand_id, + OperandId output_operand_id, const std::vector<uint32_t>& beginning_padding, const std::vector<uint32_t>& ending_padding, mojom::PaddingMode::Tag mode, @@ -437,8 +438,8 @@ // }; template <typename Pool2dAttributes> void BuildPool2d(mojom::Pool2d::Kind kind, - uint64_t input_operand_id, - uint64_t output_operand_id, + OperandId input_operand_id, + OperandId output_operand_id, const Pool2dAttributes& attributes) { mojom::Pool2dPtr pool2d = mojom::Pool2d::New(); pool2d->kind = kind; @@ -466,22 +467,22 @@ mojom::Operation::NewPool2d(std::move(pool2d))); } - void BuildPrelu(uint64_t input_operand_id, - uint64_t slope_operand_id, - uint64_t output_operand_id); + void BuildPrelu(OperandId input_operand_id, + OperandId slope_operand_id, + OperandId output_operand_id); - void BuildQuantizeLinear(uint64_t input_operand_id, - uint64_t scale_operand_id, - uint64_t zero_point_operand_id, - uint64_t output_operand_id); + void BuildQuantizeLinear(OperandId input_operand_id, + OperandId scale_operand_id, + OperandId zero_point_operand_id, + OperandId output_operand_id); void BuildReduce(mojom::Reduce::Kind kind, - uint64_t input_operand_id, - uint64_t output_operand_id, + OperandId input_operand_id, + OperandId output_operand_id, std::vector<uint32_t> axes, bool keep_dimensions); - void BuildRelu(uint64_t input_operand_id, uint64_t output_operand_id); + void BuildRelu(OperandId input_operand_id, OperandId output_operand_id); // A `Resample2dAttributes` type should have the following members: // struct Resample2dAttributes { @@ -490,8 +491,8 @@ // std::optional<std::vector<float>> scales; // std::vector<uint32_t> axes = {2, 3};}; template <typename Resample2dAttributes> - void BuildResample2d(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildResample2d(OperandId input_operand_id, + OperandId output_operand_id, const Resample2dAttributes& attributes) { mojom::Resample2dPtr resample2d = mojom::Resample2d::New(); resample2d->input_operand_id = input_operand_id; @@ -506,59 +507,59 @@ mojom::Operation::NewResample2d(std::move(resample2d))); } - void BuildReshape(uint64_t input_operand_id, uint64_t output_operand_id); + void BuildReshape(OperandId input_operand_id, OperandId output_operand_id); - void BuildReverse(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildReverse(OperandId input_operand_id, + OperandId output_operand_id, std::vector<uint32_t> axes); - void BuildScatterElements(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t updates_operand_id, - uint64_t output_operand_id, + void BuildScatterElements(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId updates_operand_id, + OperandId output_operand_id, uint32_t axis); - void BuildScatterND(uint64_t input_operand_id, - uint64_t indices_operand_id, - uint64_t updates_operand_id, - uint64_t output_operand_id); + void BuildScatterND(OperandId input_operand_id, + OperandId indices_operand_id, + OperandId updates_operand_id, + OperandId output_operand_id); - void BuildSigmoid(uint64_t input_operand_id, uint64_t output_operand_id); + void BuildSigmoid(OperandId input_operand_id, OperandId output_operand_id); - void BuildSoftmax(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildSoftmax(OperandId input_operand_id, + OperandId output_operand_id, uint32_t axis); - void BuildSoftplus(uint64_t input_operand_id, uint64_t output_operand_id); + void BuildSoftplus(OperandId input_operand_id, OperandId output_operand_id); - void BuildSoftsign(uint64_t input_operand_id, uint64_t output_operand_id); + void BuildSoftsign(OperandId input_operand_id, OperandId output_operand_id); - void BuildSplit(uint64_t input_operand_id, - const std::vector<uint64_t>& output_operand_ids, + void BuildSplit(OperandId input_operand_id, + const std::vector<OperandId>& output_operand_ids, uint32_t axis); - void BuildTanh(uint64_t input_operand_id, uint64_t output_operand_id); + void BuildTanh(OperandId input_operand_id, OperandId output_operand_id); - void BuildTile(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildTile(OperandId input_operand_id, + OperandId output_operand_id, std::vector<uint32_t> repetitions); - void BuildTranspose(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildTranspose(OperandId input_operand_id, + OperandId output_operand_id, std::vector<uint32_t> permutation); - void BuildTriangular(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildTriangular(OperandId input_operand_id, + OperandId output_operand_id, bool upper, int32_t diagonal); - void BuildWhere(uint64_t condition_operand_id, - uint64_t true_value_operand_id, - uint64_t false_value_operand_id, - uint64_t output_operand_id); + void BuildWhere(OperandId condition_operand_id, + OperandId true_value_operand_id, + OperandId false_value_operand_id, + OperandId output_operand_id); - void BuildSlice(uint64_t input_operand_id, - uint64_t output_operand_id, + void BuildSlice(OperandId input_operand_id, + OperandId output_operand_id, base::span<const uint32_t> starts, base::span<const uint32_t> sizes, base::span<const uint32_t> strides); @@ -575,13 +576,13 @@ const ContextProperties& context_properties); private: - uint64_t BuildOperand( + OperandId BuildOperand( const std::vector<uint32_t>& dimensions, OperandDataType type, mojom::Operand::Kind kind = mojom::Operand::Kind::kOutput); mojom::GraphInfoPtr graph_info_; - uint64_t operand_id_ = 1; + OperandId next_operand_id_ = 1; base::raw_ref<mojo::AssociatedRemote<mojom::WebNNGraphBuilder>> graph_builder_remote_;
diff --git a/storage/browser/quota/quota_manager_impl.cc b/storage/browser/quota/quota_manager_impl.cc index d333962e..85ddf5ee 100644 --- a/storage/browser/quota/quota_manager_impl.cc +++ b/storage/browser/quota/quota_manager_impl.cc
@@ -148,10 +148,11 @@ class QuotaManagerImpl::UsageAndQuotaInfoGatherer : public QuotaTask { public: - UsageAndQuotaInfoGatherer(QuotaManagerImpl* manager, - const StorageKey& storage_key, - bool is_incognito, - UsageAndQuotaForDevtoolsCallback callback) + UsageAndQuotaInfoGatherer( + QuotaManagerImpl* manager, + const StorageKey& storage_key, + bool is_incognito, + UsageAndQuotaWithBreakdownAndOverrideFlagCallback callback) : QuotaTask(manager), storage_key_(storage_key), callback_(std::move(callback)), @@ -161,10 +162,11 @@ DCHECK(callback_); } - UsageAndQuotaInfoGatherer(QuotaManagerImpl* manager, - const BucketInfo& bucket_info, - bool is_incognito, - UsageAndQuotaForDevtoolsCallback callback) + UsageAndQuotaInfoGatherer( + QuotaManagerImpl* manager, + const BucketInfo& bucket_info, + bool is_incognito, + UsageAndQuotaWithBreakdownAndOverrideFlagCallback callback) : UsageAndQuotaInfoGatherer(manager, bucket_info.storage_key, is_incognito, @@ -331,7 +333,7 @@ // Non-null iff usage info is to be gathered for an individual bucket. If // null, usage is gathered for all buckets in the given host/StorageKey. std::optional<BucketInfo> bucket_info_; - QuotaManagerImpl::UsageAndQuotaForDevtoolsCallback callback_; + QuotaManagerImpl::UsageAndQuotaWithBreakdownAndOverrideFlagCallback callback_; const bool is_unlimited_; const bool is_incognito_; @@ -1203,7 +1205,7 @@ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(callback); - GetUsageAndQuotaForDevtools( + HandleGetUsageAndQuotaRequest( storage_key, base::BindOnce(&DidGetUsageAndQuotaStripOverride, std::move(callback))); } @@ -1216,7 +1218,7 @@ if (base::FeatureList::IsEnabled(storage::features::kStaticStorageQuota) && !IsStorageUnlimited(storage_key)) { - GetUsageAndQuotaForDevtools( + HandleGetUsageAndQuotaRequest( storage_key, base::BindOnce( [](UsageAndQuotaWithBreakdownCallback callback, @@ -1232,14 +1234,22 @@ return; } - GetUsageAndQuotaForDevtools( + HandleGetUsageAndQuotaRequest( storage_key, base::BindOnce(&DidGetUsageAndQuotaStripOverride, std::move(callback))); } void QuotaManagerImpl::GetUsageAndQuotaForDevtools( const StorageKey& storage_key, - UsageAndQuotaForDevtoolsCallback callback) { + UsageAndQuotaWithBreakdownAndOverrideFlagCallback callback) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(callback); + HandleGetUsageAndQuotaRequest(storage_key, std::move(callback)); +} + +void QuotaManagerImpl::HandleGetUsageAndQuotaRequest( + const StorageKey& storage_key, + UsageAndQuotaWithBreakdownAndOverrideFlagCallback callback) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(callback); EnsureDatabaseOpened();
diff --git a/storage/browser/quota/quota_manager_impl.h b/storage/browser/quota/quota_manager_impl.h index f692b9c..81b986b 100644 --- a/storage/browser/quota/quota_manager_impl.h +++ b/storage/browser/quota/quota_manager_impl.h
@@ -147,7 +147,7 @@ int64_t quota, blink::mojom::UsageBreakdownPtr usage_breakdown)>; - using UsageAndQuotaForDevtoolsCallback = + using UsageAndQuotaWithBreakdownAndOverrideFlagCallback = base::OnceCallback<void(blink::mojom::QuotaStatusCode, int64_t usage, int64_t quota, @@ -269,7 +269,7 @@ // Called by DevTools. virtual void GetUsageAndQuotaForDevtools( const blink::StorageKey& storage_key, - UsageAndQuotaForDevtoolsCallback callback); + UsageAndQuotaWithBreakdownAndOverrideFlagCallback callback); // Called by storage backends. // @@ -699,6 +699,9 @@ void GetUsageAndQuotaWithBreakdown( const blink::StorageKey& storage_key, UsageAndQuotaWithBreakdownCallback callback); + void HandleGetUsageAndQuotaRequest( + const blink::StorageKey& storage_key, + UsageAndQuotaWithBreakdownAndOverrideFlagCallback callback); void GetQuotaSettings(QuotaSettingsCallback callback); void DidGetSettings(std::optional<QuotaSettings> settings); void GetStorageCapacity(StorageCapacityCallback callback);
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 34f157f..30227f02 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -13030,7 +13030,8 @@ { "name": "Enabled", "enable_features": [ - "LCPPPrefetchSubresource" + "LCPPPrefetchSubresource", + "LCPPPrefetchSubresourceAsync" ] } ] @@ -15945,7 +15946,8 @@ "PartitionAllocSchedulerLoopQuarantine", "PartitionAllocWithAdvancedChecks", "PartitionAllocZappingByFreeFlags" - ] + ], + "disable_benchmarking": "true" } ] }
diff --git a/third_party/angle b/third_party/angle index 432d1d1..3b77a17 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit 432d1d1efdbd0e8d5788529fe193e0eb1e8456bf +Subproject commit 3b77a177ba09c418046d232e7f16dd402f10ef1c
diff --git a/third_party/blink/common/features.cc b/third_party/blink/common/features.cc index f04610d..8222b48 100644 --- a/third_party/blink/common/features.cc +++ b/third_party/blink/common/features.cc
@@ -1671,6 +1671,10 @@ "LCPPPrefetchSubresource", base::FEATURE_DISABLED_BY_DEFAULT); +BASE_FEATURE(kLCPPPrefetchSubresourceAsync, + "LCPPPrefetchSubresourceAsync", + base::FEATURE_DISABLED_BY_DEFAULT); + BASE_FEATURE(kHttpDiskCachePrewarming, "HttpDiskCachePrewarming", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/third_party/blink/public/common/features.h b/third_party/blink/public/common/features.h index bfdbf2c..1095714 100644 --- a/third_party/blink/public/common/features.h +++ b/third_party/blink/public/common/features.h
@@ -1140,6 +1140,9 @@ // cache data. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLCPPPrefetchSubresource); +// If enabled, doing prefetch task async after main resource fetching. +BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kLCPPPrefetchSubresourceAsync); + // If enabled, prewarm HTTP disk cache based on the previous navigation. BLINK_COMMON_EXPORT BASE_DECLARE_FEATURE(kHttpDiskCachePrewarming);
diff --git a/third_party/blink/public/common/service_worker/service_worker_subresource_load_metrics.h b/third_party/blink/public/common/service_worker/service_worker_subresource_load_metrics.h index a886c70c..1a843f3c 100644 --- a/third_party/blink/public/common/service_worker/service_worker_subresource_load_metrics.h +++ b/third_party/blink/public/common/service_worker/service_worker_subresource_load_metrics.h
@@ -136,6 +136,11 @@ // Routing API, from navigation start till onload event. uint32_t matched_race_network_and_fetch_router_source_count = 0; + // Total number of sub-resources which were matched to the + // `RouterSourceEnum.race-network-and-cache` in ServiceWorker Static + // Routing API, from navigation start till onload event. + uint32_t matched_race_network_and_cache_router_source_count = 0; + // Total router evaluation time of ServiceWorker Static Routing API // for sub-resources. base::TimeDelta total_router_evaluation_time_for_subresources; @@ -183,6 +188,8 @@ other.matched_cache_router_source_count && matched_race_network_and_fetch_router_source_count == other.matched_race_network_and_fetch_router_source_count && + matched_race_network_and_cache_router_source_count == + other.matched_race_network_and_cache_router_source_count && total_router_evaluation_time_for_subresources == other.total_router_evaluation_time_for_subresources && total_cache_lookup_time_for_subresources ==
diff --git a/third_party/blink/renderer/modules/ai/ai.idl b/third_party/blink/renderer/modules/ai/ai.idl index d024739..9eb32bc4 100644 --- a/third_party/blink/renderer/modules/ai/ai.idl +++ b/third_party/blink/renderer/modules/ai/ai.idl
@@ -8,6 +8,7 @@ // for LanguageModel instead. [ Exposed(Window AIPromptAPI, Worker AIPromptAPIForWorkers), + RuntimeEnabled=AIPromptAPI, SecureContext ] interface AI {};
diff --git a/third_party/blink/renderer/modules/ai/language_model.idl b/third_party/blink/renderer/modules/ai/language_model.idl index a55cbed3..95f846e 100644 --- a/third_party/blink/renderer/modules/ai/language_model.idl +++ b/third_party/blink/renderer/modules/ai/language_model.idl
@@ -15,6 +15,7 @@ [ Exposed(Window AIPromptAPI, Worker AIPromptAPIForWorkers), + RuntimeEnabled=AIPromptAPI, SecureContext ] interface LanguageModel : EventTarget {
diff --git a/third_party/blink/renderer/modules/ai/language_model_factory.idl b/third_party/blink/renderer/modules/ai/language_model_factory.idl index 64dc38b6..e9abc2d 100644 --- a/third_party/blink/renderer/modules/ai/language_model_factory.idl +++ b/third_party/blink/renderer/modules/ai/language_model_factory.idl
@@ -9,6 +9,7 @@ [ Exposed(Window AIPromptAPI, Worker AIPromptAPIForWorkers), + RuntimeEnabled=AIPromptAPI, SecureContext ] interface LanguageModelFactory {
diff --git a/third_party/blink/renderer/modules/ai/language_model_params.idl b/third_party/blink/renderer/modules/ai/language_model_params.idl index 6d0c751..2ab22da 100644 --- a/third_party/blink/renderer/modules/ai/language_model_params.idl +++ b/third_party/blink/renderer/modules/ai/language_model_params.idl
@@ -6,6 +6,7 @@ [ Exposed(Window AIPromptAPI, Worker AIPromptAPIForWorkers), + RuntimeEnabled=AIPromptAPI, SecureContext ] interface LanguageModelParams {
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc index 506cc99..d656a6fe 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -3551,7 +3551,7 @@ metrics.matched_race_network_and_fetch_router_source_count++; break; case network::mojom::ServiceWorkerRouterSourceType::kRaceNetworkAndCache: - // TODO(crbug.com/370844790): implement race network and cache + metrics.matched_race_network_and_cache_router_source_count++; break; } }
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 8663620..a9f2490f 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -342,11 +342,7 @@ { name: "AIPromptAPIForWorkers", public: true, - origin_trial_feature_name: "AIPromptAPIForExtension", - origin_trial_allows_third_party: true, status: "experimental", - base_feature_status: "enabled", - copied_from_base_feature_if: "overridden", }, { name: "AIPromptAPIMultimodalInput",
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 236d7ef9..d31fbdc 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -9179,7 +9179,7 @@ # Gardener 2025-04-28 crbug.com/414234413 [ Mac13-arm64 ] http/tests/devtools/elements/styles-1/edit-value-with-trimmed-url.js [ Failure Pass ] -# Gardener 2025-04-28. Failes on WebKit Linux ASAN +# Gardener 2025-04-28. Fails on WebKit Linux ASAN crbug.com/414243950 [ Linux ] virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.html?cpu [ Crash ] crbug.com/414243950 [ Linux ] virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.serviceworker.html?cpu [ Crash ] crbug.com/414243950 [ Linux ] virtual/webnn-service-on-cpu/external/wpt/webnn/conformance_tests/qdq_subgraph.https.any.sharedworker.html?cpu [ Crash ] @@ -9187,3 +9187,6 @@ # Gardener 2025-04-30 crbug.com/324536287 external/wpt/soft-navigation-heuristics/interaction-with-paint-before-back.tentative.html [ Failure Pass ] + +# Gardener 2025-05-01 +crbug.com/411161567 [ Linux ] accessibility/interest-target.html [ Failure Pass ]
diff --git a/third_party/catapult b/third_party/catapult index 0f4bac5..1591e81 160000 --- a/third_party/catapult +++ b/third_party/catapult
@@ -1 +1 @@ -Subproject commit 0f4bac59a38c6aa5ad9874778f822d76ea737d35 +Subproject commit 1591e813b66e04a5b9d9e8fc5d94e74ef4effaa1
diff --git a/third_party/compiler-rt/src b/third_party/compiler-rt/src index cf8cac9..6558e6a 160000 --- a/third_party/compiler-rt/src +++ b/third_party/compiler-rt/src
@@ -1 +1 @@ -Subproject commit cf8cac9f64ff4ac6fd2041a699dd86f717c63586 +Subproject commit 6558e6a3eacafd269527cf2595e0e722f117c1e6
diff --git a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc index 03d7cfa..3a6e194 100644 --- a/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc +++ b/third_party/crashpad/crashpad/snapshot/mac/process_reader_mac_test.cc
@@ -836,7 +836,9 @@ MacOSVersionNumber() >= 10'07'00; } -TEST(ProcessReaderMac, SelfModules) { +// Disabled to investigate crbug.com/414919209. +// TODO(crbug.com/414919209): Re-enable or remove if no longer relevant. +TEST(ProcessReaderMac, DISABLED_SelfModules) { ScopedOpenCLNoOpKernel ensure_cl_kernels; ASSERT_NO_FATAL_FAILURE(ensure_cl_kernels.SetUp()); @@ -1023,7 +1025,9 @@ bool ensure_cl_kernels_success_; }; -TEST(ProcessReaderMac, ChildModules) { +// Disabled to investigate crbug.com/414919209. +// TODO(crbug.com/414919209): Re-enable or remove if no longer relevant. +TEST(ProcessReaderMac, DISABLED_ChildModules) { ScopedOpenCLNoOpKernel ensure_cl_kernels; ASSERT_NO_FATAL_FAILURE(ensure_cl_kernels.SetUp());
diff --git a/third_party/depot_tools b/third_party/depot_tools index e659674..354f602 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit e6596746dc95fe658b3a5f0924c10e322c7d8e22 +Subproject commit 354f6026f14f87466040e3e1878c599138a23bce
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 6c841fc..503afe0 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 6c841fc0da4e1eeec9f198fd14167572e1f6656a +Subproject commit 503afe09a5c33d317399ceb4278bcd59b2f3de0b
diff --git a/third_party/googletest/src b/third_party/googletest/src index 59c924b..04ee1b4 160000 --- a/third_party/googletest/src +++ b/third_party/googletest/src
@@ -1 +1 @@ -Subproject commit 59c924bc471cefea25a7cf7eb40b6c101b170b12 +Subproject commit 04ee1b4f2aefdffb0135d7cf2a2c519fe50dabe4
diff --git a/third_party/hunspell/README.chromium b/third_party/hunspell/README.chromium index 0a76a7f4..af8b153 100644 --- a/third_party/hunspell/README.chromium +++ b/third_party/hunspell/README.chromium
@@ -1,6 +1,6 @@ Name: hunspell URL: http://hunspell.sourceforge.net/ -Version: v1.7.1 +Version: 18f4056 CPEPrefix: cpe:/a:hunspell_project:hunspell:1.7.1 License: MPL-1.1 License File: COPYING.MPL @@ -8,7 +8,7 @@ Shipped: yes Description: -This is a partial copy of Hunspell v1.7.1 with the following changes: +This is a partial copy of Hunspell 18f4056 with the following changes: * Move README.md onto the README symlink. * Change src/hunspell/filemgr.hxx and src/hunspell/filemgr.cxx to use LineIterator. @@ -34,7 +34,7 @@ 2) Checkout hunspell: $ git clone https://github.com/hunspell/hunspell.git $ cd hunspell - $ git checkout v1.7.1 + $ git checkout 18f4056 3) Apply Hunspell patches and make a throwaway commit: $ patch -p1 --no-backup-if-mismatch -i $CHROMIUM_HUNSPELL/correction-of-a-knowingly-false-condition.patch $ patch -p1 --no-backup-if-mismatch -i $CHROMIUM_HUNSPELL/speed-up-hunspell-inner-loop.patch
diff --git a/third_party/hunspell/README.md b/third_party/hunspell/README.md index 90ef880..3145e43 100644 --- a/third_party/hunspell/README.md +++ b/third_party/hunspell/README.md
@@ -307,6 +307,18 @@ # or better, use pkg-config g++ $(pkg-config --cflags --libs hunspell) example.cxx +# Installing Hunspell (vcpkg) + +Alternatively, you can build and install hunspell using [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager: + + git clone https://github.com/Microsoft/vcpkg.git + cd vcpkg + ./bootstrap-vcpkg.sh + ./vcpkg integrate install + ./vcpkg install hunspell + +The hunspell port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository. + ## Dictionaries Hunspell (MySpell) dictionaries:
diff --git a/third_party/hunspell/google.patch b/third_party/hunspell/google.patch index 553c0fd4..8d0ab01fa6 100644 --- a/third_party/hunspell/google.patch +++ b/third_party/hunspell/google.patch
@@ -1,5 +1,5 @@ diff --git a/src/hunspell/affixmgr.cxx b/src/hunspell/affixmgr.cxx -index 2f38b93..6bdec4e 100644 +index c49be5b..71790df 100644 --- a/src/hunspell/affixmgr.cxx +++ b/src/hunspell/affixmgr.cxx @@ -86,11 +86,19 @@ @@ -128,7 +128,7 @@ } finishFileMgr(afflst); -@@ -1271,6 +1328,24 @@ std::string AffixMgr::prefix_check_twosfx_morph(const char* word, +@@ -1277,6 +1334,24 @@ std::string AffixMgr::prefix_check_twosfx_morph(const char* word, // Is word a non-compound with a REP substitution (see checkcompoundrep)? int AffixMgr::cpdrep_check(const char* word, int wl) { @@ -144,7 +144,7 @@ + while ((r=strstr(r, pattern)) != NULL) { + std::string candidate(word); + candidate.replace(r-word, lenp, pattern2); -+ if (candidate_check(candidate.c_str(), candidate.size())) return 1; ++ if (candidate_check(candidate)) return 1; + r++; // search for the next letter + } + } @@ -153,7 +153,7 @@ if ((wl < 2) || get_reptable().empty()) return 0; -@@ -1289,6 +1364,7 @@ int AffixMgr::cpdrep_check(const char* word, int wl) { +@@ -1295,6 +1370,7 @@ int AffixMgr::cpdrep_check(const char* word, int wl) { } } } @@ -161,15 +161,15 @@ return 0; } -@@ -4470,6 +4546,7 @@ bool AffixMgr::parse_affix(const std::string& line, +@@ -4480,6 +4556,7 @@ bool AffixMgr::parse_affix(const std::string& line, case 1: { np++; - aflag = pHMgr->decode_flag(std::string(start_piece, iter).c_str()); + aflag = pHMgr->decode_flag(std::string(start_piece, iter)); +#ifndef HUNSPELL_CHROME_CLIENT // We don't check for duplicates. if (((at == 'S') && (dupflags[aflag] & dupSFX)) || ((at == 'P') && (dupflags[aflag] & dupPFX))) { HUNSPELL_WARNING( -@@ -4478,6 +4555,7 @@ bool AffixMgr::parse_affix(const std::string& line, +@@ -4488,6 +4565,7 @@ bool AffixMgr::parse_affix(const std::string& line, af->getlinenum()); } dupflags[aflag] += (char)((at == 'S') ? dupSFX : dupPFX); @@ -178,7 +178,7 @@ } // piece 3 - is cross product indicator diff --git a/src/hunspell/affixmgr.hxx b/src/hunspell/affixmgr.hxx -index 450f50a..ea2ee98 100644 +index 836ebe0..1e9c4f1 100644 --- a/src/hunspell/affixmgr.hxx +++ b/src/hunspell/affixmgr.hxx @@ -89,6 +89,40 @@ @@ -242,7 +242,7 @@ ~AffixMgr(); struct hentry* affix_check(const char* word, int len, -@@ -334,6 +376,10 @@ class AffixMgr { +@@ -333,6 +375,10 @@ class AffixMgr { int get_fullstrip() const; private: @@ -335,10 +335,10 @@ #endif +#endif diff --git a/src/hunspell/hashmgr.cxx b/src/hunspell/hashmgr.cxx -index 3ec263d..2e4ed3a 100644 +index b0a6d74..f1b6583 100644 --- a/src/hunspell/hashmgr.cxx +++ b/src/hunspell/hashmgr.cxx -@@ -82,8 +82,14 @@ +@@ -82,16 +82,28 @@ // build a hash table from a munched word list @@ -347,15 +347,14 @@ + : bdict_reader(reader), +#else HashMgr::HashMgr(const char* tpath, const char* apath, const char* key) -- : tablesize(0), +- : flag_mode(FLAG_CHAR), + : +#endif -+ tablesize(0), - tableptr(NULL), - flag_mode(FLAG_CHAR), ++ flag_mode(FLAG_CHAR), complexprefixes(0), -@@ -97,8 +103,14 @@ HashMgr::HashMgr(const char* tpath, const char* apath, const char* key) - aliasm(NULL) { + utf8(0), + forbiddenword(FORBIDDENWORD) // forbidden word signing flag + { langnum = 0; csconv = 0; +#ifdef HUNSPELL_CHROME_CLIENT @@ -369,7 +368,7 @@ if (ec) { /* error condition - what should we do here */ HUNSPELL_WARNING(stderr, "Hash Manager Error : %d\n", ec); -@@ -156,14 +168,57 @@ HashMgr::~HashMgr() { +@@ -140,14 +152,57 @@ HashMgr::~HashMgr() { #endif #endif @@ -424,18 +423,18 @@ + + return AffixIDsToHentry(word_buf, affix_ids, affix_count); +#else - struct hentry* dp; - if (tableptr) { - dp = tableptr[hash(word)]; -@@ -175,6 +230,7 @@ struct hentry* HashMgr::lookup(const char* word) const { - } + struct hentry* dp = tableptr[hash(word)]; + if (!dp) + return NULL; +@@ -156,6 +211,7 @@ struct hentry* HashMgr::lookup(const char* word) const { + return dp; } return NULL; +#endif } // add a word to the hash table (private) -@@ -185,6 +241,8 @@ int HashMgr::add_word(const std::string& in_word, +@@ -166,6 +222,8 @@ int HashMgr::add_word(const std::string& in_word, const std::string* in_desc, bool onlyupcase, int captype) { @@ -444,7 +443,7 @@ const std::string* word = &in_word; const std::string* desc = in_desc; -@@ -416,6 +474,17 @@ int HashMgr::add_word(const std::string& in_word, +@@ -408,6 +466,17 @@ int HashMgr::add_word(const std::string& in_word, delete desc_copy; delete word_copy; @@ -462,7 +461,7 @@ return 0; } -@@ -480,6 +549,12 @@ int HashMgr::get_clen_and_captype(const std::string& word, int* captype) { +@@ -472,6 +541,12 @@ int HashMgr::get_clen_and_captype(const std::string& word, int* captype) { // remove word (personal dictionary function for standalone applications) int HashMgr::remove(const std::string& word) { @@ -475,7 +474,7 @@ struct hentry* dp = lookup(word.c_str()); while (dp) { if (dp->alen == 0 || !TESTAFF(dp->astr, forbiddenword, dp->alen)) { -@@ -497,6 +572,7 @@ int HashMgr::remove(const std::string& word) { +@@ -489,6 +564,7 @@ int HashMgr::remove(const std::string& word) { } dp = dp->next_homonym; } @@ -483,7 +482,7 @@ return 0; } -@@ -555,6 +631,44 @@ int HashMgr::add_with_affix(const std::string& word, const std::string& example) +@@ -547,6 +623,44 @@ int HashMgr::add_with_affix(const std::string& word, const std::string& example) // walk the hash table entry by entry - null at end // initialize: col=-1; hp = NULL; hp = walk_hashtable(&col, hp); struct hentry* HashMgr::walk_hashtable(int& col, struct hentry* hp) const { @@ -527,8 +526,8 @@ +#else if (hp && hp->next != NULL) return hp->next; - for (col++; col < tablesize; col++) { -@@ -564,10 +678,12 @@ struct hentry* HashMgr::walk_hashtable(int& col, struct hentry* hp) const { + for (col++; col < (int)tableptr.size(); ++col) { +@@ -556,10 +670,12 @@ struct hentry* HashMgr::walk_hashtable(int& col, struct hentry* hp) const { // null at end and reset to start col = -1; return NULL; @@ -541,7 +540,7 @@ // open dictionary file FileMgr* dict = new FileMgr(tpath, key); if (dict == NULL) -@@ -698,12 +814,16 @@ int HashMgr::load_tables(const char* tpath, const char* key) { +@@ -686,12 +802,16 @@ int HashMgr::load_tables(const char* tpath, const char* key) { } delete dict; @@ -558,15 +557,15 @@ unsigned long hv = 0; for (int i = 0; i < 4 && *word != 0; i++) hv = (hv << 8) | (*word++); -@@ -712,6 +832,7 @@ int HashMgr::hash(const char* word) const { +@@ -700,6 +820,7 @@ int HashMgr::hash(const char* word) const { hv ^= (*word++); } - return (unsigned long)hv % tablesize; + return (unsigned long)hv % tableptr.size(); +#endif } int HashMgr::decode_flags(unsigned short** result, const std::string& flags, FileMgr* af) const { -@@ -921,7 +1042,12 @@ int HashMgr::load_config(const char* affpath, const char* key) { +@@ -909,7 +1030,12 @@ int HashMgr::load_config(const char* affpath, const char* key) { int firstline = 1; // open the affix file @@ -579,7 +578,7 @@ if (!afflst) { HUNSPELL_WARNING( stderr, "Error - could not open affix description file %s\n", affpath); -@@ -1159,6 +1285,132 @@ bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) { +@@ -1132,6 +1258,132 @@ bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) { return true; } @@ -710,10 +709,10 @@ +#endif + int HashMgr::is_aliasf() const { - return (aliasf != NULL); + return !aliasf.empty(); } diff --git a/src/hunspell/hashmgr.hxx b/src/hunspell/hashmgr.hxx -index 98b09e2..6fa2ba7 100644 +index 401b83c..666074a 100644 --- a/src/hunspell/hashmgr.hxx +++ b/src/hunspell/hashmgr.hxx @@ -79,6 +79,13 @@ @@ -740,10 +739,10 @@ + std::map<std::string_view, int> custom_word_to_affix_id_map_; + std::vector<std::string*> pointer_to_strings_; +#endif - int tablesize; - struct hentry** tableptr; + std::vector<struct hentry*> tableptr; flag flag_mode; -@@ -111,7 +124,23 @@ class HashMgr { + int complexprefixes; +@@ -108,7 +121,23 @@ class HashMgr { std::vector<replentry> reptable; public: @@ -767,7 +766,7 @@ ~HashMgr(); struct hentry* lookup(const char*) const; -@@ -144,6 +173,40 @@ class HashMgr { +@@ -141,6 +170,40 @@ class HashMgr { int captype); int load_config(const char* affpath, const char* key); bool parse_aliasf(const std::string& line, FileMgr* af); @@ -830,7 +829,7 @@ #define ROTATE(v, q) \ diff --git a/src/hunspell/hunspell.cxx b/src/hunspell/hunspell.cxx -index 4afafda..f699f5c 100644 +index d136d14..329e297 100644 --- a/src/hunspell/hunspell.cxx +++ b/src/hunspell/hunspell.cxx @@ -77,19 +77,28 @@ @@ -1086,23 +1085,23 @@ /* spell(word) - spellcheck word * output: false = bad word, true = good word diff --git a/src/hunspell/replist.cxx b/src/hunspell/replist.cxx -index 1395ade..9d52f33 100644 +index df428be..cc861e4 100644 --- a/src/hunspell/replist.cxx +++ b/src/hunspell/replist.cxx -@@ -161,6 +161,7 @@ int RepList::add(const std::string& in_pat1, const std::string& pat2) { +@@ -151,6 +151,7 @@ int RepList::add(const std::string& in_pat1, const std::string& pat2) { mystrrep(r->outstrings[type], "_", " "); - dat[pos++] = r; + dat.push_back(r); // sort to the right place in the list +#if 0 - int i; - for (i = pos - 1; i > 0; i--) { + size_t i; + for (i = dat.size() - 1; i > 0; --i) { if (strcmp(r->pattern.c_str(), dat[i - 1]->pattern.c_str()) < 0) { -@@ -169,6 +170,15 @@ int RepList::add(const std::string& in_pat1, const std::string& pat2) { +@@ -159,6 +160,15 @@ int RepList::add(const std::string& in_pat1, const std::string& pat2) { break; } dat[i] = r; +#else -+ for (int i = pos - 1; i > 0; i--) { ++ for (int i = dat.size() - 1; i > 0; --i) { + r = dat[i]; + if (r->pattern < dat[i - 1]->pattern) { + dat[i] = dat[i - 1]; @@ -1114,7 +1113,7 @@ } diff --git a/src/hunspell/replist.hxx b/src/hunspell/replist.hxx -index 08daeb4..2bc8aa7 100644 +index ea0524a..35fe025 100644 --- a/src/hunspell/replist.hxx +++ b/src/hunspell/replist.hxx @@ -72,6 +72,12 @@ @@ -1131,7 +1130,7 @@ #include <string> diff --git a/src/hunspell/suggestmgr.cxx b/src/hunspell/suggestmgr.cxx -index 6b363de..2be03dd 100644 +index 6e9d028..c35b491 100644 --- a/src/hunspell/suggestmgr.cxx +++ b/src/hunspell/suggestmgr.cxx @@ -82,7 +82,112 @@ const w_char W_VLINE = {'\0', '|'}; @@ -1247,8 +1246,8 @@ // register affix manager and check in string of chars to // try when building candidate suggestions pAMgr = aptr; -@@ -455,6 +560,21 @@ int SuggestMgr::replchars(std::vector<std::string>& wlst, - int wl = strlen(word); +@@ -462,6 +567,21 @@ int SuggestMgr::replchars(std::vector<std::string>& wlst, + int wl = word.size(); if (wl < 2 || !pAMgr) return wlst.size(); + @@ -1257,27 +1256,27 @@ + const char *pattern, *pattern2; + hunspell::ReplacementIterator iterator = bdict_reader->GetReplacementIterator(); + while (iterator.GetNext(&pattern, &pattern2)) { -+ const char* r = word; ++ size_t r = 0; + size_t lenr = strlen(pattern2); + size_t lenp = strlen(pattern); + + // search every occurence of the pattern in the word -+ while ((r=strstr(r, pattern)) != NULL) { ++ while ((r = word.find(pattern, r)) != std::string::npos) { + candidate = word; -+ candidate.replace(r-word, lenp, pattern2); ++ candidate.replace(r, lenp, pattern2); +#else const std::vector<replentry>& reptable = pAMgr->get_reptable(); for (size_t i = 0; i < reptable.size(); ++i) { - const char* r = word; -@@ -474,6 +594,7 @@ int SuggestMgr::replchars(std::vector<std::string>& wlst, - candidate.resize(r - word); + size_t r = 0; +@@ -480,6 +600,7 @@ int SuggestMgr::replchars(std::vector<std::string>& wlst, + candidate.assign(word, 0, r); candidate.append(reptable[i].outstrings[type]); - candidate.append(r + reptable[i].pattern.size()); + candidate.append(word, r + reptable[i].pattern.size(), std::string::npos); +#endif testsug(wlst, candidate, cpdsuggest, NULL, NULL); // check REP suggestions with space size_t sp = candidate.find(' '); -@@ -1131,6 +1252,9 @@ void SuggestMgr::ngsuggest(std::vector<std::string>& wlst, +@@ -1137,6 +1258,9 @@ void SuggestMgr::ngsuggest(std::vector<std::string>& wlst, struct hentry* hp = NULL; int col = -1; @@ -1287,7 +1286,7 @@ phonetable* ph = (pAMgr) ? pAMgr->get_phonetable() : NULL; std::string target; std::string candidate; -@@ -1257,7 +1381,11 @@ void SuggestMgr::ngsuggest(std::vector<std::string>& wlst, +@@ -1263,7 +1387,11 @@ void SuggestMgr::ngsuggest(std::vector<std::string>& wlst, if (sc > scores[lp]) { scores[lp] = sc; @@ -1299,7 +1298,7 @@ lval = sc; for (int j = 0; j < MAX_ROOTS; j++) if (scores[j] < lval) { -@@ -2197,8 +2325,8 @@ void SuggestMgr::lcs(const char* s, +@@ -2202,8 +2330,8 @@ void SuggestMgr::lcs(const char* s, m = strlen(s); n = strlen(s2); } @@ -1310,7 +1309,7 @@ if (!c || !b) { if (c) free(c); -@@ -2207,10 +2335,6 @@ void SuggestMgr::lcs(const char* s, +@@ -2212,10 +2340,6 @@ void SuggestMgr::lcs(const char* s, *result = NULL; return; } @@ -1322,7 +1321,7 @@ for (j = 1; j <= n; j++) { if (((utf8) && (su[i - 1] == su2[j - 1])) || diff --git a/src/hunspell/suggestmgr.hxx b/src/hunspell/suggestmgr.hxx -index 4c2fb69..925c6a0 100644 +index 0c2398a..35c8903 100644 --- a/src/hunspell/suggestmgr.hxx +++ b/src/hunspell/suggestmgr.hxx @@ -116,7 +116,11 @@ class SuggestMgr {
diff --git a/third_party/hunspell/src/hunspell/affentry.cxx b/third_party/hunspell/src/hunspell/affentry.cxx index 2cf4f467..1e33991a 100644 --- a/third_party/hunspell/src/hunspell/affentry.cxx +++ b/third_party/hunspell/src/hunspell/affentry.cxx
@@ -122,8 +122,9 @@ return NULL; } -inline int PfxEntry::test_condition(const char* st) { - const char* pos = NULL; // group with pos input position +inline int PfxEntry::test_condition(const std::string& s) { + size_t st = 0; + size_t pos = std::string::npos; // group with pos input position bool neg = false; // complementer bool ingroup = false; // character in the group if (numconds == 0) @@ -148,53 +149,56 @@ case ']': { if (bool(neg) == bool(ingroup)) return 0; - pos = NULL; + pos = std::string::npos; p = nextchar(p); // skip the next character - if (!ingroup && *st) - for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++) - ; - if (*st == '\0' && p) + if (!ingroup && st < s.size()) { + ++st; + while ((opts & aeUTF8) && st < s.size() && (s[st] & 0xc0) == 0x80) + ++st; + } + if (st == s.size() && p) return 0; // word <= condition break; } case '.': - if (!pos) { // dots are not metacharacters in groups: [.] + if (pos == std::string::npos) { // dots are not metacharacters in groups: [.] p = nextchar(p); // skip the next character - for (st++; (opts & aeUTF8) && (*st & 0xc0) == 0x80; st++) - ; - if (*st == '\0' && p) + ++st; + while ((opts & aeUTF8) && st < s.size() && (s[st] & 0xc0) == 0x80) + ++st; + if (st == s.size() && p) return 0; // word <= condition break; } /* FALLTHROUGH */ default: { - if (*st == *p) { - st++; + if (s[st] == *p) { + ++st; p = nextchar(p); - if ((opts & aeUTF8) && (*(st - 1) & 0x80)) { // multibyte + if ((opts & aeUTF8) && (s[st - 1] & 0x80)) { // multibyte while (p && (*p & 0xc0) == 0x80) { // character - if (*p != *st) { - if (!pos) + if (*p != s[st]) { + if (pos == std::string::npos) return 0; st = pos; break; } p = nextchar(p); - st++; + ++st; } - if (pos && st != pos) { + if (pos != std::string::npos && st != pos) { ingroup = true; while (p && *p != ']' && ((p = nextchar(p)) != NULL)) { } } - } else if (pos) { + } else if (pos != std::string::npos) { ingroup = true; while (p && *p != ']' && ((p = nextchar(p)) != NULL)) { } } - } else if (pos) { // group + } else if (pos != std::string::npos) { // group p = nextchar(p); } else return 0; @@ -234,7 +238,7 @@ // if all conditions are met then check if resulting // root word in the dictionary - if (test_condition(tmpword.c_str())) { + if (test_condition(tmpword)) { tmpl += strip.size(); if ((he = pmyMgr->lookup(tmpword.c_str())) != NULL) { do { @@ -266,7 +270,7 @@ } // check if this prefix entry matches -struct hentry* PfxEntry::check_twosfx(const char* word, +struct hentry* PfxEntry::check_twosfx(const std::string& word, int len, char in_compound, const FLAG needflag) { @@ -283,7 +287,7 @@ // back any characters that would have been stripped std::string tmpword(strip); - tmpword.append(word + appnd.size()); + tmpword.append(word, appnd.size()); // now make sure all of the conditions on characters // are met. Please see the appendix at the end of @@ -293,7 +297,7 @@ // if all conditions are met then check if resulting // root word in the dictionary - if (test_condition(tmpword.c_str())) { + if (test_condition(tmpword)) { tmpl += strip.size(); // prefix matched but no root word was found @@ -302,7 +306,7 @@ if ((opts & aeXPRODUCT) && (in_compound != IN_CPD_BEGIN)) { // hash entry of root word or NULL - struct hentry* he = pmyMgr->suffix_check_twosfx(tmpword.c_str(), tmpl, aeXPRODUCT, this, + struct hentry* he = pmyMgr->suffix_check_twosfx(tmpword, tmpl, aeXPRODUCT, this, needflag); if (he) return he; @@ -340,7 +344,7 @@ // if all conditions are met then check if resulting // root word in the dictionary - if (test_condition(tmpword.c_str())) { + if (test_condition(tmpword)) { tmpl += strip.size(); // prefix matched but no root word was found @@ -387,7 +391,7 @@ // if all conditions are met then check if resulting // root word in the dictionary - if (test_condition(tmpword.c_str())) { + if (test_condition(tmpword)) { tmpl += strip.size(); struct hentry* he; // hash entry of root word or NULL if ((he = pmyMgr->lookup(tmpword.c_str())) != NULL) { @@ -689,7 +693,7 @@ } // see if two-level suffix is present in the word -struct hentry* SfxEntry::check_twosfx(const char* word, +struct hentry* SfxEntry::check_twosfx(const std::string& word, int len, int optflags, PfxEntry* ppfx,
diff --git a/third_party/hunspell/src/hunspell/affentry.hxx b/third_party/hunspell/src/hunspell/affentry.hxx index b736bf0..6cc8d2a 100644 --- a/third_party/hunspell/src/hunspell/affentry.hxx +++ b/third_party/hunspell/src/hunspell/affentry.hxx
@@ -99,7 +99,7 @@ char in_compound, const FLAG needflag = FLAG_NULL); - struct hentry* check_twosfx(const char* word, + struct hentry* check_twosfx(const std::string& word, int len, char in_compound, const FLAG needflag = FLAG_NULL); @@ -136,7 +136,7 @@ inline void setFlgNxt(PfxEntry* ptr) { flgnxt = ptr; } inline char* nextchar(char* p); - inline int test_condition(const char* st); + inline int test_condition(const std::string& st); }; /* A Suffix Entry */ @@ -171,7 +171,7 @@ const FLAG needflag, const FLAG badflag); - struct hentry* check_twosfx(const char* word, + struct hentry* check_twosfx(const std::string& word, int len, int optflags, PfxEntry* ppfx,
diff --git a/third_party/hunspell/src/hunspell/affixmgr.cxx b/third_party/hunspell/src/hunspell/affixmgr.cxx index 6bdec4e..71790df 100644 --- a/third_party/hunspell/src/hunspell/affixmgr.cxx +++ b/third_party/hunspell/src/hunspell/affixmgr.cxx
@@ -1083,10 +1083,12 @@ } // calculate the character length of the condition -int AffixMgr::condlen(const char* st) { +int AffixMgr::condlen(const std::string& s) { int l = 0; bool group = false; - for (; *st; st++) { + std::string::const_iterator st = s.begin(); + std::string::const_iterator end = s.end(); + while (st != end) { if (*st == '[') { group = true; l++; @@ -1094,16 +1096,17 @@ group = false; else if (!group && (!utf8 || (!(*st & 0x80) || ((*st & 0xc0) == 0x80)))) l++; + ++st; } return l; } -int AffixMgr::encodeit(AffEntry& entry, const char* cs) { - if (strcmp(cs, ".") != 0) { +int AffixMgr::encodeit(AffEntry& entry, const std::string& cs) { + if (cs.compare(".") != 0) { entry.numconds = (char)condlen(cs); - const size_t cslen = strlen(cs); + const size_t cslen = cs.size(); const size_t short_part = std::min<size_t>(MAXCONDLEN, cslen); - memcpy(entry.c.conds, cs, short_part); + memcpy(entry.c.conds, cs.data(), short_part); if (short_part < MAXCONDLEN) { //blank out the remaining space memset(entry.c.conds + short_part, 0, MAXCONDLEN - short_part); @@ -1111,9 +1114,12 @@ //there is more conditions than fit in fixed space, so its //a long condition entry.opts |= aeLONGCOND; - entry.c.l.conds2 = mystrdup(cs + MAXCONDLEN_1); + size_t remaining = cs.size() - MAXCONDLEN_1; + entry.c.l.conds2 = (char*)malloc(1 + remaining); if (!entry.c.l.conds2) return 1; + memcpy(entry.c.l.conds2, cs.data() + MAXCONDLEN_1, remaining); + entry.c.l.conds2[remaining] = 0; } } else { entry.numconds = 0; @@ -1197,7 +1203,7 @@ } // check word for prefixes and two-level suffixes -struct hentry* AffixMgr::prefix_check_twosfx(const char* word, +struct hentry* AffixMgr::prefix_check_twosfx(const std::string& word, int len, char in_compound, const FLAG needflag) { @@ -1218,11 +1224,11 @@ } // now handle the general case - unsigned char sp = *((const unsigned char*)word); + unsigned char sp = word[0]; PfxEntry* pptr = pStart[sp]; while (pptr) { - if (isSubset(pptr->getKey(), word)) { + if (isSubset(pptr->getKey(), word.c_str())) { rv = pptr->check_twosfx(word, len, in_compound, needflag); if (rv) { pfx = pptr; @@ -1340,7 +1346,7 @@ while ((r=strstr(r, pattern)) != NULL) { std::string candidate(word); candidate.replace(r-word, lenp, pattern2); - if (candidate_check(candidate.c_str(), candidate.size())) return 1; + if (candidate_check(candidate)) return 1; r++; // search for the next letter } } @@ -1358,7 +1364,7 @@ while ((r = strstr(r, get_reptable()[i].pattern.c_str())) != NULL) { std::string candidate(word); candidate.replace(r - word, lenp, get_reptable()[i].outstrings[0]); - if (candidate_check(candidate.c_str(), candidate.size())) + if (candidate_check(candidate)) return 1; ++r; // search for the next letter } @@ -1379,7 +1385,7 @@ if (utf8 && ((word[i] & 0xc0) == 0x80)) continue; candidate.insert(i, 1, ' '); - if (candidate_check(candidate.c_str(), candidate.size())) + if (candidate_check(candidate)) return 1; candidate.erase(i, 1); } @@ -1407,7 +1413,7 @@ ((checkcpdtable[i].pattern[0] == '0' && r1->blen <= pos && strncmp(word + pos - r1->blen, r1->word, r1->blen) == 0) || (checkcpdtable[i].pattern[0] != '0' && - ((len = checkcpdtable[i].pattern.size()) != 0) && + ((len = checkcpdtable[i].pattern.size()) != 0) && len <= pos && strncmp(word + pos - len, checkcpdtable[i].pattern.c_str(), len) == 0)))) { return 1; } @@ -1578,16 +1584,16 @@ return 0; } -inline int AffixMgr::candidate_check(const char* word, int len) { +inline int AffixMgr::candidate_check(const std::string& word) { - struct hentry* rv = lookup(word); + struct hentry* rv = lookup(word.c_str()); if (rv) return 1; // rv = prefix_check(word,len,1); // if (rv) return 1; - rv = affix_check(word, len); + rv = affix_check(word.c_str(), word.size()); if (rv) return 1; return 0; @@ -1651,7 +1657,6 @@ char hu_mov_rule = 0, char is_sug = 0, int* info = NULL) { - int i; short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2; struct hentry* rv = NULL; struct hentry* rv_first; @@ -1694,7 +1699,7 @@ st.assign(word); - for (i = cmin; i < cmax; i++) { + for (int i = cmin; i < cmax; ++i) { // go to end of the UTF-8 character if (utf8) { for (; (st[i] & 0xc0) == 0x80; i++) @@ -1795,7 +1800,7 @@ st.c_str(), i, 0, NULL, FLAG_NULL, compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || (compoundmoresuffixes && - (rv = suffix_check_twosfx(st.c_str(), i, 0, NULL, compoundflag)))) && + (rv = suffix_check_twosfx(st, i, 0, NULL, compoundflag)))) && !hu_mov_rule && sfx->getCont() && ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, @@ -1813,7 +1818,7 @@ hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || (compoundmoresuffixes && (rv = suffix_check_twosfx( - st.c_str(), i, 0, NULL, + st, i, 0, NULL, compoundbegin))) || // twofold suffixes + compound (rv = prefix_check(st.c_str(), i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, @@ -1824,7 +1829,7 @@ hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || (compoundmoresuffixes && (rv = suffix_check_twosfx( - st.c_str(), i, 0, NULL, + st, i, 0, NULL, compoundmiddle))) || // twofold suffixes + compound (rv = prefix_check(st.c_str(), i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, @@ -1969,7 +1974,7 @@ } // check FORCEUCASE - if (rv && forceucase && (rv) && + if (rv && forceucase && (TESTAFF(rv->astr, forceucase, rv->alen)) && !(info && *info & SPELL_ORIGCAP)) rv = NULL; @@ -2038,19 +2043,20 @@ // perhaps second word has prefix or/and suffix sfx = NULL; sfxflag = FLAG_NULL; - rv = (compoundflag && !onlycpdrule) + rv = (compoundflag && !onlycpdrule && i < word.size()) ? affix_check((word.c_str() + i), strlen(word.c_str() + i), compoundflag, IN_CPD_END) : NULL; if (!rv && compoundend && !onlycpdrule) { sfx = NULL; pfx = NULL; - rv = affix_check((word.c_str() + i), strlen(word.c_str() + i), compoundend, - IN_CPD_END); + if (i < word.size()) + rv = affix_check((word.c_str() + i), strlen(word.c_str() + i), compoundend, IN_CPD_END); } if (!rv && !defcpdtable.empty() && words) { - rv = affix_check((word.c_str() + i), strlen(word.c_str() + i), 0, IN_CPD_END); + if (i < word.size()) + rv = affix_check((word.c_str() + i), strlen(word.c_str() + i), 0, IN_CPD_END); if (rv && defcpd_check(&words, wnum + 1, rv, NULL, 1)) return rv_first; rv = NULL; @@ -2078,7 +2084,7 @@ } // check FORCEUCASE - if (rv && forceucase && (rv) && + if (rv && forceucase && (TESTAFF(rv->astr, forceucase, rv->alen)) && !(info && *info & SPELL_ORIGCAP)) rv = NULL; @@ -2256,8 +2262,7 @@ // check if compound word is correctly spelled // hu_mov_rule = spec. Hungarian rule (XXX) -int AffixMgr::compound_check_morph(const char* word, - int len, +int AffixMgr::compound_check_morph(const std::string& word, short wordnum, short numsyllable, short maxwordnum, @@ -2267,7 +2272,6 @@ char hu_mov_rule, std::string& result, const std::string* partresult) { - int i; short oldnumsyllable, oldnumsyllable2, oldwordnum, oldwordnum2; int ok = 0; @@ -2284,6 +2288,7 @@ char affixed = 0; hentry** oldwords = words; + size_t len = word.size(); // add a time limit to handle possible // combinatorical explosion of the overlapping words @@ -2303,11 +2308,11 @@ > static_cast<double>(TIMELIMIT) * CLOCKS_PER_SEC * 1000) timelimit_exceeded = true; - setcminmax(&cmin, &cmax, word, len); + setcminmax(&cmin, &cmax, word.c_str(), len); st.assign(word); - for (i = cmin; i < cmax; i++) { + for (int i = cmin; i < cmax; ++i) { // go to end of the UTF-8 character if (utf8) { for (; (st[i] & 0xc0) == 0x80; i++) @@ -2393,7 +2398,7 @@ compoundflag, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || (compoundmoresuffixes && - (rv = suffix_check_twosfx(st.c_str(), i, 0, NULL, compoundflag)))) && + (rv = suffix_check_twosfx(st, i, 0, NULL, compoundflag)))) && !hu_mov_rule && sfx->getCont() && ((compoundforbidflag && TESTAFF(sfx->getCont(), compoundforbidflag, @@ -2411,7 +2416,7 @@ hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || (compoundmoresuffixes && (rv = suffix_check_twosfx( - st.c_str(), i, 0, NULL, + st, i, 0, NULL, compoundbegin))) || // twofold suffix+compound (rv = prefix_check(st.c_str(), i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, @@ -2422,7 +2427,7 @@ hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN)) || (compoundmoresuffixes && (rv = suffix_check_twosfx( - st.c_str(), i, 0, NULL, + st, i, 0, NULL, compoundmiddle))) || // twofold suffix+compound (rv = prefix_check(st.c_str(), i, hu_mov_rule ? IN_CPD_OTHER : IN_CPD_BEGIN, @@ -2516,8 +2521,8 @@ ( // test CHECKCOMPOUNDPATTERN !checkcpdtable.empty() && !words && - cpdpat_check(word, i, rv, NULL, affixed)) || - (checkcompoundcase && !words && cpdcase_check(word, i)))) + cpdpat_check(word.c_str(), i, rv, NULL, affixed)) || + (checkcompoundcase && !words && cpdcase_check(word.c_str(), i)))) // LANG_hu section: spec. Hungarian rule || ((!rv) && (langnum == LANG_hu) && hu_mov_rule && @@ -2541,7 +2546,7 @@ // NEXT WORD(S) rv_first = rv; - rv = lookup((word + i)); // perhaps without prefix + rv = lookup((word.c_str() + i)); // perhaps without prefix // search homonym with compound flag while ((rv) && ((needaffix && TESTAFF(rv->astr, needaffix, rv->alen)) || @@ -2558,7 +2563,7 @@ result.append(presult); result.push_back(MSEP_FLD); result.append(MORPH_PART); - result.append(word + i); + result.append(word, i); if (complexprefixes && HENTRY_DATA(rv)) result.append(HENTRY_DATA2(rv)); if (!HENTRY_FIND(rv, MORPH_STEM)) { @@ -2615,7 +2620,7 @@ result.append(presult); result.push_back(MSEP_FLD); result.append(MORPH_PART); - result.append(word + i); + result.append(word, i); if (HENTRY_DATA(rv)) { if (complexprefixes) @@ -2643,30 +2648,30 @@ sfxflag = FLAG_NULL; if (compoundflag && !onlycpdrule) - rv = affix_check((word + i), strlen(word + i), compoundflag); + rv = affix_check((word.c_str() + i), strlen(word.c_str() + i), compoundflag); else rv = NULL; if (!rv && compoundend && !onlycpdrule) { sfx = NULL; pfx = NULL; - rv = affix_check((word + i), strlen(word + i), compoundend); + rv = affix_check((word.c_str() + i), strlen(word.c_str() + i), compoundend); } if (!rv && !defcpdtable.empty() && words) { - rv = affix_check((word + i), strlen(word + i), 0, IN_CPD_END); + rv = affix_check((word.c_str() + i), strlen(word.c_str() + i), 0, IN_CPD_END); if (rv && words && defcpd_check(&words, wnum + 1, rv, NULL, 1)) { std::string m; if (compoundflag) - m = affix_check_morph((word + i), strlen(word + i), compoundflag); + m = affix_check_morph((word.c_str() + i), strlen(word.c_str() + i), compoundflag); if (m.empty() && compoundend) { - m = affix_check_morph((word + i), strlen(word + i), compoundend); + m = affix_check_morph((word.c_str() + i), strlen(word.c_str() + i), compoundend); } result.append(presult); if (!m.empty()) { result.push_back(MSEP_FLD); result.append(MORPH_PART); - result.append(word + i); + result.append(word, i); line_uniq_app(m, MSEP_REC); result.append(m); } @@ -2696,7 +2701,7 @@ if (langnum == LANG_hu) { // calculate syllable number of the word - numsyllable += get_syllable(word + i); + numsyllable += get_syllable(word.c_str() + i); // - affix syllable num. // XXX only second suffix (inflections, not derivations) @@ -2750,15 +2755,15 @@ ((!checkcompounddup || (rv != rv_first)))) { std::string m; if (compoundflag) - m = affix_check_morph((word + i), strlen(word + i), compoundflag); + m = affix_check_morph((word.c_str() + i), strlen(word.c_str() + i), compoundflag); if (m.empty() && compoundend) { - m = affix_check_morph((word + i), strlen(word + i), compoundend); + m = affix_check_morph((word.c_str() + i), strlen(word.c_str() + i), compoundend); } result.append(presult); if (!m.empty()) { result.push_back(MSEP_FLD); result.append(MORPH_PART); - result.append(word + i); + result.append(word, i); line_uniq_app(m, MSEP_REC); result.push_back(MSEP_FLD); result.append(m); @@ -2772,7 +2777,7 @@ // perhaps second word is a compound word (recursive call) if ((wordnum + 2 < maxwordnum) && (ok == 0)) { - compound_check_morph((word + i), strlen(word + i), wordnum + 1, + compound_check_morph(word.substr(i), wordnum + 1, numsyllable, maxwordnum, wnum + 1, words, rwords, 0, result, &presult); } else { @@ -2923,7 +2928,7 @@ } // check word for two-level suffixes -struct hentry* AffixMgr::suffix_check_twosfx(const char* word, +struct hentry* AffixMgr::suffix_check_twosfx(const std::string& word, int len, int sfxopts, PfxEntry* ppfx, @@ -2944,11 +2949,11 @@ // now handle the general case if (len == 0) return NULL; // FULLSTRIP - unsigned char sp = *((const unsigned char*)(word + len - 1)); + unsigned char sp = word[len - 1]; SfxEntry* sptr = sStart[sp]; while (sptr) { - if (isRevSubset(sptr->getKey(), word + len - 1, len)) { + if (isRevSubset(sptr->getKey(), word.c_str() + len - 1, len)) { if (contclasses[sptr->getFlag()]) { rv = sptr->check_twosfx(word, len, sfxopts, ppfx, needflag); if (rv) { @@ -3785,7 +3790,7 @@ std::string s; if (!parse_string(line, s, af->getlinenum())) return false; - *out = pHMgr->decode_flag(s.c_str()); + *out = pHMgr->decode_flag(s); return true; } @@ -4105,7 +4110,7 @@ if (slash_pos != std::string::npos) { std::string chunk(checkcpdtable.back().pattern, slash_pos + 1); checkcpdtable.back().pattern.resize(slash_pos); - checkcpdtable.back().cond = pHMgr->decode_flag(chunk.c_str()); + checkcpdtable.back().cond = pHMgr->decode_flag(chunk); } break; } @@ -4115,7 +4120,7 @@ if (slash_pos != std::string::npos) { std::string chunk(checkcpdtable.back().pattern2, slash_pos + 1); checkcpdtable.back().pattern2.resize(slash_pos); - checkcpdtable.back().cond2 = pHMgr->decode_flag(chunk.c_str()); + checkcpdtable.back().cond2 = pHMgr->decode_flag(chunk); } break; } @@ -4320,6 +4325,11 @@ --k; } } + if (chb == che) { + HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", + af->getlinenum()); + } + maptable.back().push_back(std::string(chb, che)); } break; @@ -4545,7 +4555,7 @@ // piece 2 - is affix char case 1: { np++; - aflag = pHMgr->decode_flag(std::string(start_piece, iter).c_str()); + aflag = pHMgr->decode_flag(std::string(start_piece, iter)); #ifndef HUNSPELL_CHROME_CLIENT // We don't check for duplicates. if (((at == 'S') && (dupflags[aflag] & dupSFX)) || ((at == 'P') && (dupflags[aflag] & dupPFX))) { @@ -4636,7 +4646,7 @@ case 1: { np++; std::string chunk(start_piece, iter); - if (pHMgr->decode_flag(chunk.c_str()) != aflag) { + if (pHMgr->decode_flag(chunk) != aflag) { char* err = pHMgr->encode_flag(aflag); if (err) { HUNSPELL_WARNING(stderr, @@ -4751,14 +4761,14 @@ reverse_condition(chunk); } if (!entry->strip.empty() && chunk != "." && - redundant_condition(at, entry->strip.c_str(), entry->strip.size(), chunk.c_str(), + redundant_condition(at, entry->strip, chunk, af->getlinenum())) chunk = "."; if (at == 'S') { reverseword(chunk); reverse_condition(chunk); } - if (encodeit(*entry, chunk.c_str())) + if (encodeit(*entry, chunk)) return false; break; } @@ -4838,17 +4848,15 @@ } int AffixMgr::redundant_condition(char ft, - const char* strip, - int stripl, - const char* cond, + const std::string& strip, + const std::string& cond, int linenum) { - int condl = strlen(cond); - int i; - int j; + int stripl = strip.size(), condl = cond.size(); + int i, j; int neg; int in; if (ft == 'P') { // prefix - if (strncmp(strip, cond, condl) == 0) + if (strip.compare(0, condl, cond) == 0) return 1; if (utf8) { } else { @@ -4872,7 +4880,7 @@ if (j == (condl - 1) && (cond[j] != ']')) { HUNSPELL_WARNING(stderr, "error: line %d: missing ] in condition:\n%s\n", - linenum, cond); + linenum, cond.c_str()); return 0; } if ((!neg && !in) || (neg && in)) { @@ -4888,7 +4896,7 @@ return 1; } } else { // suffix - if ((stripl >= condl) && strcmp(strip + stripl - condl, cond) == 0) + if ((stripl >= condl) && strip.compare(stripl - condl, std::string::npos, cond) == 0) return 1; if (utf8) { } else { @@ -4911,7 +4919,7 @@ if ((j == 0) && (cond[j] != '[')) { HUNSPELL_WARNING(stderr, "error: line: %d: missing ] in condition:\n%s\n", - linenum, cond); + linenum, cond.c_str()); return 0; } neg = (cond[j + 1] == '^') ? 1 : 0; @@ -4933,7 +4941,7 @@ std::vector<std::string> AffixMgr::get_suffix_words(short unsigned* suff, int len, - const char* root_word) { + const std::string& root_word) { std::vector<std::string> slst; short unsigned* start_ptr = suff; for (int j = 0; j < SETSIZE; j++) {
diff --git a/third_party/hunspell/src/hunspell/affixmgr.hxx b/third_party/hunspell/src/hunspell/affixmgr.hxx index ea2ee98..1e9c4f1 100644 --- a/third_party/hunspell/src/hunspell/affixmgr.hxx +++ b/third_party/hunspell/src/hunspell/affixmgr.hxx
@@ -227,7 +227,7 @@ char in_compound, const FLAG needflag = FLAG_NULL); inline int isSubset(const char* s1, const char* s2); - struct hentry* prefix_check_twosfx(const char* word, + struct hentry* prefix_check_twosfx(const std::string& word, int len, char in_compound, const FLAG needflag = FLAG_NULL); @@ -239,7 +239,7 @@ const FLAG cclass = FLAG_NULL, const FLAG needflag = FLAG_NULL, char in_compound = IN_CPD_NOT); - struct hentry* suffix_check_twosfx(const char* word, + struct hentry* suffix_check_twosfx(const std::string& word, int len, int sfxopts, PfxEntry* ppfx, @@ -303,7 +303,7 @@ hentry** rwords, char all); int cpdcase_check(const char* word, int len); - inline int candidate_check(const char* word, int len); + inline int candidate_check(const std::string& word); void setcminmax(int* cmin, int* cmax, const char* word, int len); struct hentry* compound_check(const std::string& word, short wordnum, @@ -316,8 +316,7 @@ char is_sug, int* info); - int compound_check_morph(const char* word, - int len, + int compound_check_morph(const std::string& word, short wordnum, short numsyllable, short maxwordnum, @@ -330,7 +329,7 @@ std::vector<std::string> get_suffix_words(short unsigned* suff, int len, - const char* root_word); + const std::string& root_word); struct hentry* lookup(const char* word); const std::vector<replentry>& get_reptable() const; @@ -397,8 +396,8 @@ void reverse_condition(std::string&); std::string& debugflag(std::string& result, unsigned short flag); - int condlen(const char*); - int encodeit(AffEntry& entry, const char* cs); + int condlen(const std::string& s); + int encodeit(AffEntry& entry, const std::string& cs); int build_pfxtree(PfxEntry* pfxptr); int build_sfxtree(SfxEntry* sfxptr); int process_pfx_order(); @@ -407,7 +406,7 @@ SfxEntry* process_sfx_in_order(SfxEntry* ptr, SfxEntry* nptr); int process_pfx_tree_to_list(); int process_sfx_tree_to_list(); - int redundant_condition(char, const char* strip, int stripl, const char* cond, int); + int redundant_condition(char, const std::string& strip, const std::string& cond, int); void finishFileMgr(FileMgr* afflst); };
diff --git a/third_party/hunspell/src/hunspell/csutil.cxx b/third_party/hunspell/src/hunspell/csutil.cxx index fbaa768..df1fc92 100644 --- a/third_party/hunspell/src/hunspell/csutil.cxx +++ b/third_party/hunspell/src/hunspell/csutil.cxx
@@ -134,6 +134,7 @@ std::string& u16_u8(std::string& dest, const std::vector<w_char>& src) { dest.clear(); + dest.reserve(src.size()); std::vector<w_char>::const_iterator u2 = src.begin(); std::vector<w_char>::const_iterator u2_max = src.end(); while (u2 < u2_max) { @@ -169,8 +170,11 @@ return dest; } -int u8_u16(std::vector<w_char>& dest, const std::string& src) { - dest.clear(); +int u8_u16(std::vector<w_char>& dest, const std::string& src, bool only_convert_first_letter) { + // faster to oversize initially, assign to elements and resize to what's used + // than to reserve and push_back + dest.resize(only_convert_first_letter ? 1 : src.size()); + std::vector<w_char>::iterator u16 = dest.begin(); std::string::const_iterator u8 = src.begin(); std::string::const_iterator u8_max = src.end(); @@ -246,21 +250,27 @@ } break; } - case 0xf0: { // 4 or more byte UTF-8 codes + default: { // 4 or more byte UTF-8 codes + assert(((*u8) & 0xf0) == 0xf0 && "can only be 0xf0"); HUNSPELL_WARNING(stderr, "This UTF-8 encoding can't convert to UTF-16:\n%s\n", src.c_str()); u2.h = 0xff; u2.l = 0xfd; - dest.push_back(u2); + *u16++ = u2; + dest.resize(u16 - dest.begin()); return -1; } } - dest.push_back(u2); + *u16++ = u2; + if (only_convert_first_letter) + break; ++u8; } - return dest.size(); + int size = u16 - dest.begin(); + dest.resize(size); + return size; } namespace {
diff --git a/third_party/hunspell/src/hunspell/csutil.hxx b/third_party/hunspell/src/hunspell/csutil.hxx index c6f03d8..eaab2f7 100644 --- a/third_party/hunspell/src/hunspell/csutil.hxx +++ b/third_party/hunspell/src/hunspell/csutil.hxx
@@ -78,6 +78,7 @@ #include <fstream> #include <string> #include <vector> +#include <assert.h> #include <string.h> #include "w_char.hxx" #include "htypes.hxx" @@ -135,7 +136,8 @@ // convert UTF-8 characters to UTF-16 LIBHUNSPELL_DLL_EXPORTED int u8_u16(std::vector<w_char>& dest, - const std::string& src); + const std::string& src, + bool only_convert_first_letter = false); // remove end of line char(s) LIBHUNSPELL_DLL_EXPORTED void mychomp(std::string& s); @@ -321,7 +323,8 @@ inline char* HENTRY_FIND(struct hentry* h, const char* p) { - return (HENTRY_DATA(h) ? strstr(HENTRY_DATA(h), p) : NULL); + char* data = HENTRY_DATA(h); + return data ? strstr(data, p) : NULL; } #endif
diff --git a/third_party/hunspell/src/hunspell/hashmgr.cxx b/third_party/hunspell/src/hunspell/hashmgr.cxx index 2e4ed3a..f1b6583 100644 --- a/third_party/hunspell/src/hunspell/hashmgr.cxx +++ b/third_party/hunspell/src/hunspell/hashmgr.cxx
@@ -89,18 +89,11 @@ HashMgr::HashMgr(const char* tpath, const char* apath, const char* key) : #endif - tablesize(0), - tableptr(NULL), flag_mode(FLAG_CHAR), complexprefixes(0), utf8(0), forbiddenword(FORBIDDENWORD) // forbidden word signing flag - , - numaliasf(0), - aliasf(NULL), - aliasflen(0), - numaliasm(0), - aliasm(NULL) { +{ langnum = 0; csconv = 0; #ifdef HUNSPELL_CHROME_CLIENT @@ -114,52 +107,43 @@ if (ec) { /* error condition - what should we do here */ HUNSPELL_WARNING(stderr, "Hash Manager Error : %d\n", ec); - free(tableptr); - //keep tablesize to 1 to fix possible division with zero - tablesize = 1; - tableptr = (struct hentry**)calloc(tablesize, sizeof(struct hentry*)); - if (!tableptr) { - tablesize = 0; - } + free_table(); + //keep table size to 1 to fix possible division with zero + tableptr.resize(1, nullptr); } } -HashMgr::~HashMgr() { - if (tableptr) { - // now pass through hash table freeing up everything - // go through column by column of the table - for (int i = 0; i < tablesize; i++) { - struct hentry* pt = tableptr[i]; - struct hentry* nt = NULL; - while (pt) { - nt = pt->next; - if (pt->astr && - (!aliasf || TESTAFF(pt->astr, ONLYUPCASEFLAG, pt->alen))) - free(pt->astr); - free(pt); - pt = nt; - } - } - free(tableptr); - } - tablesize = 0; +void HashMgr::free_flag(unsigned short* astr, short alen) { + if (astr && (aliasf.empty() || TESTAFF(astr, ONLYUPCASEFLAG, alen))) + free(astr); +} - if (aliasf) { - for (int j = 0; j < (numaliasf); j++) - free(aliasf[j]); - free(aliasf); - aliasf = NULL; - if (aliasflen) { - free(aliasflen); - aliasflen = NULL; +void HashMgr::free_table() { + // now pass through hash table freeing up everything + // go through column by column of the table + for (size_t i = 0; i < tableptr.size(); ++i) { + struct hentry* pt = tableptr[i]; + struct hentry* nt = NULL; + while (pt) { + nt = pt->next; + free_flag(pt->astr, pt->alen); + free(pt); + pt = nt; } } - if (aliasm) { - for (int j = 0; j < (numaliasm); j++) - free(aliasm[j]); - free(aliasm); - aliasm = NULL; - } + tableptr.clear(); +} + +HashMgr::~HashMgr() { + free_table(); + + for (size_t j = 0, numaliasf = aliasf.size(); j < numaliasf; ++j) + free(aliasf[j]); + aliasf.clear(); + + for (size_t j = 0, numaliasm = aliasm.size(); j < numaliasm; ++j) + free(aliasm[j]); + aliasm.clear(); #ifndef OPENOFFICEORG #ifndef MOZILLA_CLIENT @@ -219,15 +203,12 @@ return AffixIDsToHentry(word_buf, affix_ids, affix_count); #else - struct hentry* dp; - if (tableptr) { - dp = tableptr[hash(word)]; - if (!dp) - return NULL; - for (; dp != NULL; dp = dp->next) { - if (strcmp(word, dp->word) == 0) - return dp; - } + struct hentry* dp = tableptr[hash(word)]; + if (!dp) + return NULL; + for (; dp != NULL; dp = dp->next) { + if (strcmp(word, dp->word) == 0) + return dp; } return NULL; #endif @@ -265,7 +246,7 @@ else reverseword(*word_copy); - if (in_desc && !aliasm) { + if (in_desc && aliasm.empty()) { desc_copy = new std::string(*in_desc); if (complexprefixes) { @@ -281,14 +262,24 @@ word = word_copy; } + // limit of hp->blen + if (word->size() > std::numeric_limits<unsigned char>::max()) { + HUNSPELL_WARNING(stderr, "error: word len %ld is over max limit\n", word->size()); + delete desc_copy; + delete word_copy; + free_flag(aff, al); + return 1; + } + bool upcasehomonym = false; - int descl = desc ? (aliasm ? sizeof(char*) : desc->size() + 1) : 0; + int descl = desc ? (!aliasm.empty() ? sizeof(char*) : desc->size() + 1) : 0; // variable-length hash record with word and optional fields struct hentry* hp = (struct hentry*)malloc(sizeof(struct hentry) + word->size() + descl); if (!hp) { delete desc_copy; delete word_copy; + free_flag(aff, al); return 1; } @@ -308,18 +299,19 @@ // store the description string or its pointer if (desc) { hp->var |= H_OPT; - if (aliasm) { + if (!aliasm.empty()) { hp->var |= H_OPT_ALIASM; store_pointer(hpw + word->size() + 1, get_aliasm(atoi(desc->c_str()))); } else { strcpy(hpw + word->size() + 1, desc->c_str()); } - if (strstr(HENTRY_DATA(hp), MORPH_PHON)) { + if (HENTRY_FIND(hp, MORPH_PHON)) { hp->var |= H_OPT_PHON; // store ph: fields (pronounciation, misspellings, old orthography etc.) // of a morphological description in reptable to use in REP replacements. - if (reptable.capacity() < (unsigned int)(tablesize/MORPH_PHON_RATIO)) - reptable.reserve(tablesize/MORPH_PHON_RATIO); + size_t predicted = tableptr.size() / MORPH_PHON_RATIO; + if (reptable.capacity() < predicted) + reptable.reserve(predicted); std::string fields = HENTRY_DATA(hp); std::string::const_iterator iter = fields.begin(); std::string::const_iterator start_piece = mystrsep(fields, iter); @@ -610,7 +602,7 @@ if (dp && dp->astr) { int captype; int wcl = get_clen_and_captype(word, &captype); - if (aliasf) { + if (!aliasf.empty()) { add_word(word, wcl, dp->astr, dp->alen, NULL, false, captype); } else { unsigned short* flags = @@ -671,7 +663,7 @@ #else if (hp && hp->next != NULL) return hp->next; - for (col++; col < tablesize; col++) { + for (col++; col < (int)tableptr.size(); ++col) { if (tableptr[col]) return tableptr[col]; } @@ -689,7 +681,7 @@ if (dict == NULL) return 1; - // first read the first line of file to get hash table size */ + // first read the first line of file to get hash table size std::string ts; if (!dict->getline(ts)) { HUNSPELL_WARNING(stderr, "error: empty dic file %s\n", tpath); @@ -703,7 +695,7 @@ ts.erase(0, 3); } - tablesize = atoi(ts.c_str()); + int tablesize = atoi(ts.c_str()); int nExtra = 5 + USERWORD; @@ -720,11 +712,7 @@ tablesize++; // allocate the hash table - tableptr = (struct hentry**)calloc(tablesize, sizeof(struct hentry*)); - if (!tableptr) { - delete dict; - return 3; - } + tableptr.resize(tablesize, nullptr); // loop through all words on much list and add to hash // table and create word and affix strings @@ -781,7 +769,7 @@ if (ap_pos != std::string::npos && ap_pos != ts.size()) { std::string ap(ts.substr(ap_pos + 1)); ts.resize(ap_pos); - if (aliasf) { + if (!aliasf.empty()) { int index = atoi(ap.c_str()); al = get_aliasf(index, &flags, dict); if (!al) { @@ -831,7 +819,7 @@ ROTATE(hv, ROTATE_LEN); hv ^= (*word++); } - return (unsigned long)hv % tablesize; + return (unsigned long)hv % tableptr.size(); #endif } @@ -987,7 +975,7 @@ return true; } -unsigned short HashMgr::decode_flag(const char* f) const { +unsigned short HashMgr::decode_flag(const std::string& f) const { unsigned short s = 0; int i; switch (flag_mode) { @@ -995,7 +983,7 @@ s = ((unsigned short)((unsigned char)f[0]) << 8) + (unsigned char)f[1]; break; case FLAG_NUM: - i = atoi(f); + i = atoi(f.c_str()); if (i >= DEFAULTFLAGS) HUNSPELL_WARNING(stderr, "error: flag id %d is too large (max: %d)\n", i, DEFAULTFLAGS - 1); @@ -1009,7 +997,7 @@ break; } default: - s = *(unsigned char*)f; + s = (unsigned char)f[0]; } if (s == 0) HUNSPELL_WARNING(stderr, "error: 0 is wrong flag id\n"); @@ -1097,7 +1085,7 @@ delete afflst; return 1; } - forbiddenword = decode_flag(st.c_str()); + forbiddenword = decode_flag(st); } if (line.compare(0, 3, "SET", 3) == 0) { @@ -1175,13 +1163,14 @@ /* parse in the ALIAS table */ bool HashMgr::parse_aliasf(const std::string& line, FileMgr* af) { - if (numaliasf != 0) { + if (!aliasf.empty()) { HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); return false; } int i = 0; int np = 0; + int numaliasf = 0; std::string::const_iterator iter = line.begin(); std::string::const_iterator start_piece = mystrsep(line, iter); while (start_piece != line.end()) { @@ -1193,27 +1182,14 @@ case 1: { numaliasf = atoi(std::string(start_piece, iter).c_str()); if (numaliasf < 1) { - numaliasf = 0; - aliasf = NULL; - aliasflen = NULL; + aliasf.clear(); + aliasflen.clear(); HUNSPELL_WARNING(stderr, "error: line %d: bad entry number\n", af->getlinenum()); return false; } - aliasf = - (unsigned short**)malloc(numaliasf * sizeof(unsigned short*)); - aliasflen = - (unsigned short*)malloc(numaliasf * sizeof(unsigned short)); - if (!aliasf || !aliasflen) { - numaliasf = 0; - if (aliasf) - free(aliasf); - if (aliasflen) - free(aliasflen); - aliasf = NULL; - aliasflen = NULL; - return false; - } + aliasf.reserve(numaliasf); + aliasflen.reserve(numaliasf); np++; break; } @@ -1224,21 +1200,18 @@ start_piece = mystrsep(line, iter); } if (np != 2) { - numaliasf = 0; - free(aliasf); - free(aliasflen); - aliasf = NULL; - aliasflen = NULL; + aliasf.clear(); + aliasflen.clear(); HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); return false; } /* now parse the numaliasf lines to read in the remainder of the table */ - for (int j = 0; j < numaliasf; j++) { + for (int j = 0; j < numaliasf; ++j) { std::string nl; - aliasf[j] = NULL; - aliasflen[j] = 0; + unsigned short* alias = NULL; + unsigned aliaslen = 0; i = 0; if (af->getline(nl)) { mychomp(nl); @@ -1256,9 +1229,9 @@ } case 1: { std::string piece(start_piece, iter); - aliasflen[j] = - (unsigned short)decode_flags(&(aliasf[j]), piece, af); - std::sort(aliasf[j], aliasf[j] + aliasflen[j]); + aliaslen = + (unsigned short)decode_flags(&alias, piece, af); + std::sort(alias, alias + aliaslen); break; } default: @@ -1268,19 +1241,19 @@ start_piece = mystrsep(nl, iter); } } - if (!aliasf[j]) { + if (!alias) { for (int k = 0; k < j; ++k) { free(aliasf[k]); } - free(aliasf); - free(aliasflen); - aliasf = NULL; - aliasflen = NULL; - numaliasf = 0; + aliasf.clear(); + aliasflen.clear(); HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); return false; } + + aliasf.push_back(alias); + aliasflen.push_back(aliaslen); } return true; } @@ -1412,11 +1385,11 @@ #endif int HashMgr::is_aliasf() const { - return (aliasf != NULL); + return !aliasf.empty(); } int HashMgr::get_aliasf(int index, unsigned short** fvec, FileMgr* af) const { - if ((index > 0) && (index <= numaliasf)) { + if (index > 0 && static_cast<size_t>(index) <= aliasflen.size()) { *fvec = aliasf[index - 1]; return aliasflen[index - 1]; } @@ -1428,13 +1401,14 @@ /* parse morph alias definitions */ bool HashMgr::parse_aliasm(const std::string& line, FileMgr* af) { - if (numaliasm != 0) { + if (!aliasm.empty()) { HUNSPELL_WARNING(stderr, "error: line %d: multiple table definitions\n", af->getlinenum()); return false; } int i = 0; int np = 0; + int numaliasm = 0; std::string::const_iterator iter = line.begin(); std::string::const_iterator start_piece = mystrsep(line, iter); while (start_piece != line.end()) { @@ -1450,11 +1424,7 @@ af->getlinenum()); return false; } - aliasm = (char**)malloc(numaliasm * sizeof(char*)); - if (!aliasm) { - numaliasm = 0; - return false; - } + aliasm.reserve(numaliasm); np++; break; } @@ -1465,18 +1435,16 @@ start_piece = mystrsep(line, iter); } if (np != 2) { - numaliasm = 0; - free(aliasm); - aliasm = NULL; + aliasm.clear(); HUNSPELL_WARNING(stderr, "error: line %d: missing data\n", af->getlinenum()); return false; } /* now parse the numaliasm lines to read in the remainder of the table */ - for (int j = 0; j < numaliasm; j++) { + for (int j = 0; j < numaliasm; ++j) { std::string nl; - aliasm[j] = NULL; + char* alias = NULL; if (af->getline(nl)) { mychomp(nl); iter = nl.begin(); @@ -1502,7 +1470,7 @@ else reverseword(chunk); } - aliasm[j] = mystrdup(chunk.c_str()); + alias = mystrdup(chunk.c_str()); break; } default: @@ -1512,27 +1480,26 @@ start_piece = mystrsep(nl, iter); } } - if (!aliasm[j]) { - numaliasm = 0; + if (!alias) { for (int k = 0; k < j; ++k) { free(aliasm[k]); } - free(aliasm); - aliasm = NULL; + aliasm.clear(); HUNSPELL_WARNING(stderr, "error: line %d: table is corrupt\n", af->getlinenum()); return false; } + aliasm.push_back(alias); } return true; } int HashMgr::is_aliasm() const { - return (aliasm != NULL); + return !aliasm.empty(); } char* HashMgr::get_aliasm(int index) const { - if ((index > 0) && (index <= numaliasm)) + if (index > 0 && static_cast<size_t>(index) <= aliasm.size()) return aliasm[index - 1]; HUNSPELL_WARNING(stderr, "error: bad morph. alias index: %d\n", index); return NULL;
diff --git a/third_party/hunspell/src/hunspell/hashmgr.hxx b/third_party/hunspell/src/hunspell/hashmgr.hxx index 6fa2ba71..666074a6 100644 --- a/third_party/hunspell/src/hunspell/hashmgr.hxx +++ b/third_party/hunspell/src/hunspell/hashmgr.hxx
@@ -101,8 +101,7 @@ std::map<std::string_view, int> custom_word_to_affix_id_map_; std::vector<std::string*> pointer_to_strings_; #endif - int tablesize; - struct hentry** tableptr; + std::vector<struct hentry*> tableptr; flag flag_mode; int complexprefixes; int utf8; @@ -113,11 +112,9 @@ struct cs_info* csconv; std::string ignorechars; std::vector<w_char> ignorechars_utf16; - int numaliasf; // flag vector `compression' with aliases - unsigned short** aliasf; - unsigned short* aliasflen; - int numaliasm; // morphological desciption `compression' with aliases - char** aliasm; + std::vector<unsigned short*> aliasf; // flag vector `compression' with aliases + std::vector<unsigned short> aliasflen; + std::vector<char*> aliasm; // morphological desciption `compression' with aliases // reptable created from REP table of aff file and from "ph:" fields // of the dic file. It contains phonetic and other common misspellings // (letters, letter groups and words) for better suggestions @@ -152,7 +149,7 @@ int remove(const std::string& word); int decode_flags(unsigned short** result, const std::string& flags, FileMgr* af) const; bool decode_flags(std::vector<unsigned short>& result, const std::string& flags, FileMgr* af) const; - unsigned short decode_flag(const char* flag) const; + unsigned short decode_flag(const std::string& flag) const; char* encode_flag(unsigned short flag) const; int is_aliasf() const; int get_aliasf(int index, unsigned short** fvec, FileMgr* af) const; @@ -216,6 +213,8 @@ bool parse_aliasm(const std::string& line, FileMgr* af); bool parse_reptable(const std::string& line, FileMgr* af); int remove_forbidden_flag(const std::string& word); + void free_table(); + void free_flag(unsigned short* astr, short alen); }; #endif
diff --git a/third_party/hunspell/src/hunspell/hunspell.cxx b/third_party/hunspell/src/hunspell/hunspell.cxx index f699f5c..329e297 100644 --- a/third_party/hunspell/src/hunspell/hunspell.cxx +++ b/third_party/hunspell/src/hunspell/hunspell.cxx
@@ -1969,7 +1969,7 @@ he = m_HMgrs[i]->lookup(word); } if (he) { - slst = pAMgr->get_suffix_words(he->astr, he->alen, root_word.c_str()); + slst = pAMgr->get_suffix_words(he->astr, he->alen, root_word); } return slst; }
diff --git a/third_party/hunspell/src/hunspell/phonet.cxx b/third_party/hunspell/src/hunspell/phonet.cxx index 69601a2..fd4b6b6 100644 --- a/third_party/hunspell/src/hunspell/phonet.cxx +++ b/third_party/hunspell/src/hunspell/phonet.cxx
@@ -108,9 +108,10 @@ if (myisalpha(word[i + k]) // ...could be implied? && strchr(s + 1, word[i + k]) != NULL) { k++; - while (*s != ')') + while (*s && *s != ')') s++; - s++; + if (*s == ')') + s++; } } p0 = (int)*s;
diff --git a/third_party/hunspell/src/hunspell/replist.cxx b/third_party/hunspell/src/hunspell/replist.cxx index 9d52f33..cc861e4d 100644 --- a/third_party/hunspell/src/hunspell/replist.cxx +++ b/third_party/hunspell/src/hunspell/replist.cxx
@@ -77,28 +77,18 @@ #include "csutil.hxx" RepList::RepList(int n) { - dat = (replentry**)malloc(sizeof(replentry*) * n); - if (dat == 0) - size = 0; - else - size = n; - pos = 0; + dat.reserve(n); } RepList::~RepList() { - for (int i = 0; i < pos; i++) { + for (size_t i = 0, pos = dat.size(); i < pos; ++i) { delete dat[i]; } - free(dat); -} - -replentry* RepList::item(int n) { - return dat[n]; } int RepList::find(const char* word) { int p1 = 0; - int p2 = pos - 1; + int p2 = dat.size() - 1; int ret = -1; while (p1 <= p2) { int m = ((unsigned)p1 + (unsigned)p2) >> 1; @@ -115,11 +105,11 @@ return ret; } -std::string RepList::replace(const char* word, int ind, bool atstart) { +std::string RepList::replace(const size_t wordlen, int ind, bool atstart) { int type = atstart ? 1 : 0; if (ind < 0) return std::string(); - if (strlen(word) == dat[ind]->pattern.size()) + if (wordlen == dat[ind]->pattern.size()) type = atstart ? 3 : 2; while (type && dat[ind]->outstrings[type].empty()) type = (type == 2 && !atstart) ? 0 : type - 1; @@ -127,7 +117,7 @@ } int RepList::add(const std::string& in_pat1, const std::string& pat2) { - if (pos >= size || in_pat1.empty() || pat2.empty()) { + if (in_pat1.empty() || pat2.empty()) { return 1; } // analyse word context @@ -159,11 +149,11 @@ r->pattern = pat1; r->outstrings[type] = pat2; mystrrep(r->outstrings[type], "_", " "); - dat[pos++] = r; + dat.push_back(r); // sort to the right place in the list #if 0 - int i; - for (i = pos - 1; i > 0; i--) { + size_t i; + for (i = dat.size() - 1; i > 0; --i) { if (strcmp(r->pattern.c_str(), dat[i - 1]->pattern.c_str()) < 0) { dat[i] = dat[i - 1]; } else @@ -171,7 +161,7 @@ } dat[i] = r; #else - for (int i = pos - 1; i > 0; i--) { + for (int i = dat.size() - 1; i > 0; --i) { r = dat[i]; if (r->pattern < dat[i - 1]->pattern) { dat[i] = dat[i - 1]; @@ -191,7 +181,7 @@ bool change = false; for (size_t i = 0; i < wordlen; ++i) { int n = find(word + i); - std::string l = replace(word + i, n, i == 0); + std::string l = replace(wordlen - i, n, i == 0); if (!l.empty()) { dest.append(l); i += dat[n]->pattern.size() - 1;
diff --git a/third_party/hunspell/src/hunspell/replist.hxx b/third_party/hunspell/src/hunspell/replist.hxx index 2bc8aa74..35fe025 100644 --- a/third_party/hunspell/src/hunspell/replist.hxx +++ b/third_party/hunspell/src/hunspell/replist.hxx
@@ -88,19 +88,15 @@ RepList(const RepList&); RepList& operator=(const RepList&); - protected: - replentry** dat; - int size; - int pos; + std::vector<replentry*> dat; public: explicit RepList(int n); ~RepList(); int add(const std::string& pat1, const std::string& pat2); - replentry* item(int n); int find(const char* word); - std::string replace(const char* word, int n, bool atstart); + std::string replace(const size_t wordlen, int n, bool atstart); bool conv(const std::string& word, std::string& dest); }; #endif
diff --git a/third_party/hunspell/src/hunspell/suggestmgr.cxx b/third_party/hunspell/src/hunspell/suggestmgr.cxx index 2be03dd..c35b491 100644 --- a/third_party/hunspell/src/hunspell/suggestmgr.cxx +++ b/third_party/hunspell/src/hunspell/suggestmgr.cxx
@@ -499,18 +499,19 @@ timelimit = clock(); timer = MINTIMER; return map_related(word, candidate, 0, wlst, cpdsuggest, - maptable, &timer, &timelimit); + maptable, &timer, &timelimit, 0); } -int SuggestMgr::map_related(const char* word, +int SuggestMgr::map_related(const std::string& word, std::string& candidate, - int wn, + size_t wn, std::vector<std::string>& wlst, int cpdsuggest, const std::vector<mapentry>& maptable, int* timer, - clock_t* timelimit) { - if (*(word + wn) == '\0') { + clock_t* timelimit, + int depth) { + if (word.size() == wn) { int cwrd = 1; for (size_t m = 0; m < wlst.size(); ++m) { if (wlst[m] == candidate) { @@ -525,18 +526,24 @@ } return wlst.size(); } + + if (depth > 16384) { + *timer = 0; + return wlst.size(); + } + int in_map = 0; for (size_t j = 0; j < maptable.size(); ++j) { for (size_t k = 0; k < maptable[j].size(); ++k) { size_t len = maptable[j][k].size(); - if (strncmp(maptable[j][k].c_str(), word + wn, len) == 0) { + if (len && word.compare(wn, len, maptable[j][k]) == 0) { in_map = 1; size_t cn = candidate.size(); for (size_t l = 0; l < maptable[j].size(); ++l) { candidate.resize(cn); candidate.append(maptable[j][l]); map_related(word, candidate, wn + len, wlst, - cpdsuggest, maptable, timer, timelimit); + cpdsuggest, maptable, timer, timelimit, depth + 1); if (!(*timer)) return wlst.size(); } @@ -544,9 +551,9 @@ } } if (!in_map) { - candidate.push_back(*(word + wn)); + candidate.push_back(word[wn]); map_related(word, candidate, wn + 1, wlst, cpdsuggest, - maptable, timer, timelimit); + maptable, timer, timelimit, depth + 1); } return wlst.size(); } @@ -554,10 +561,10 @@ // suggestions for a typical fault of spelling, that // differs with more, than 1 letter from the right form. int SuggestMgr::replchars(std::vector<std::string>& wlst, - const char* word, + const std::string& word, int cpdsuggest) { std::string candidate; - int wl = strlen(word); + int wl = word.size(); if (wl < 2 || !pAMgr) return wlst.size(); @@ -566,34 +573,33 @@ const char *pattern, *pattern2; hunspell::ReplacementIterator iterator = bdict_reader->GetReplacementIterator(); while (iterator.GetNext(&pattern, &pattern2)) { - const char* r = word; + size_t r = 0; size_t lenr = strlen(pattern2); size_t lenp = strlen(pattern); // search every occurence of the pattern in the word - while ((r=strstr(r, pattern)) != NULL) { + while ((r = word.find(pattern, r)) != std::string::npos) { candidate = word; - candidate.replace(r-word, lenp, pattern2); + candidate.replace(r, lenp, pattern2); #else const std::vector<replentry>& reptable = pAMgr->get_reptable(); for (size_t i = 0; i < reptable.size(); ++i) { - const char* r = word; + size_t r = 0; // search every occurence of the pattern in the word - while ((r = strstr(r, reptable[i].pattern.c_str())) != NULL) { - int type = (r == word) ? 1 : 0; - if (r - word + reptable[i].pattern.size() == strlen(word)) + while ((r = word.find(reptable[i].pattern, r)) != std::string::npos) { + int type = (r == 0) ? 1 : 0; + if (r + reptable[i].pattern.size() == word.size()) type += 2; while (type && reptable[i].outstrings[type].empty()) - type = (type == 2 && r != word) ? 0 : type - 1; + type = (type == 2 && r != 0) ? 0 : type - 1; const std::string&out = reptable[i].outstrings[type]; if (out.empty()) { ++r; continue; } - candidate.assign(word); - candidate.resize(r - word); + candidate.assign(word, 0, r); candidate.append(reptable[i].outstrings[type]); - candidate.append(r + reptable[i].pattern.size()); + candidate.append(word, r + reptable[i].pattern.size(), std::string::npos); #endif testsug(wlst, candidate, cpdsuggest, NULL, NULL); // check REP suggestions with space @@ -1814,9 +1820,9 @@ } if (!rv && pAMgr->have_contclass()) { - rv = pAMgr->suffix_check_twosfx(word.c_str(), word.size(), 0, NULL, FLAG_NULL); + rv = pAMgr->suffix_check_twosfx(word, word.size(), 0, NULL, FLAG_NULL); if (!rv) - rv = pAMgr->prefix_check_twosfx(word.c_str(), word.size(), 0, FLAG_NULL); + rv = pAMgr->prefix_check_twosfx(word, word.size(), 0, FLAG_NULL); } // check forbidden words @@ -1901,8 +1907,7 @@ if (pAMgr->get_compound() && result.empty()) { struct hentry* rwords[100]; // buffer for COMPOUND pattern checking - pAMgr->compound_check_morph(w.c_str(), w.size(), 0, 0, 100, 0, NULL, (hentry**)&rwords, 0, result, - NULL); + pAMgr->compound_check_morph(w, 0, 0, 100, 0, NULL, (hentry**)&rwords, 0, result, NULL); } line_uniq(result, MSEP_REC);
diff --git a/third_party/hunspell/src/hunspell/suggestmgr.hxx b/third_party/hunspell/src/hunspell/suggestmgr.hxx index 925c6a0..35c8903 100644 --- a/third_party/hunspell/src/hunspell/suggestmgr.hxx +++ b/third_party/hunspell/src/hunspell/suggestmgr.hxx
@@ -143,7 +143,7 @@ int check_forbidden(const char*, int); void capchars(std::vector<std::string>&, const char*, int); - int replchars(std::vector<std::string>&, const char*, int); + int replchars(std::vector<std::string>&, const std::string&, int); int doubletwochars(std::vector<std::string>&, const char*, int); int forgotchar(std::vector<std::string>&, const char*, int); int swapchar(std::vector<std::string>&, const char*, int); @@ -165,14 +165,15 @@ int movechar_utf(std::vector<std::string>&, const w_char*, int, int); int mapchars(std::vector<std::string>&, const char*, int); - int map_related(const char*, + int map_related(const std::string&, std::string&, - int, + size_t, std::vector<std::string>& wlst, int, const std::vector<mapentry>&, int*, - clock_t*); + clock_t*, + int depth); int ngram(int n, const std::vector<w_char>& su1, const std::vector<w_char>& su2, int opt); int ngram(int n, const std::string& s1, const std::string& s2, int opt);
diff --git a/third_party/hunspell/src/parsers/latexparser.cxx b/third_party/hunspell/src/parsers/latexparser.cxx index ea0335c..1188ed9 100644 --- a/third_party/hunspell/src/parsers/latexparser.cxx +++ b/third_party/hunspell/src/parsers/latexparser.cxx
@@ -217,13 +217,13 @@ break; case 1: // wordchar apostrophe = 0; - if ((is_wordchar((char*)APOSTROPHE) || - (is_utf8() && is_wordchar((char*)UTF8_APOS))) && + if ((is_wordchar(APOSTROPHE) || + (is_utf8() && is_wordchar(UTF8_APOS))) && !line[actual].empty() && line[actual][head] == '\'' && is_wordchar(line[actual].c_str() + head + 1)) { head++; } else if (is_utf8() && - is_wordchar((char*)APOSTROPHE) && // add Unicode apostrophe + is_wordchar(APOSTROPHE) && // add Unicode apostrophe // to the WORDCHARS, if // needed strncmp(line[actual].c_str() + head, UTF8_APOS, strlen(UTF8_APOS)) ==
diff --git a/third_party/hunspell/src/parsers/textparser.cxx b/third_party/hunspell/src/parsers/textparser.cxx index fb1bc9a..d798075 100644 --- a/third_party/hunspell/src/parsers/textparser.cxx +++ b/third_party/hunspell/src/parsers/textparser.cxx
@@ -77,18 +77,19 @@ int TextParser::is_wordchar(const char* w) { if (*w == '\0') return 0; + size_t cache_index = (*w + 256) % 256; if (utf8) { - std::vector<w_char> wc; - unsigned short idx; - u8_u16(wc, w); - if (wc.empty()) + const bool use_cache = cache_index < 0x80; + if (use_cache) + return wordcharacters[cache_index]; + if (u8_u16(wc, w, true) < 1) return 0; - idx = (wc[0].h << 8) + wc[0].l; - return (unicodeisalpha(idx) || - (wordchars_utf16 && - std::binary_search(wordchars_utf16, wordchars_utf16 + wclen, wc[0]))); + unsigned short idx = (wc[0].h << 8) + wc[0].l; + return unicodeisalpha(idx) || + (wordchars_utf16 && + std::binary_search(wordchars_utf16, wordchars_utf16 + wclen, wc[0])); } else { - return wordcharacters[(*w + 256) % 256]; + return wordcharacters[cache_index]; } } @@ -120,15 +121,27 @@ } } -void TextParser::init(const w_char* wc, int len) { +void TextParser::init(const w_char* wc_utf8, int len) { actual = 0; head = 0; token = 0; state = 0; utf8 = 1; checkurl = 0; - wordchars_utf16 = wc; + wordchars_utf16 = wc_utf8; wclen = len; + + // build a cache for the simple cases + wordcharacters.resize(0x80); + w_char wc2; + wc2.h = 0; + for (unsigned char idx = 0; idx < 0x80; ++idx) { + wc2.l = idx; + int cache = unicodeisalpha(idx) || + (wordchars_utf16 && + std::binary_search(wordchars_utf16, wordchars_utf16 + wclen, wc2)); + wordcharacters[idx] = cache; + } } int TextParser::next_char(const char* ln, size_t* pos) { @@ -181,13 +194,13 @@ case 1: // wordchar if ((latin1 = get_latin1(line[actual].c_str() + head))) { head += strlen(latin1); - } else if ((is_wordchar((char*)APOSTROPHE) || - (is_utf8() && is_wordchar((char*)UTF8_APOS))) && + } else if ((is_wordchar(APOSTROPHE) || + (is_utf8() && is_wordchar(UTF8_APOS))) && !line[actual].empty() && line[actual][head] == '\'' && is_wordchar(line[actual].c_str() + head + 1)) { head++; } else if (is_utf8() && - is_wordchar((char*)APOSTROPHE) && // add Unicode apostrophe + is_wordchar(APOSTROPHE) && // add Unicode apostrophe // to the WORDCHARS, if // needed strncmp(line[actual].c_str() + head, UTF8_APOS, strlen(UTF8_APOS)) ==
diff --git a/third_party/hunspell/src/parsers/textparser.hxx b/third_party/hunspell/src/parsers/textparser.hxx index 94a1f77..06e7a68 100644 --- a/third_party/hunspell/src/parsers/textparser.hxx +++ b/third_party/hunspell/src/parsers/textparser.hxx
@@ -59,6 +59,7 @@ std::vector<int> wordcharacters;// for detection of the word boundaries std::string line[MAXPREVLINE]; // parsed and previous lines std::vector<bool> urlline; // mask for url detection + std::vector<w_char> wc; int checkurl; int actual; // actual line size_t head; // head position
diff --git a/third_party/hunspell/src/parsers/xmlparser.cxx b/third_party/hunspell/src/parsers/xmlparser.cxx index 83a20c9..aacc977 100644 --- a/third_party/hunspell/src/parsers/xmlparser.cxx +++ b/third_party/hunspell/src/parsers/xmlparser.cxx
@@ -135,14 +135,14 @@ case ST_WORD: // wordchar if ((latin1 = get_latin1(line[actual].c_str() + head))) { head += strlen(latin1); - } else if ((is_wordchar((char*)APOSTROPHE) || - (is_utf8() && is_wordchar((char*)UTF8_APOS))) && + } else if ((is_wordchar(APOSTROPHE) || + (is_utf8() && is_wordchar(UTF8_APOS))) && strncmp(line[actual].c_str() + head, ENTITY_APOS, strlen(ENTITY_APOS)) == 0 && is_wordchar(line[actual].c_str() + head + strlen(ENTITY_APOS))) { head += strlen(ENTITY_APOS) - 1; } else if (is_utf8() && - is_wordchar((char*)APOSTROPHE) && // add Unicode apostrophe + is_wordchar(APOSTROPHE) && // add Unicode apostrophe // to the WORDCHARS, if // needed strncmp(line[actual].c_str() + head, UTF8_APOS, strlen(UTF8_APOS)) ==
diff --git a/tools/crates/run_cargo.py b/tools/crates/run_cargo.py index c83086a..518c0ff 100755 --- a/tools/crates/run_cargo.py +++ b/tools/crates/run_cargo.py
@@ -14,9 +14,10 @@ import platform import subprocess import sys +import pathlib -DEFAULT_SYSROOT = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', - '..', 'third_party', 'rust-toolchain') +DEFAULT_SYSROOT = pathlib.Path(__file__).parents[2].joinpath( + 'third_party', 'rust-toolchain') # Determine the cargo executable name based on whether `subprocess` thinks # we're on a Windows platform or not, which is more accurate than checking it @@ -25,12 +26,12 @@ def RunCargo(rust_sysroot, home_dir, cargo_args): - if not os.path.exists(rust_sysroot): + rust_sysroot = pathlib.Path(rust_sysroot) + if not rust_sysroot.exists(): print(f'WARNING: Rust sysroot missing at "{rust_sysroot}"') - abs_rust_sysroot = os.path.abspath(rust_sysroot) - bin_dir = os.path.join(abs_rust_sysroot, 'bin') - cargo_path = os.path.join(bin_dir, _CARGO_EXE) + bin_dir = rust_sysroot.absolute().joinpath('bin') + cargo_path = bin_dir.joinpath(_CARGO_EXE) cargo_env = dict(os.environ) if home_dir: @@ -66,6 +67,7 @@ parser = argparse.ArgumentParser(description='run cargo') parser.add_argument('--rust-sysroot', default=DEFAULT_SYSROOT, + type=pathlib.Path, help='use cargo and rustc from here') (args, cargo_args) = parser.parse_known_args() return RunCargo(args.rust_sysroot, None, cargo_args)
diff --git a/tools/crates/run_cargo_vet.py b/tools/crates/run_cargo_vet.py index 2719de0..16a9e8d 100755 --- a/tools/crates/run_cargo_vet.py +++ b/tools/crates/run_cargo_vet.py
@@ -14,6 +14,7 @@ import argparse import os +import pathlib import platform import subprocess import sys @@ -46,6 +47,7 @@ 'run `cargo vet` against `//third_party/rust/chromium_crates_io`') parser.add_argument('--rust-sysroot', default=DEFAULT_SYSROOT, + type=pathlib.Path, help='use cargo and rustc from here') (args, unrecognized_args) = parser.parse_known_args()
diff --git a/tools/crates/run_gnrt.py b/tools/crates/run_gnrt.py index 9254cf0f..ed074743 100755 --- a/tools/crates/run_gnrt.py +++ b/tools/crates/run_gnrt.py
@@ -9,6 +9,7 @@ import argparse import os +import pathlib import platform import subprocess import sys @@ -22,6 +23,7 @@ parser = argparse.ArgumentParser(description='build and run gnrt') parser.add_argument('--rust-sysroot', default=DEFAULT_SYSROOT, + type=pathlib.Path, help='use cargo and rustc from here') parser.add_argument('--out-dir', default='out/gnrt',
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 32f393a0..f631a44 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -319,7 +319,7 @@ ], 'asan_lsan_release_trybot_remoteexec': [ - 'asan', 'lsan', 'release_trybot_minimal_symbols_remoteexec', 'use_siso', 'reclient', + 'asan', 'lsan', 'release_trybot_minimal_symbols_remoteexec', 'use_siso', ], 'cast_binary_size_remoteexec': [ @@ -387,7 +387,7 @@ ], 'debug_bot_blink': [ - 'debug_bot_blink', 'use_siso', 'reclient', + 'debug_bot_blink', 'use_siso', ], 'debug_bot_remoteexec': [ @@ -412,15 +412,15 @@ ], 'gpu_tests_release_trybot_minimal_symbol_x86_resource_allowlisting_remoteexec': [ - 'gpu_tests', 'release_trybot_minimal_symbols_remoteexec', 'x86', 'resource_allowlisting', 'use_siso', 'reclient', + 'gpu_tests', 'release_trybot_minimal_symbols_remoteexec', 'x86', 'resource_allowlisting', 'use_siso', ], 'gpu_tests_release_trybot_minimal_symbols_remoteexec': [ - 'gpu_tests', 'release_trybot_minimal_symbols_remoteexec', 'use_siso', 'reclient', + 'gpu_tests', 'release_trybot_minimal_symbols_remoteexec', 'use_siso', ], 'gpu_tests_release_trybot_ptr_comp_remoteexec': [ - 'gpu_tests', 'release_trybot_minimal_symbols_remoteexec', 'v8_pointer_compression', 'use_siso', 'reclient', + 'gpu_tests', 'release_trybot_minimal_symbols_remoteexec', 'v8_pointer_compression', 'use_siso', ], 'gpu_tests_release_trybot_remoteexec_siso': [ @@ -637,15 +637,15 @@ ], 'release_bot_blink': [ - 'release_bot_blink', 'use_siso', 'reclient', + 'release_bot_blink', 'use_siso', ], 'release_bot_blink_v8_debug_remoteexec': [ - 'release_bot_blink', 'v8_enable_debugging_features', 'use_siso', 'reclient' + 'release_bot_blink', 'v8_enable_debugging_features', 'use_siso' ], 'release_bot_remoteexec': [ - 'release_bot_remoteexec', 'reclient', + 'release_bot_remoteexec', 'use_siso', ], 'release_trybot_blink_do_typecheck_siso': [ @@ -1013,11 +1013,6 @@ 'gn_args': 'proprietary_codecs=true', }, - # TODO: crbug.com/379584977 - Remove this mixin after dropping reclient. - 'reclient': { - 'gn_args': 'use_reclient=true', - }, - # Historically, a 'release' bot had DCHECKs turned off. DCHECKs are now # enabled by default, but explicitly turning them off here preserves # backwards compatibility. TODO: We should probably come up with better
diff --git a/tools/mb/mb_config_expectations/client.v8.chromium.json b/tools/mb/mb_config_expectations/client.v8.chromium.json index 2c1ae46..cc3b8d2a 100644 --- a/tools/mb/mb_config_expectations/client.v8.chromium.json +++ b/tools/mb/mb_config_expectations/client.v8.chromium.json
@@ -4,8 +4,9 @@ "dcheck_always_on": false, "is_component_build": false, "is_debug": false, - "use_reclient": true, - "use_remoteexec": true + "use_reclient": false, + "use_remoteexec": true, + "use_siso": true } } } \ No newline at end of file
diff --git a/tools/mb/mb_config_expectations/client.v8.fyi.json b/tools/mb/mb_config_expectations/client.v8.fyi.json index 41d02f0..be49792 100644 --- a/tools/mb/mb_config_expectations/client.v8.fyi.json +++ b/tools/mb/mb_config_expectations/client.v8.fyi.json
@@ -25,7 +25,7 @@ "is_debug": false, "is_lsan": true, "symbol_level": 1, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true } @@ -37,7 +37,7 @@ "is_debug": true, "proprietary_codecs": true, "symbol_level": 1, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true } @@ -50,7 +50,7 @@ "is_debug": false, "proprietary_codecs": true, "symbol_level": 1, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true } @@ -63,7 +63,7 @@ "is_debug": false, "proprietary_codecs": true, "symbol_level": 1, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true, "v8_enable_pointer_compression": false @@ -77,7 +77,7 @@ "is_debug": false, "proprietary_codecs": true, "symbol_level": 1, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true } @@ -89,7 +89,7 @@ "is_component_build": false, "is_debug": false, "proprietary_codecs": true, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true } @@ -101,7 +101,7 @@ "is_component_build": false, "is_debug": false, "proprietary_codecs": true, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true, "v8_enable_debugging_features": true @@ -114,7 +114,7 @@ "is_component_build": false, "is_debug": false, "proprietary_codecs": true, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true } @@ -126,7 +126,7 @@ "is_component_build": false, "is_debug": false, "proprietary_codecs": true, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true } @@ -138,7 +138,7 @@ "is_component_build": false, "is_debug": false, "proprietary_codecs": true, - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true } @@ -153,7 +153,7 @@ "proprietary_codecs": true, "symbol_level": 1, "target_cpu": "x86", - "use_reclient": true, + "use_reclient": false, "use_remoteexec": true, "use_siso": true }
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index e691575..d336106 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -8745,6 +8745,7 @@ <int value="-2134333982" label="ShowArcFilesApp:enabled"/> <int value="-2134244069" label="HttpFormWarning:enabled"/> <int value="-2133892372" label="ResamplingInputEvents:disabled"/> + <int value="-2133694243" label="AllowTabClosingUponMinimization:disabled"/> <int value="-2133277113" label="CCTModuleCustomHeader:disabled"/> <int value="-2133276662" label="EduCoexistenceConsentLog:disabled"/> <int value="-2132591642" label="enable-input-view"/> @@ -14193,6 +14194,7 @@ <int value="-67176255" label="PeripheralNotification:disabled"/> <int value="-66834375" label="SharesheetCopyToClipboard:enabled"/> <int value="-66535194" label="DesktopMinimalUI:enabled"/> + <int value="-65929089" label="CpaSpecUpdate:enabled"/> <int value="-64839201" label="SyncUSSAutofillWalletData:disabled"/> <int value="-64824628" label="VizHitTestSurfaceLayer:disabled"/> <int value="-64747770" label="IncognitoDownloadsWarning:disabled"/> @@ -17215,6 +17217,7 @@ <int value="1101421005" label="DownloadLater:disabled"/> <int value="1102035446" label="AutofillUpstreamAuthenticatePreflightCall:enabled"/> + <int value="1102164603" label="AllowTabClosingUponMinimization:enabled"/> <int value="1102309668" label="EnableKeyboardUsedPalmSuppression:disabled"/> <int value="1102780374" label="ClickToCallDetectionV2:disabled"/> <int value="1103037724" label="AiSettingsPageEnterpriseDisabledUi:enabled"/> @@ -18046,6 +18049,7 @@ <int value="1408331660" label="enhanced-bookmarks-experiment"/> <int value="1409120591" label="PassiveMixedContentWarning:disabled"/> <int value="1409437197" label="OfflinePagesLimitlessPrefetching:enabled"/> + <int value="1409625676" label="CpaSpecUpdate:disabled"/> <int value="1409653883" label="GetUserMediaDeferredDeviceSettingsSelection:disabled"/> <int value="1410403456" label="AndroidBrowserControlsInViz:enabled"/>
diff --git a/tools/metrics/histograms/metadata/contextual_cueing/histograms.xml b/tools/metrics/histograms/metadata/contextual_cueing/histograms.xml index 5a60929..6243506 100644 --- a/tools/metrics/histograms/metadata/contextual_cueing/histograms.xml +++ b/tools/metrics/histograms/metadata/contextual_cueing/histograms.xml
@@ -55,6 +55,27 @@ </histogram> <histogram + name="ContextualCueing.GlicSuggestions.SuggestionsFetchLatency.{ResultType}" + units="ms" expires_after="2025-08-30"> + <owner>zekunjiang@google.com</owner> + <owner>rajendrant@google.com</owner> + <owner>sophiechang@chromium.org</owner> + <summary> + Recorded every time something is returned as a result of invoking the + suggestions fetch API. The results are split by the type of results returned + (e.g. results with no suggestions vs results with valid suggestions). + </summary> + <token key="ResultType"> + <variant name="EmptySuggestions" + summary="When no suggestions are returned as a result of a + suggestions fetch"/> + <variant name="ValidSuggestions" + summary="When valid suggestions are returned as a result of a + suggestions fetch"/> + </token> +</histogram> + +<histogram name="ContextualCueing.NudgeDecision.{ContextualCueingOptimizationType}" enum="ContextualCueingNudgeDecision" expires_after="2025-08-30"> <owner>sophiechang@chromium.org</owner>
diff --git a/ui/accessibility/ax_bit_map.h b/ui/accessibility/ax_bit_map.h index 271722d..a0175925 100644 --- a/ui/accessibility/ax_bit_map.h +++ b/ui/accessibility/ax_bit_map.h
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include <array>
diff --git a/ui/android/java/src/org/chromium/ui/base/DeviceInput.java b/ui/android/java/src/org/chromium/ui/base/DeviceInput.java index a96c8ca8..3aa7602 100644 --- a/ui/android/java/src/org/chromium/ui/base/DeviceInput.java +++ b/ui/android/java/src/org/chromium/ui/base/DeviceInput.java
@@ -52,7 +52,9 @@ for (int i = 0; i < deviceIds.length; i++) { int deviceId = deviceIds[i]; InputDevice device = InputDevice.getDevice(deviceId); - if (device != null) mDeviceSnapshotsById.put(deviceId, DeviceSnapshot.from(device)); + if (device != null) { + mDeviceSnapshotsById.put(deviceId, DeviceSnapshot.from(device)); + } } // Register listener to perform cache updates. @@ -89,7 +91,9 @@ return sSupportsAlphabeticKeyboardForTesting; } for (int i = 0; i < mDeviceSnapshotsById.size(); i++) { - if (mDeviceSnapshotsById.valueAt(i).supportsAlphabeticKeyboard) return true; + if (mDeviceSnapshotsById.valueAt(i).supportsAlphabeticKeyboard) { + return true; + } } return false; } @@ -117,7 +121,9 @@ return sSupportsPrecisionPointerForTesting; } for (int i = 0; i < mDeviceSnapshotsById.size(); i++) { - if (mDeviceSnapshotsById.valueAt(i).supportsPrecisionPointer) return true; + if (mDeviceSnapshotsById.valueAt(i).supportsPrecisionPointer) { + return true; + } } return false; } @@ -126,15 +132,20 @@ public void onInputDeviceAdded(int deviceId) { ThreadUtils.assertOnUiThread(); InputDevice device = InputDevice.getDevice(deviceId); - if (device != null) mDeviceSnapshotsById.put(deviceId, DeviceSnapshot.from(device)); + if (device != null) { + mDeviceSnapshotsById.put(deviceId, DeviceSnapshot.from(device)); + } } @Override public void onInputDeviceChanged(int deviceId) { ThreadUtils.assertOnUiThread(); InputDevice device = InputDevice.getDevice(deviceId); - if (device != null) mDeviceSnapshotsById.put(deviceId, DeviceSnapshot.from(device)); - else mDeviceSnapshotsById.remove(deviceId); + if (device != null) { + mDeviceSnapshotsById.put(deviceId, DeviceSnapshot.from(device)); + } else { + mDeviceSnapshotsById.remove(deviceId); + } } @Override @@ -171,6 +182,7 @@ return new DeviceSnapshot( /* supportsAlphabeticKeyboard= */ isPhysical && device.getKeyboardType() == KEYBOARD_TYPE_ALPHABETIC, + // SOURCE_MOUSE applies to pointer devices, including mouse and touchpad /* supportsPrecisionPointer= */ isPhysical && device.supportsSource(SOURCE_MOUSE)); }
diff --git a/ui/base/webui/web_ui_util.cc b/ui/base/webui/web_ui_util.cc index 46a4ec9..c2cd68ef 100644 --- a/ui/base/webui/web_ui_util.cc +++ b/ui/base/webui/web_ui_util.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/40285824): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "ui/base/webui/web_ui_util.h"
diff --git a/ui/compositor/debug_utils.cc b/ui/compositor/debug_utils.cc index 256386e..70ace71d0 100644 --- a/ui/compositor/debug_utils.cc +++ b/ui/compositor/debug_utils.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "ui/compositor/debug_utils.h"
diff --git a/ui/display/util/edid_parser.cc b/ui/display/util/edid_parser.cc index 8f6a91f..939fe32 100644 --- a/ui/display/util/edid_parser.cc +++ b/ui/display/util/edid_parser.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "ui/display/util/edid_parser.h"
diff --git a/ui/gfx/color_transform_unittest.cc b/ui/gfx/color_transform_unittest.cc index 9514c654..9177fdf 100644 --- a/ui/gfx/color_transform_unittest.cc +++ b/ui/gfx/color_transform_unittest.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/354829279): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "ui/gfx/color_transform.h"
diff --git a/ui/message_center/message_center_stats_collector.cc b/ui/message_center/message_center_stats_collector.cc index db52080..45f35e7 100644 --- a/ui/message_center/message_center_stats_collector.cc +++ b/ui/message_center/message_center_stats_collector.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "ui/message_center/message_center_stats_collector.h"
diff --git a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc index 5db1e212..8bfa9bd 100644 --- a/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc +++ b/ui/ozone/demo/skia/skia_surfaceless_gl_renderer.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "ui/ozone/demo/skia/skia_surfaceless_gl_renderer.h"
diff --git a/ui/ozone/demo/surfaceless_gl_renderer.cc b/ui/ozone/demo/surfaceless_gl_renderer.cc index 6926973..2487fd0b 100644 --- a/ui/ozone/demo/surfaceless_gl_renderer.cc +++ b/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "ui/ozone/demo/surfaceless_gl_renderer.h"
diff --git a/ui/ozone/demo/vulkan_overlay_renderer.cc b/ui/ozone/demo/vulkan_overlay_renderer.cc index 416aa9923..236782b2 100644 --- a/ui/ozone/demo/vulkan_overlay_renderer.cc +++ b/ui/ozone/demo/vulkan_overlay_renderer.cc
@@ -2,10 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifdef UNSAFE_BUFFERS_BUILD -// TODO(crbug.com/351564777): Remove this and convert code to safer constructs. -#pragma allow_unsafe_buffers -#endif #include "ui/ozone/demo/vulkan_overlay_renderer.h"