diff --git a/DEPS b/DEPS index 3903934..45a88c3 100644 --- a/DEPS +++ b/DEPS
@@ -305,19 +305,19 @@ # 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': '00df6ccb195fb28a11b4cf5e75ec4f4ff0184a28', + 'src_internal_revision': 'b49cbaf2dea6f1fbf2c6c1c3a09c585e3e80dc3f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': 'cd3d3daafe559192288d12cde5722034b935df7f', + 'skia_revision': 'f1b130c74c5327c8d4919d74fd4efc80890c77e8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. - 'v8_revision': '1eb663b94ad6497cc132406af5e9ed696bf2448c', + 'v8_revision': '3989e5c91c126ec93396b4022a9ba6665500350f', # 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': 'f25948774f7c24ef4d28c42cb0fee0e69aac0489', + 'angle_revision': '24a3d30d02ff37aa148f9ff41e3200bc66865b50', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. @@ -332,7 +332,7 @@ # # Note this revision should be updated with # third_party/boringssl/roll_boringssl.py, not roll-dep. - 'boringssl_revision': 'f1b043c28352a4e79114324ca2e86df33922e843', + 'boringssl_revision': 'd3c1afdc1b3ca24469c895dff659cff3accb6c56', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Fuchsia sdk # and whatever else without interference from each other. @@ -388,7 +388,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling CrossBench # and whatever else without interference from each other. - 'crossbench_revision': '4a6a61d7a060123c387c21d296b73ffecd9de2a2', + 'crossbench_revision': '4bac63a1a8c5c2079ee915f3568802fa96ec591e', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -404,7 +404,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': '25ba3401dee476c69cb9df7be12fea0b9a9377d4', + 'devtools_frontend_revision': '1f7b38eb44bce769dd9c25d9a24fb1c00193fb16', # 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. @@ -714,7 +714,7 @@ 'packages': [ { 'package': 'chrome_internal/third_party/google3/data_sharing_sdk', - 'version': '4aIIq-rDZI5mGeROQ42Oekdt9QAD6UNWE0TYMy1qGLQC', + 'version': 'O8f801tf1yCNOWuctzUdCgeOaTocPXrCrMDFX8zAKswC', }, ], 'condition': 'checkout_src_internal and non_git_source', @@ -1295,12 +1295,12 @@ 'src/clank': { 'url': Var('chrome_git') + '/clank/internal/apps.git' + '@' + - '1dff60ff4bbb8b13831e78c6c4e32a1445b37cbe', + '9ab4f6780971f4824a29937121d8e447a043b67d', 'condition': 'checkout_android and checkout_src_internal', }, 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + '2860bb82fe04cccb9716f89492f7b981144403d8', + 'url': Var('chromium_git') + '/website.git' + '@' + '66de3b3613bef02e6d95dc3e2148ff577e8acf67', }, 'src/ios/third_party/earl_grey2/src': { @@ -1722,7 +1722,7 @@ # Tools used when building Chrome for Chrome OS. This affects both the Simple # Chrome workflow, as well as the chromeos-chrome ebuild. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd088a2e0aeba09f7c9fda5f6105fc275af13f01c', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '2aa46d5583da48a991526b3849ce3993b82c06c8', 'condition': 'checkout_chromeos', }, @@ -1757,13 +1757,13 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1f6ef165b726ed7316b8e88666390e90a82e8e50', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + 'aaaca2863c2bf13df8b9256cb53a276c7ebbfc07', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), 'src/third_party/devtools-frontend-internal': { - 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '6f01cd303a3c15410a17512002f66c72e6a8e5e6', + 'url': Var('chrome_git') + '/devtools/devtools-internal.git' + '@' + '2693858869047a9bc7ca57362c543793b85f69a8', 'condition': 'checkout_src_internal', }, @@ -2249,7 +2249,7 @@ Var('pdfium_git') + '/pdfium.git' + '@' + Var('pdfium_revision'), 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + '05564d1572f910f8e8e50eba47ef8d7163e4ee0a', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '700c45efcea755315945adc001f31b3d1e51c226', 'src/base/tracing/test/data': { 'bucket': 'perfetto', @@ -2391,7 +2391,7 @@ 'packages': [ { 'package': 'chromium/third_party/r8', - 'version': 'Ct5P52jBNitwDrzqSn-X_dyAlLSpDkGgQQgDk6OUUlMC', + 'version': 'bkA7QgnyJtoxOVZ6JF9qXTD-ddmw5xXBnlamEm6kTBkC', }, ], 'condition': 'checkout_android', @@ -2525,7 +2525,7 @@ 'dep_type': 'cipd', }, - 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@23ed8d76c58a57c4f14b0aba6197d5631a844f00', + 'src/third_party/vulkan-deps': '{chromium_git}/vulkan-deps@3564f95cf10c7febe85d145baf229a3f91ef7447', 'src/third_party/glslang/src': '{chromium_git}/external/github.com/KhronosGroup/glslang@df3398078fab37b50ab33192af01cbc5b5d5b377', 'src/third_party/spirv-cross/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3', 'src/third_party/spirv-headers/src': '{chromium_git}/external/github.com/KhronosGroup/SPIRV-Headers@69ab0f32dc6376d74b3f5b0b7161c6681478badd', @@ -2534,7 +2534,7 @@ 'src/third_party/vulkan-loader/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Loader@2761c159b9325baa5980e028ac081963b5d5dd9c', 'src/third_party/vulkan-tools/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Tools@7e82aea5fc1394d417a0df6a5680a4cce5c37286', 'src/third_party/vulkan-utility-libraries/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@7ea05992a52e96426bd4c56ea12d208e0d6c9a5f', - 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@13c0c4dc619d165b05061702a3c8eb604d21efa4', + 'src/third_party/vulkan-validation-layers/src': '{chromium_git}/external/github.com/KhronosGroup/Vulkan-ValidationLayers@b87d71c2177c08e5ad43c15d1fb8b3f60926c023', 'src/third_party/vulkan_memory_allocator': Var('chromium_git') + '/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git' + '@' + '56300b29fbfcc693ee6609ddad3fdd5b7a449a21', @@ -2714,7 +2714,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/help_app/app', - 'version': 'v4MyjUT4F_l7AMdzWSBqe8H-0WC4x0yfECZDr3YHkdcC', + 'version': 'q8zh4MNPVYZZy-EgnEej-CcqU5dQQSUZpSvymP78TJoC', }, ], 'condition': 'checkout_chromeos and checkout_src_internal', @@ -4608,7 +4608,7 @@ 'src/components/accessibility/internal': { 'url': Var('chrome_git') + '/chrome-accessibility.git' + '@' + - 'ecd750e333640c29bc0228ea55a9234693e327c6', + '2e6c405fd5f09ad9d8933bc531af8c5dd24f348c', 'condition': 'checkout_src_internal', }, @@ -4625,7 +4625,7 @@ 'src/components/metrics/internal': { 'url': Var('chrome_git') + '/chrome/components/metrics/internal.git' + '@' + - 'ac1f976e1ef64a9b1df0e2a3ef0256d6f53bd5aa', + 'ff75f0920247434231b3f71eb150713e2d3752b5', 'condition': 'checkout_src_internal', }, @@ -4637,7 +4637,7 @@ 'src/components/optimization_guide/internal': { 'url': Var('chrome_git') + '/chrome/components/optimization_guide.git' + '@' + - '124a90e02063af1f40473e2213f0104c09c41e0f', + '66733820b7ce999c31e929765140f207792127ff', 'condition': 'checkout_src_internal', }, @@ -4697,7 +4697,7 @@ 'src/ios_internal': { 'url': Var('chrome_git') + '/chrome/ios_internal.git' + '@' + - '546afc212797e507ffad9bcecbc38e381f50e7aa', + 'e1fa9c580e9ae769577b551d19ad93035aaa6a79', 'condition': 'checkout_ios and checkout_src_internal', },
diff --git a/android_webview/browser/aw_form_database_service.cc b/android_webview/browser/aw_form_database_service.cc index de916ef6..8fb6effa 100644 --- a/android_webview/browser/aw_form_database_service.cc +++ b/android_webview/browser/aw_form_database_service.cc
@@ -38,12 +38,11 @@ has_form_data_completion_( base::WaitableEvent::ResetPolicy::AUTOMATIC, base::WaitableEvent::InitialState::NOT_SIGNALED) { - auto db_task_runner = base::ThreadPool::CreateSequencedTaskRunner( - {base::MayBlock(), base::TaskPriority::USER_VISIBLE, - base::TaskShutdownBehavior::BLOCK_SHUTDOWN}); - web_database_ = new WebDatabaseService(path.Append(kWebDataFilename), - content::GetUIThreadTaskRunner({}), - db_task_runner); + web_database_ = new WebDatabaseService( + path.Append(kWebDataFilename), content::GetUIThreadTaskRunner({}), + base::ThreadPool::CreateSequencedTaskRunner( + {base::MayBlock(), base::TaskPriority::USER_VISIBLE, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN})); web_database_->AddTable(std::make_unique<autofill::AutocompleteTable>()); // WebView shouldn't depend on non-Autocomplete tables. However, // `AwFormDatabaseService::ClearFormData()` also clear Autofill-related data. @@ -54,7 +53,7 @@ web_database_->LoadDatabase(); autofill_data_ = new autofill::AutofillWebDataService( - web_database_, content::GetUIThreadTaskRunner({}), db_task_runner); + web_database_, content::GetUIThreadTaskRunner({})); autofill_data_->Init(base::BindOnce(&DatabaseErrorCallback)); }
diff --git a/android_webview/browser/ip_protection/aw_ip_protection_config_provider.cc b/android_webview/browser/ip_protection/aw_ip_protection_config_provider.cc index 6b58d0a..712054e9 100644 --- a/android_webview/browser/ip_protection/aw_ip_protection_config_provider.cc +++ b/android_webview/browser/ip_protection/aw_ip_protection_config_provider.cc
@@ -28,7 +28,9 @@ #include "base/threading/sequence_bound.h" #include "components/ip_protection/android/ip_protection_token_ipc_fetcher.h" #include "components/ip_protection/common/ip_protection_config_provider_helper.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "components/ip_protection/common/ip_protection_proxy_config_fetcher.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "components/version_info/android/channel_getter.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/storage_partition.h" @@ -47,6 +49,8 @@ namespace android_webview { +using ::ip_protection::TryGetAuthTokensAndroidResult; + AwIpProtectionConfigProvider::AwIpProtectionConfigProvider( AwBrowserContext* aw_browser_context) : aw_browser_context_(aw_browser_context), @@ -127,7 +131,7 @@ if (!IsIpProtectionEnabled()) { TryGetAuthTokensComplete( /*bsa_tokens=*/std::nullopt, std::move(callback), - AwIpProtectionTryGetAuthTokensResult::kFailedDisabled); + TryGetAuthTokensAndroidResult::kFailedDisabled); return; } @@ -164,16 +168,16 @@ return; } if (!tokens.ok()) { - AwIpProtectionTryGetAuthTokensResult result; + TryGetAuthTokensAndroidResult result; switch (tokens.status().code()) { case absl::StatusCode::kUnavailable: - result = AwIpProtectionTryGetAuthTokensResult::kFailedBSATransient; + result = TryGetAuthTokensAndroidResult::kFailedBSATransient; break; case absl::StatusCode::kFailedPrecondition: - result = AwIpProtectionTryGetAuthTokensResult::kFailedBSAPersistent; + result = TryGetAuthTokensAndroidResult::kFailedBSAPersistent; break; default: - result = AwIpProtectionTryGetAuthTokensResult::kFailedBSAOther; + result = TryGetAuthTokensAndroidResult::kFailedBSAOther; break; } VLOG(2) << "AwIpProtectionConfigProvider::OnFetchBlindSignedTokenCompleted " @@ -189,13 +193,13 @@ "OnFetchBlindSignedTokenCompleted called with no tokens"; TryGetAuthTokensComplete( /*bsa_tokens=*/std::nullopt, std::move(callback), - AwIpProtectionTryGetAuthTokensResult::kFailedBSAOther); + TryGetAuthTokensAndroidResult::kFailedBSAOther); return; } - std::vector<network::BlindSignedAuthToken> bsa_tokens; + std::vector<ip_protection::BlindSignedAuthToken> bsa_tokens; for (const quiche::BlindSignToken& token : tokens.value()) { - std::optional<network::BlindSignedAuthToken> converted_token = + std::optional<ip_protection::BlindSignedAuthToken> converted_token = ip_protection::IpProtectionConfigProviderHelper:: CreateBlindSignedAuthToken(token); if (!converted_token.has_value() || converted_token->token.empty()) { @@ -205,7 +209,7 @@ "`network::mojom::BlindSignedAuthToken`"; TryGetAuthTokensComplete( /*bsa_tokens=*/std::nullopt, std::move(callback), - AwIpProtectionTryGetAuthTokensResult::kFailedBSAOther); + TryGetAuthTokensAndroidResult::kFailedBSAOther); return; } else { bsa_tokens.push_back(std::move(converted_token).value()); @@ -213,23 +217,21 @@ } const base::TimeTicks current_time = base::TimeTicks::Now(); - base::UmaHistogramTimes("NetworkService.AwIpProtection.TokenBatchRequestTime", - current_time - bsa_get_tokens_start_time); - TryGetAuthTokensComplete(std::move(bsa_tokens), std::move(callback), - AwIpProtectionTryGetAuthTokensResult::kSuccess); + TryGetAuthTokensAndroidResult::kSuccess, + current_time - bsa_get_tokens_start_time); } void AwIpProtectionConfigProvider::TryGetAuthTokensComplete( - std::optional<std::vector<network::BlindSignedAuthToken>> bsa_tokens, + std::optional<std::vector<ip_protection::BlindSignedAuthToken>> bsa_tokens, TryGetAuthTokensCallback callback, - AwIpProtectionTryGetAuthTokensResult result) { - if (result == AwIpProtectionTryGetAuthTokensResult::kSuccess) { + ip_protection::TryGetAuthTokensAndroidResult result, + std::optional<base::TimeDelta> duration) { + if (result == TryGetAuthTokensAndroidResult::kSuccess) { CHECK(bsa_tokens.has_value() && !bsa_tokens->empty()); } - base::UmaHistogramEnumeration( - "NetworkService.AwIpProtection.TryGetAuthTokensResult", result); + ip_protection::Telemetry().AndroidTokenBatchFetchComplete(result, duration); std::optional<base::TimeDelta> backoff = CalculateBackoff(result); std::optional<base::Time> try_again_after; @@ -245,17 +247,17 @@ } std::optional<base::TimeDelta> AwIpProtectionConfigProvider::CalculateBackoff( - AwIpProtectionTryGetAuthTokensResult result) { + TryGetAuthTokensAndroidResult result) { std::optional<base::TimeDelta> backoff; switch (result) { - case AwIpProtectionTryGetAuthTokensResult::kSuccess: + case TryGetAuthTokensAndroidResult::kSuccess: break; - case AwIpProtectionTryGetAuthTokensResult::kFailedBSAPersistent: - case AwIpProtectionTryGetAuthTokensResult::kFailedDisabled: + case TryGetAuthTokensAndroidResult::kFailedBSAPersistent: + case TryGetAuthTokensAndroidResult::kFailedDisabled: backoff = base::TimeDelta::Max(); break; - case AwIpProtectionTryGetAuthTokensResult::kFailedBSATransient: - case AwIpProtectionTryGetAuthTokensResult::kFailedBSAOther: + case TryGetAuthTokensAndroidResult::kFailedBSATransient: + case TryGetAuthTokensAndroidResult::kFailedBSAOther: backoff = ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff; // Note that we calculate the backoff assuming that we've waited for
diff --git a/android_webview/browser/ip_protection/aw_ip_protection_config_provider.h b/android_webview/browser/ip_protection/aw_ip_protection_config_provider.h index d57bf4b6..1214117 100644 --- a/android_webview/browser/ip_protection/aw_ip_protection_config_provider.h +++ b/android_webview/browser/ip_protection/aw_ip_protection_config_provider.h
@@ -20,8 +20,10 @@ #include "base/time/time.h" #include "components/ip_protection/android/ip_protection_token_ipc_fetcher.h" #include "components/ip_protection/common/ip_protection_config_provider_helper.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "components/ip_protection/common/ip_protection_proxy_config_fetcher.h" #include "components/ip_protection/common/ip_protection_proxy_config_retriever.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "components/keyed_service/core/keyed_service.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" @@ -39,28 +41,6 @@ namespace android_webview { -// The result of a fetch of tokens from the IP Protection auth token server. -// -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. Keep this in sync with -// AwIpProtectionTokenBatchRequestResult in enums.xml. -enum class AwIpProtectionTryGetAuthTokensResult { - // The request was successful and resulted in new tokens. - kSuccess = 0, - // A transient error, implies that retrying the action (with backoff) is - // appropriate. - kFailedBSATransient = 1, - // A persistent error, implies that the action should not be retried. - kFailedBSAPersistent = 2, - // Any other issue calling BSA. - kFailedBSAOther = 3, - // The attempt to request tokens failed because IP Protection is disabled by - // WebView. - kFailedDisabled = 4, - - kMaxValue = kFailedDisabled, -}; - // Fetches IP protection tokens and proxy list on demand for the network // service. @@ -140,14 +120,16 @@ // Finish a call to `TryGetAuthTokens()` by recording the result and invoking // its callback. void TryGetAuthTokensComplete( - std::optional<std::vector<network::BlindSignedAuthToken>> bsa_tokens, + std::optional<std::vector<ip_protection::BlindSignedAuthToken>> + bsa_tokens, TryGetAuthTokensCallback callback, - AwIpProtectionTryGetAuthTokensResult result); + ip_protection::TryGetAuthTokensAndroidResult result, + std::optional<base::TimeDelta> duration = std::nullopt); // Calculates the backoff time for the given result, based on // `last_try_get_auth_tokens_..` fields, and updates those fields. std::optional<base::TimeDelta> CalculateBackoff( - AwIpProtectionTryGetAuthTokensResult result); + ip_protection::TryGetAuthTokensAndroidResult result); // Injected browser context. raw_ptr<AwBrowserContext> aw_browser_context_; @@ -174,8 +156,9 @@ // backoff applied to `try_again_after`. `last_try_get_auth_tokens_backoff_` // will be set to `base::TimeDelta::Max()` if no further attempts to get // tokens should be made. These will be updated by calls from any receiver. - AwIpProtectionTryGetAuthTokensResult last_try_get_auth_tokens_result_ = - AwIpProtectionTryGetAuthTokensResult::kSuccess; + ip_protection::TryGetAuthTokensAndroidResult + last_try_get_auth_tokens_result_ = + ip_protection::TryGetAuthTokensAndroidResult::kSuccess; std::optional<base::TimeDelta> last_try_get_auth_tokens_backoff_; // The `mojo::Receiver` objects allowing the network service to call methods
diff --git a/android_webview/browser/ip_protection/aw_ip_protection_config_provider_unittest.cc b/android_webview/browser/ip_protection/aw_ip_protection_config_provider_unittest.cc index 07b33182..2fb711c 100644 --- a/android_webview/browser/ip_protection/aw_ip_protection_config_provider_unittest.cc +++ b/android_webview/browser/ip_protection/aw_ip_protection_config_provider_unittest.cc
@@ -17,6 +17,7 @@ #include "base/types/expected.h" #include "components/ip_protection/android/blind_sign_message_android_impl.h" #include "components/ip_protection/common/ip_protection_config_provider_helper.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "components/ip_protection/common/ip_protection_proxy_config_fetcher.h" #include "components/ip_protection/common/mock_blind_sign_auth.h" #include "content/public/browser/browser_thread.h" @@ -93,7 +94,7 @@ // Expect that the TryGetAuthTokens call returned the given tokens. void ExpectTryGetAuthTokensResult( - std::vector<network::BlindSignedAuthToken> bsa_tokens) { + std::vector<ip_protection::BlindSignedAuthToken> bsa_tokens) { EXPECT_EQ(std::get<0>(tokens_future_.Get()), bsa_tokens); // Clear future so it can be reused and accept new tokens. tokens_future_.Clear(); @@ -113,20 +114,20 @@ content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; base::test::TestFuture< - const std::optional<std::vector<network::BlindSignedAuthToken>>&, + const std::optional<std::vector<ip_protection::BlindSignedAuthToken>>&, std::optional<base::Time>> tokens_future_; protected: base::test::TestFuture<const std::optional<std::vector<net::ProxyChain>>&, - const std::optional<network::GeoHint>&> + const std::optional<ip_protection::GeoHint>&> proxy_list_future_; // A convenient expiration time for fake tokens, in the future. base::Time expiration_time_; // A convenient geo hint for fake tokens. - network::GeoHint geo_hint_; + ip_protection::GeoHint geo_hint_; base::HistogramTester histogram_tester_; @@ -158,7 +159,7 @@ EXPECT_EQ(bsa_->num_tokens(), 2); EXPECT_EQ(bsa_->proxy_layer(), quiche::ProxyLayer::kProxyB); - std::vector<network::BlindSignedAuthToken> expected; + std::vector<ip_protection::BlindSignedAuthToken> expected; expected.push_back(ip_protection::IpProtectionConfigProviderHelper:: CreateMockBlindSignedAuthTokenForTesting( "single-use-1", expiration_time_, geo_hint_) @@ -171,7 +172,7 @@ ExpectTryGetAuthTokensResult(std::move(expected)); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - AwIpProtectionTryGetAuthTokensResult::kSuccess, 1); + ip_protection::TryGetAuthTokensAndroidResult::kSuccess, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 1); } @@ -190,7 +191,7 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - AwIpProtectionTryGetAuthTokensResult::kFailedBSAOther, 1); + ip_protection::TryGetAuthTokensAndroidResult::kFailedBSAOther, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -219,7 +220,7 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - AwIpProtectionTryGetAuthTokensResult::kFailedBSAOther, 1); + ip_protection::TryGetAuthTokensAndroidResult::kFailedBSAOther, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -227,7 +228,7 @@ TEST_F(AwIpProtectionConfigProviderTest, TokenGeoHintContainsOnlyCountry) { scoped_feature_list_.InitAndEnableFeature( net::features::kEnableIpProtectionProxy); - network::GeoHint geo_hint_country; + ip_protection::GeoHint geo_hint_country; geo_hint_country.country_code = "US"; bsa_->set_tokens( {ip_protection::IpProtectionConfigProviderHelper:: @@ -244,7 +245,7 @@ EXPECT_EQ(bsa_->num_tokens(), 2); EXPECT_EQ(bsa_->proxy_layer(), quiche::ProxyLayer::kProxyB); - std::vector<network::BlindSignedAuthToken> expected; + std::vector<ip_protection::BlindSignedAuthToken> expected; expected.push_back(ip_protection::IpProtectionConfigProviderHelper:: CreateMockBlindSignedAuthTokenForTesting( "single-use-1", expiration_time_, geo_hint_country) @@ -257,7 +258,7 @@ ExpectTryGetAuthTokensResult(std::move(expected)); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - AwIpProtectionTryGetAuthTokensResult::kSuccess, 1); + ip_protection::TryGetAuthTokensAndroidResult::kSuccess, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 1); } @@ -265,7 +266,7 @@ TEST_F(AwIpProtectionConfigProviderTest, TokenHasMissingGeoHint) { scoped_feature_list_.InitAndEnableFeature( net::features::kEnableIpProtectionProxy); - network::GeoHint geo_hint; + ip_protection::GeoHint geo_hint; bsa_->set_tokens({ip_protection::IpProtectionConfigProviderHelper:: CreateBlindSignTokenForTesting( "single-use-1", expiration_time_, geo_hint)}); @@ -280,7 +281,7 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - AwIpProtectionTryGetAuthTokensResult::kFailedBSAOther, 1); + ip_protection::TryGetAuthTokensAndroidResult::kFailedBSAOther, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -301,7 +302,7 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - AwIpProtectionTryGetAuthTokensResult::kFailedBSATransient, 1); + ip_protection::TryGetAuthTokensAndroidResult::kFailedBSATransient, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -321,7 +322,7 @@ ExpectTryGetAuthTokensResultFailed(base::TimeDelta::Max()); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - AwIpProtectionTryGetAuthTokensResult::kFailedBSAPersistent, 1); + ip_protection::TryGetAuthTokensAndroidResult::kFailedBSAPersistent, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -342,7 +343,7 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - AwIpProtectionTryGetAuthTokensResult::kFailedBSAOther, 1); + ip_protection::TryGetAuthTokensAndroidResult::kFailedBSAOther, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -359,7 +360,6 @@ histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } - TEST_F(AwIpProtectionConfigProviderTest, ProxyOverrideFlagsAll) { std::vector<net::ProxyChain> proxy_override_list = { ip_protection::IpProtectionProxyConfigFetcher::MakeChainForTesting( @@ -451,5 +451,4 @@ EXPECT_FALSE(geo_hint.has_value()); } - } // namespace android_webview
diff --git a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java index 7a413fd..13a5cbc 100644 --- a/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java +++ b/android_webview/java/src/org/chromium/android_webview/common/ProductionSupportedFlagList.java
@@ -773,6 +773,7 @@ Flag.baseFeature("V8SingleThreadedGCInBackgroundNoIncrementalMarking"), Flag.baseFeature("V8SingleThreadedGCInBackgroundParallelPause"), Flag.baseFeature("V8UpdateLimitAfterLoading"), + Flag.baseFeature("V8IncrementalMarkingStartUserVisible"), Flag.baseFeature("WebAssemblyMoreAggressiveCodeCaching"), Flag.baseFeature("WebAssemblyTurboshaft"), Flag.baseFeature("WebAssemblyTurboshaftInstructionSelection"), @@ -1003,6 +1004,7 @@ ContentFeatures.DEFER_SPECULATIVE_RFH_CREATION, "Enables deferring the speculative render frame host creation when the" + "navigation starts"), + Flag.baseFeature(ContentFeatures.PWA_NAVIGATION_CAPTURING), Flag.baseFeature("TransportSecurityFileWriterSchedule"), Flag.commandLine( AwSwitches.WEBVIEW_INTERCEPTED_COOKIE_HEADER,
diff --git a/ash/auth/active_session_auth_metrics_recorder.cc b/ash/auth/active_session_auth_metrics_recorder.cc index 02153da..c0be720f 100644 --- a/ash/auth/active_session_auth_metrics_recorder.cc +++ b/ash/auth/active_session_auth_metrics_recorder.cc
@@ -36,6 +36,8 @@ "Ash.Auth.ActiveSessionAuthPinAttempt"; constexpr char kNumberOfPasswordAttemptHistogram[] = "Ash.Auth.ActiveSessionAuthPasswordAttempt"; +constexpr char kNumberOfFingerprintAttemptHistogram[] = + "Ash.Auth.ActiveSessionAuthFingerprintAttempt"; // The ceiling to use when clamping the number of PIN attempts that can be // recorded for UMA collection. @@ -44,6 +46,11 @@ // The ceiling to use when clamping the number of Password attempts that can be // recorded for UMA collection. constexpr int kMaxRecordedPasswordAttempts = 20; + +// The ceiling to use when clamping the number of Fingerprint attempts that can +// be recorded for UMA collection. +constexpr int kMaxRecordedFingerprintAttempts = 20; + } // namespace ActiveSessionAuthMetricsRecorder::ActiveSessionAuthMetricsRecorder() = default; @@ -85,10 +92,16 @@ password_attempt_counter_, kMaxRecordedPasswordAttempts); + // Record to metric the number of fingerprint attempts. + base::UmaHistogramExactLinear(kNumberOfFingerprintAttemptHistogram, + fingerprint_attempt_counter_, + kMaxRecordedFingerprintAttempts); + // Reset the state. auth_succeeded_ = false; pin_attempt_counter_ = 0; password_attempt_counter_ = 0; + fingerprint_attempt_counter_ = 0; started_auth_type_.reset(); open_reason_.reset(); open_timer_.reset(); @@ -104,6 +117,16 @@ case AuthInputType::kPin: ++pin_attempt_counter_; break; + case AuthInputType::kFingerprint: + // Fingerprint authentication begins when the authentication dialog is + // shown and the user has fingerprint record(s) and the policy doesn't + // prevent its use. The fingerprint session remains active until + // explicitly terminated, so even after a failed scan attempt, there's no + // need to restart it. This session runs concurrently with password/PIN + // authentication attempts. Therefore, we are not tracking "Authentication + // Started" events for fingerprint specifically, but rather focusing on + // the count of successful and failed attempts. + NOTREACHED(); default: NOTREACHED(); } @@ -115,19 +138,31 @@ void ActiveSessionAuthMetricsRecorder::RecordAuthFailed( AuthInputType input_type) { - CHECK(started_auth_type_.has_value()); - CHECK_EQ(started_auth_type_.value(), input_type); + // Fingerprint authentication can occur concurrently with other + // AuthInputType's. + if (input_type == AuthInputType::kFingerprint) { + ++fingerprint_attempt_counter_; + } else { + CHECK(started_auth_type_.has_value()); + CHECK_EQ(started_auth_type_.value(), input_type); + + started_auth_type_.reset(); + } // Record to metric the failed authentication type. base::UmaHistogramEnumeration(kAuthFailedHistogram, input_type); - - started_auth_type_.reset(); } void ActiveSessionAuthMetricsRecorder::RecordAuthSucceeded( AuthInputType input_type) { - CHECK(started_auth_type_.has_value()); - CHECK_EQ(started_auth_type_.value(), input_type); + // Fingerprint authentication can occur concurrently with other + // AuthInputType's. + if (input_type == AuthInputType::kFingerprint) { + ++fingerprint_attempt_counter_; + } else { + CHECK(started_auth_type_.has_value()); + CHECK_EQ(started_auth_type_.value(), input_type); + } // Record to metric the succeeded authentication type. base::UmaHistogramEnumeration(kAuthSucceededHistogram, input_type);
diff --git a/ash/auth/active_session_auth_metrics_recorder.h b/ash/auth/active_session_auth_metrics_recorder.h index 702dbe6..61232ec7b 100644 --- a/ash/auth/active_session_auth_metrics_recorder.h +++ b/ash/auth/active_session_auth_metrics_recorder.h
@@ -41,6 +41,7 @@ int pin_attempt_counter_ = 0; int password_attempt_counter_ = 0; + int fingerprint_attempt_counter_ = 0; bool auth_succeeded_ = false; };
diff --git a/ash/auth/test/active_session_auth_metrics_recorder_unittest.cc b/ash/auth/test/active_session_auth_metrics_recorder_unittest.cc index 448a616..ee70a16b 100644 --- a/ash/auth/test/active_session_auth_metrics_recorder_unittest.cc +++ b/ash/auth/test/active_session_auth_metrics_recorder_unittest.cc
@@ -30,6 +30,8 @@ "Ash.Auth.ActiveSessionAuthPinAttempt"; constexpr char kNumberOfPasswordAttemptHistogram[] = "Ash.Auth.ActiveSessionAuthPasswordAttempt"; +constexpr char kNumberOfFingerprintAttemptHistogram[] = + "Ash.Auth.ActiveSessionAuthFingerprintAttempt"; class ActiveSessionAuthMetricsRecorderTest : public AshTestBase { public: @@ -230,4 +232,36 @@ histogram_tester_->ExpectBucketCount(kNumberOfPinAttemptHistogram, 2, 1); } +// Verifies that histogram records the fingerprint authentication attempt +// counter. +TEST_F(ActiveSessionAuthMetricsRecorderTest, + ActiveSessionAuthFingerprintAttemptTest) { + metrics_recorder_.RecordShow(AuthRequest::Reason::kPasswordManager); + + metrics_recorder_.RecordAuthFailed(AuthInputType::kFingerprint); + + metrics_recorder_.RecordAuthSucceeded(AuthInputType::kFingerprint); + metrics_recorder_.RecordClose(); + histogram_tester_->ExpectBucketCount(kNumberOfFingerprintAttemptHistogram, 2, + 1); +} + +// Verifies that histogram records the fingerprint and authentication attempt +// counter. +TEST_F(ActiveSessionAuthMetricsRecorderTest, + ActiveSessionAuthFingerprintAndPinAttemptTest) { + metrics_recorder_.RecordShow(AuthRequest::Reason::kPasswordManager); + + metrics_recorder_.RecordAuthFailed(AuthInputType::kFingerprint); + + // Pin auhtentication started but concurrently the fingerprint succeeded + metrics_recorder_.RecordAuthStarted(AuthInputType::kPin); + metrics_recorder_.RecordAuthSucceeded(AuthInputType::kFingerprint); + metrics_recorder_.RecordClose(); + + histogram_tester_->ExpectBucketCount(kNumberOfPinAttemptHistogram, 1, 1); + histogram_tester_->ExpectBucketCount(kNumberOfFingerprintAttemptHistogram, 2, + 1); +} + } // namespace ash
diff --git a/ash/auth/views/auth_common.h b/ash/auth/views/auth_common.h index f3a4de5..a613aec2 100644 --- a/ash/auth/views/auth_common.h +++ b/ash/auth/views/auth_common.h
@@ -14,10 +14,15 @@ // The enums below are used in histograms, do not remove/renumber entries. If // you're adding to any of these enums, update the corresponding enum listing in // tools/metrics/histograms/metadata/ash/enums.xml: -enum class AuthInputType { kPassword = 0, kPin = 1, kMaxValue = kPin }; +enum class AuthInputType { + kPassword = 0, + kPin = 1, + kFingerprint = 2, + kMaxValue = kFingerprint +}; -using AuthFactorSet = - base::EnumSet<AuthInputType, AuthInputType::kPassword, AuthInputType::kPin>; +using AuthFactorSet = base:: + EnumSet<AuthInputType, AuthInputType::kPassword, AuthInputType::kMaxValue>; // The text width is the kActiveSessionAuthViewWidthDp - // 2 X 32 dp margin.
diff --git a/ash/auth/views/auth_container_view.cc b/ash/auth/views/auth_container_view.cc index 82b16a9..da0e99a 100644 --- a/ash/auth/views/auth_container_view.cc +++ b/ash/auth/views/auth_container_view.cc
@@ -225,6 +225,9 @@ void AuthContainerView::AddFingerprintView() { CHECK_EQ(fingerprint_view_, nullptr); fingerprint_view_ = AddChildView(std::make_unique<FingerprintView>()); + if (available_auth_factors_.Has(AuthInputType::kFingerprint)) { + SetFingerprintState(FingerprintState::AVAILABLE_DEFAULT); + } } gfx::Size AuthContainerView::CalculatePreferredSize(
diff --git a/ash/style/option_button_base.cc b/ash/style/option_button_base.cc index 2cf22f7..934bbc0 100644 --- a/ash/style/option_button_base.cc +++ b/ash/style/option_button_base.cc
@@ -85,10 +85,6 @@ return gfx::Size(min_width_, kButtonHeight); } -int OptionButtonBase::GetHeightForWidth(int width) const { - return kButtonHeight; -} - void OptionButtonBase::SetLabelColorId(ui::ColorId color_id) { label()->SetEnabledColorId(color_id); }
diff --git a/ash/style/option_button_base.h b/ash/style/option_button_base.h index 5fd72fc..6f67aac 100644 --- a/ash/style/option_button_base.h +++ b/ash/style/option_button_base.h
@@ -68,7 +68,6 @@ gfx::Size CalculatePreferredSize( const views::SizeBounds& available_size) const override; gfx::Size GetMinimumSize() const override; - int GetHeightForWidth(int width) const override; void Layout(PassKey) override; void OnThemeChanged() override; void NotifyClick(const ui::Event& event) override;
diff --git a/ash/style/pill_button.cc b/ash/style/pill_button.cc index c1194be..5e5a47d 100644 --- a/ash/style/pill_button.cc +++ b/ash/style/pill_button.cc
@@ -232,10 +232,6 @@ return size; } -int PillButton::GetHeightForWidth(int width) const { - return GetButtonHeight(type_); -} - gfx::Insets PillButton::GetInsets() const { const int vertical_spacing = (GetButtonHeight(type_) - kIconSize) / 2; const int icon_padding = IsIconPillButton(type_)
diff --git a/ash/style/pill_button.h b/ash/style/pill_button.h index 3bd8d85..6755b652 100644 --- a/ash/style/pill_button.h +++ b/ash/style/pill_button.h
@@ -180,7 +180,6 @@ // views::LabelButton: gfx::Size CalculatePreferredSize( const views::SizeBounds& available_size) const override; - int GetHeightForWidth(int width) const override; gfx::Insets GetInsets() const override; void UpdateBackgroundColor() override; views::PropertyEffects UpdateStyleToIndicateDefaultStatus() override;
diff --git a/ash/style/rounded_label.cc b/ash/style/rounded_label.cc index 1bc9bce..37fa8e4 100644 --- a/ash/style/rounded_label.cc +++ b/ash/style/rounded_label.cc
@@ -46,10 +46,6 @@ preferred_height_); } -int RoundedLabel::GetHeightForWidth(int width) const { - return preferred_height_; -} - void RoundedLabel::OnPaintBorder(gfx::Canvas* canvas) { views::HighlightBorder::PaintBorderToCanvas( canvas, *this, GetLocalBounds(), gfx::RoundedCornersF(rounding_dp_),
diff --git a/ash/style/rounded_label.h b/ash/style/rounded_label.h index 1a61ddb..e67c3d7 100644 --- a/ash/style/rounded_label.h +++ b/ash/style/rounded_label.h
@@ -28,7 +28,6 @@ // views::Label: gfx::Size CalculatePreferredSize( const views::SizeBounds& available_size) const override; - int GetHeightForWidth(int width) const override; void OnPaintBorder(gfx::Canvas* canvas) override; const int rounding_dp_;
diff --git a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc index 09552a04..ee9dd9a 100644 --- a/ash/style/style_viewer/system_ui_components_style_viewer_view.cc +++ b/ash/style/style_viewer/system_ui_components_style_viewer_view.cc
@@ -126,8 +126,6 @@ return gfx::Size(kMenuWidth, kDefaultButtonHeight); } - int GetHeightForWidth(int w) const override { return kDefaultButtonHeight; } - void OnThemeChanged() override { views::LabelButton::OnThemeChanged();
diff --git a/ash/style/tab_slider_button.cc b/ash/style/tab_slider_button.cc index 10eab45..0c049ef 100644 --- a/ash/style/tab_slider_button.cc +++ b/ash/style/tab_slider_button.cc
@@ -201,10 +201,6 @@ UpdateLabelColor(); } -int LabelSliderButton::GetHeightForWidth(int w) const { - return kLabelButtonHeight; -} - gfx::Size LabelSliderButton::CalculatePreferredSize( const views::SizeBounds& available_size) const { gfx::Insets insets = GetInsets();
diff --git a/ash/style/tab_slider_button.h b/ash/style/tab_slider_button.h index f77cecc..881b4250 100644 --- a/ash/style/tab_slider_button.h +++ b/ash/style/tab_slider_button.h
@@ -111,7 +111,6 @@ void OnSelectedChanged() override; // views::Button: - int GetHeightForWidth(int w) const override; gfx::Size CalculatePreferredSize( const views::SizeBounds& available_size) const override; void StateChanged(ButtonState old_state) override;
diff --git a/ash/webui/boca_ui/boca_ui.cc b/ash/webui/boca_ui/boca_ui.cc index 115932d..bcbd7606 100644 --- a/ash/webui/boca_ui/boca_ui.cc +++ b/ash/webui/boca_ui/boca_ui.cc
@@ -15,6 +15,7 @@ #include "ash/webui/common/chrome_os_webui_config.h" #include "ash/webui/grit/ash_boca_ui_resources.h" #include "ash/webui/grit/ash_boca_ui_resources_map.h" +#include "chromeos/ash/components/boca/boca_role_util.h" #include "chromeos/grit/chromeos_boca_app_bundle_resources.h" #include "chromeos/grit/chromeos_boca_app_bundle_resources_map.h" #include "content/public/browser/web_contents.h" @@ -42,6 +43,12 @@ kChromeosBocaAppBundleResources, kChromeosBocaAppBundleResourcesSize)); return source; } + +void PopulateLoadTimeData(content::WebUIDataSource* source) { + source->AddBoolean("isProducer", ash::boca_util::IsProducer()); + source->AddBoolean("isConsumer", ash::boca_util::IsConsumer()); +} + } // namespace BocaUI::BocaUI(content::WebUI* web_ui) @@ -85,6 +92,7 @@ ContentSettingsType::JAVASCRIPT, ContentSettingsType::SOUND, }); + PopulateLoadTimeData(host_source); #if !DCHECK_IS_ON() // If a user goes to an invalid url and non-DCHECK mode (DHECK = debug mode)
diff --git a/ash/webui/common/resources/sea_pen/load_time_booleans.ts b/ash/webui/common/resources/sea_pen/load_time_booleans.ts index 52dd1e1..43c9785a 100644 --- a/ash/webui/common/resources/sea_pen/load_time_booleans.ts +++ b/ash/webui/common/resources/sea_pen/load_time_booleans.ts
@@ -22,10 +22,6 @@ return loadTimeData.getBoolean('isSeaPenUseExptTemplateEnabled'); } -export function isSeaPenEnterpriseEnabled() { - return loadTimeData.getBoolean('isSeaPenEnterpriseEnabled'); -} - export function isLacrosEnabled() { return loadTimeData.getBoolean('isLacrosEnabled'); }
diff --git a/ash/webui/personalization_app/personalization_app_ui.cc b/ash/webui/personalization_app/personalization_app_ui.cc index 73abe2dd..f96d47de 100644 --- a/ash/webui/personalization_app/personalization_app_ui.cc +++ b/ash/webui/personalization_app/personalization_app_ui.cc
@@ -561,9 +561,6 @@ source->AddBoolean("isSeaPenUseExptTemplateEnabled", common_sea_pen_requirements && ::ash::features::IsSeaPenUseExptTemplateEnabled()); - source->AddBoolean("isSeaPenEnterpriseEnabled", - common_sea_pen_requirements && - ::ash::features::IsSeaPenEnterpriseEnabled()); source->AddBoolean("isManagedSeaPenEnabled", sea_pen_provider_->IsManagedSeaPenEnabled()); source->AddBoolean("isManagedSeaPenFeedbackEnabled",
diff --git a/ash/webui/personalization_app/resources/js/personalization_test_api.ts b/ash/webui/personalization_app/resources/js/personalization_test_api.ts index 3dbeacc..ad1e389 100644 --- a/ash/webui/personalization_app/resources/js/personalization_test_api.ts +++ b/ash/webui/personalization_app/resources/js/personalization_test_api.ts
@@ -27,17 +27,26 @@ // Reset to a default state at the root of the app. Useful for browsertests. async function reset() { + await selectDefaultWallpaperImage(); + goToRootPath(); +} + +function goToRootPath() { + const router = PersonalizationRouterElement.instance(); + router.goToRoute(Paths.ROOT); +} + +async function selectDefaultWallpaperImage() { const wallpaperProvider = getWallpaperProvider(); await wallpaperProvider.selectDefaultImage(); +} +async function setDefaultColorScheme() { // Turn on dynamic color with default scheme. const themeProvider = getThemeProvider(); themeProvider.setColorScheme(DEFAULT_COLOR_SCHEME); const {colorScheme} = await themeProvider.getColorScheme(); assert(colorScheme === DEFAULT_COLOR_SCHEME, 'reset to default color scheme'); - - const router = PersonalizationRouterElement.instance(); - router.goToRoute(Paths.ROOT); } async function selectTimeOfDayWallpaper() { @@ -73,23 +82,29 @@ declare global { interface Window { personalizationTestApi: { + disableDailyRefresh: () => Promise<void>, + enableDailyGooglePhotosRefresh: (albumId: string) => Promise<void>, + enableDailyRefresh: (collectionId: string) => Promise<void>, + goToRootPath: () => void, isGooglePhotosIntegrationEnabled: () => boolean, makeTransparent: () => void, reset: () => Promise<void>, + selectDefaultWallpaperImage: () => Promise<void>, selectTimeOfDayWallpaper: () => Promise<void>, - enableDailyRefresh: (collectionId: string) => Promise<void>, - disableDailyRefresh: () => Promise<void>, - enableDailyGooglePhotosRefresh: (albumId: string) => Promise<void>, + setDefaultColorScheme: () => Promise<void>, }; } } window.personalizationTestApi = { + disableDailyRefresh, + enableDailyGooglePhotosRefresh, + enableDailyRefresh, + goToRootPath, isGooglePhotosIntegrationEnabled, makeTransparent, reset, + selectDefaultWallpaperImage, selectTimeOfDayWallpaper, - enableDailyRefresh, - disableDailyRefresh, - enableDailyGooglePhotosRefresh, + setDefaultColorScheme, };
diff --git a/ash/webui/vc_background_ui/vc_background_ui.cc b/ash/webui/vc_background_ui/vc_background_ui.cc index e5c5f1c..d138716 100644 --- a/ash/webui/vc_background_ui/vc_background_ui.cc +++ b/ash/webui/vc_background_ui/vc_background_ui.cc
@@ -132,9 +132,6 @@ source->AddBoolean("isSeaPenUseExptTemplateEnabled", common_sea_pen_requirements && ::ash::features::IsSeaPenUseExptTemplateEnabled()); - source->AddBoolean("isSeaPenEnterpriseEnabled", - common_sea_pen_requirements && - ::ash::features::IsSeaPenEnterpriseEnabled()); source->AddBoolean("isManagedSeaPenEnabled", sea_pen_provider_->IsManagedSeaPenEnabled()); source->AddBoolean("isManagedSeaPenFeedbackEnabled",
diff --git a/base/apple/foundation_util.h b/base/apple/foundation_util.h index f7e7173..ab7a76e 100644 --- a/base/apple/foundation_util.h +++ b/base/apple/foundation_util.h
@@ -14,6 +14,8 @@ #include "base/apple/scoped_cftyperef.h" #include "base/base_export.h" +#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/logging.h" #include "build/build_config.h" @@ -297,8 +299,38 @@ // could not be converted to NSUIntegers. [[nodiscard]] BASE_EXPORT bool CFRangeToNSRange(CFRange range, NSRange* range_out); + +// Returns an immutable `base::span<const uint8_t>` pointing to the memory +// owned by `data`. `data` must outlive the returned span. +// Returns an empty span if `data` is nil or empty. +inline span<const uint8_t> NSDataToSpan(NSData* data) { + // SAFETY: `NSData` guarantees that `bytes` is exactly `length` in size. + return UNSAFE_BUFFERS( + make_span(static_cast<const uint8_t*>(data.bytes), data.length)); +} + +// Returns a mutable `base::span<uint8_t>` pointing to the memory +// owned by `data`. `data` must outlive the returned span. +// Returns an empty span if `data` is nil or empty. +inline span<uint8_t> NSMutableDataToSpan(NSMutableData* data) { + // SAFETY: `NSMutableData` guarantees that `mutableBytes` is exactly `length` + // in size. + return UNSAFE_BUFFERS( + make_span(static_cast<uint8_t*>(data.mutableBytes), data.length)); +} + #endif // defined(__OBJC__) +// Returns an immutable `base::span<const uint8_t>` pointing to the memory +// owned by `data`. `data` must outlive the returned span. +// Returns an empty span if `data` is null or empty. +BASE_EXPORT span<const uint8_t> CFDataToSpan(CFDataRef data); + +// Returns a mutable `base::span<uint8_t>` pointing to the memory +// owned by `data`. `data` must outlive the returned span. +// Returns an empty span if `data` is null or empty. +BASE_EXPORT span<uint8_t> CFMutableDataToSpan(CFMutableDataRef data); + } // namespace base::apple // Stream operations for CFTypes. They can be used with Objective-C types as
diff --git a/base/apple/foundation_util.mm b/base/apple/foundation_util.mm index b0c6a4cb..0ef597b3 100644 --- a/base/apple/foundation_util.mm +++ b/base/apple/foundation_util.mm
@@ -452,6 +452,14 @@ return false; } +span<const uint8_t> CFDataToSpan(CFDataRef data) { + return NSDataToSpan(apple::CFToNSPtrCast(data)); +} + +span<uint8_t> CFMutableDataToSpan(CFMutableDataRef data) { + return NSMutableDataToSpan(apple::CFToNSPtrCast(data)); +} + } // namespace base::apple std::ostream& operator<<(std::ostream& o, const CFStringRef string) {
diff --git a/base/apple/foundation_util_unittest.mm b/base/apple/foundation_util_unittest.mm index 6edc2de..73d0eb3 100644 --- a/base/apple/foundation_util_unittest.mm +++ b/base/apple/foundation_util_unittest.mm
@@ -14,9 +14,12 @@ #include "base/format_macros.h" #include "base/strings/stringprintf.h" #include "build/build_config.h" +#include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #import "testing/gtest_mac.h" +using testing::ElementsAreArray; + namespace base::apple { TEST(FoundationUtilTest, CFCast) { @@ -469,6 +472,71 @@ } } +TEST(FoundationUtilTest, NSDataToSpan) { + { + NS_VALID_UNTIL_END_OF_SCOPE NSData* data = [NSData data]; + span<const uint8_t> span = NSDataToSpan(data); + EXPECT_TRUE(span.empty()); + } + + { + NS_VALID_UNTIL_END_OF_SCOPE NSMutableData* data = [NSMutableData data]; + span<uint8_t> span = NSMutableDataToSpan(data); + EXPECT_TRUE(span.empty()); + } + + const char buffer[4] = {0, CHAR_MAX, 0, CHAR_MAX}; + + { + NS_VALID_UNTIL_END_OF_SCOPE NSData* data = + [NSData dataWithBytes:buffer length:sizeof(buffer)]; + span<const uint8_t> span = NSDataToSpan(data); + EXPECT_THAT(span, ElementsAreArray(buffer)); + } + + { + NS_VALID_UNTIL_END_OF_SCOPE NSMutableData* data = + [NSMutableData dataWithBytes:buffer length:sizeof(buffer)]; + span<uint8_t> span = NSMutableDataToSpan(data); + EXPECT_THAT(span, ElementsAreArray(buffer)); + span[0] = 123; + EXPECT_EQ(static_cast<const char*>(data.bytes)[0], 123); + } +} + +TEST(FoundationUtilTest, CFDataToSpan) { + { + ScopedCFTypeRef<CFDataRef> data(CFDataCreate(nullptr, nullptr, 0)); + span<const uint8_t> span = CFDataToSpan(data.get()); + EXPECT_TRUE(span.empty()); + } + + { + ScopedCFTypeRef<CFMutableDataRef> data(CFDataCreateMutable(nullptr, 0)); + span<uint8_t> span = CFMutableDataToSpan(data.get()); + EXPECT_TRUE(span.empty()); + } + + const uint8_t buffer[4] = {0, CHAR_MAX, 0, CHAR_MAX}; + + { + ScopedCFTypeRef<CFDataRef> data( + CFDataCreate(nullptr, buffer, sizeof(buffer))); + span<const uint8_t> span = CFDataToSpan(data.get()); + EXPECT_EQ(make_span(buffer), span); + EXPECT_THAT(span, ElementsAreArray(buffer)); + } + + { + ScopedCFTypeRef<CFMutableDataRef> data(CFDataCreateMutable(nullptr, 0)); + CFDataAppendBytes(data.get(), buffer, sizeof(buffer)); + span<uint8_t> span = CFMutableDataToSpan(data.get()); + EXPECT_EQ(make_span(buffer), span); + span[0] = 123; + EXPECT_EQ(CFDataGetBytePtr(data.get())[0], 123); + } +} + #define EXPECT_LOG_EQ(expected, val) \ EXPECT_EQ(expected, (std::ostringstream() << (val)).str())
diff --git a/base/win/scoped_process_information.cc b/base/win/scoped_process_information.cc index 5bb75236..fae28c9 100644 --- a/base/win/scoped_process_information.cc +++ b/base/win/scoped_process_information.cc
@@ -40,6 +40,12 @@ Set(process_info); } +ScopedProcessInformation::ScopedProcessInformation(ScopedProcessInformation&&) = + default; + +ScopedProcessInformation& ScopedProcessInformation::operator=( + ScopedProcessInformation&&) = default; + ScopedProcessInformation::~ScopedProcessInformation() { Close(); }
diff --git a/base/win/scoped_process_information.h b/base/win/scoped_process_information.h index 8090aec..56501cb 100644 --- a/base/win/scoped_process_information.h +++ b/base/win/scoped_process_information.h
@@ -20,6 +20,9 @@ ScopedProcessInformation(); explicit ScopedProcessInformation(const PROCESS_INFORMATION& process_info); + ScopedProcessInformation(ScopedProcessInformation&&); + ScopedProcessInformation& operator=(ScopedProcessInformation&&); + ScopedProcessInformation(const ScopedProcessInformation&) = delete; ScopedProcessInformation& operator=(const ScopedProcessInformation&) = delete;
diff --git a/build/config/fuchsia/gn_configs.gni b/build/config/fuchsia/gn_configs.gni index 019035de3..ee93666 100644 --- a/build/config/fuchsia/gn_configs.gni +++ b/build/config/fuchsia/gn_configs.gni
@@ -4,11 +4,41 @@ assert(is_fuchsia) +# TODO(crbug.com/359657446): Remove the duplicate arguments in favor of +# using the ones in third_party/fuchsia-gn-sdk/. Some of them are needed +# by repos like webrtc which may not update to use the +# third_party/fuchsia-gn-sdk/src/gn_configs.gni. declare_args() { # Path to the fuchsia SDK. This is intended for use in other templates & # rules to reference the contents of the fuchsia SDK. fuchsia_sdk = "//third_party/fuchsia-sdk/sdk" + # ID uniquely identifying the Fuchsia IDK build. This is exposed as a + # property so it can be used to locate images and packages on GCS and + # as a marker to indicate the "version" of the IDK. + # Defaults to the id found in the manifest.json file of the SDK. + fuchsia_sdk_id = "" +} + +# The SDK manifest file. This is useful to include as a dependency +# for some targets in order to cause a rebuild when the version of the +# SDK is changed. +fuchsia_sdk_manifest_file = "${fuchsia_sdk}/meta/manifest.json" + +# fuchsia_tool_dir is used to specify the directory in the SDK to locate +# tools for the host cpu architecture. If the host_cpu is not recognized, +# then tool dir defaults to x64. +fuchsia_tool_dir = "${fuchsia_sdk}/tools/${host_cpu}" + +if (fuchsia_sdk_id == "") { + # Note: If we need to expose more than just the id in the future, + # we should consider exposing the entire json object for the metadata vs. + # adding a bunch of variables. + _meta = read_file(fuchsia_sdk_manifest_file, "json") + fuchsia_sdk_id = _meta.id +} + +declare_args() { # Specify a readelf_exec path to use. If not specified, the host's system # executable will be used. Passed to populate_build_id_dir.py and # prepare_package_inputs.py via the --readelf-exec flag.
diff --git a/build/config/unsafe_buffers_paths.txt b/build/config/unsafe_buffers_paths.txt index 4de33b1..390242d 100644 --- a/build/config/unsafe_buffers_paths.txt +++ b/build/config/unsafe_buffers_paths.txt
@@ -120,8 +120,6 @@ -printing/ -remoting/host/ -remoting/client/input/ --sandbox/linux/seccomp-bpf-helpers/ --sandbox/win/fuzzer/ -services/accessibility -services/data_decoder -services/shape_detection
diff --git a/cc/input/scrollbar_animation_controller_unittest.cc b/cc/input/scrollbar_animation_controller_unittest.cc index c784ce2..1a6c974 100644 --- a/cc/input/scrollbar_animation_controller_unittest.cc +++ b/cc/input/scrollbar_animation_controller_unittest.cc
@@ -71,6 +71,11 @@ EXPECT_FLOAT_EQ(opacity, h_scrollbar_layer_->Opacity()); } + void UpdateScrollbarGeometriesAndDrawProperties() { + host_impl()->active_tree()->UpdateAllScrollbarGeometriesForTesting(); + UpdateActiveTreeDrawProperties(); + } + protected: const base::TimeDelta kFadeDelay = base::Seconds(4); const base::TimeDelta kFadeDuration = base::Seconds(3); @@ -114,7 +119,7 @@ h_scrollbar_effect.opacity = 0.f; h_scrollbar_effect.has_potential_opacity_animation = true; - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_ = ScrollbarAnimationController:: CreateScrollbarAnimationControllerAuraOverlay( @@ -199,16 +204,14 @@ // Make the Layer non-scrollable, scrollbar disappears. clip_layer_->SetBounds(gfx::Size(200, 200)); GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 200); - scroll_layer_->UpdateScrollable(); - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); ExpectScrollbarsOpacity(0); // Make the layer scrollable, scrollbar appears again. clip_layer_->SetBounds(gfx::Size(100, 100)); GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 100); - scroll_layer_->UpdateScrollable(); - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); ExpectScrollbarsOpacity(1); } @@ -224,8 +227,7 @@ clip_layer_->SetBounds(gfx::Size(100, 200)); EXPECT_EQ(gfx::Size(100, 200), clip_layer_->bounds()); GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 200); - scroll_layer_->UpdateScrollable(); - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1, h_scrollbar_layer_->Opacity()); @@ -235,8 +237,7 @@ clip_layer_->SetBounds(gfx::Size(200, 100)); EXPECT_EQ(gfx::Size(200, 100), clip_layer_->bounds()); GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 100); - scroll_layer_->UpdateScrollable(); - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, h_scrollbar_layer_->Opacity()); @@ -1494,6 +1495,11 @@ void DidChangeScrollbarVisibility() override {} bool IsFluentOverlayScrollbar() const override { return false; } + void UpdateScrollbarGeometriesAndDrawProperties() { + host_impl()->active_tree()->UpdateAllScrollbarGeometriesForTesting(); + UpdateActiveTreeDrawProperties(); + } + protected: void SetUp() override { const int kTrackStart = 0; @@ -1517,7 +1523,7 @@ scrollbar_effect.opacity = 0.f; scrollbar_effect.has_potential_opacity_animation = true; - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_ = ScrollbarAnimationController::CreateScrollbarAnimationControllerAndroid( @@ -1597,8 +1603,7 @@ // Shrink along X axis, horizontal scrollbar should appear. GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 200); - scroll_layer_->UpdateScrollable(); - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); @@ -1606,8 +1611,7 @@ // Shrink along Y axis and expand along X, horizontal scrollbar // should disappear. GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 100); - scroll_layer_->UpdateScrollable(); - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); @@ -1620,16 +1624,14 @@ // Shrink along X axis, vertical scrollbar should remain invisible. GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(100, 200); - scroll_layer_->UpdateScrollable(); - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); // Shrink along Y axis and expand along X, vertical scrollbar should appear. GetScrollNode(scroll_layer_.get())->container_bounds = gfx::Size(200, 100); - scroll_layer_->UpdateScrollable(); - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); @@ -1639,7 +1641,7 @@ EXPECT_EQ(ScrollbarOrientation::kHorizontal, scrollbar_layer_->orientation()); GetScrollNode(scroll_layer_.get())->user_scrollable_horizontal = false; - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); @@ -1649,7 +1651,7 @@ EXPECT_EQ(ScrollbarOrientation::kHorizontal, scrollbar_layer_->orientation()); GetScrollNode(scroll_layer_.get())->user_scrollable_vertical = false; - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity()); @@ -1660,7 +1662,7 @@ EXPECT_EQ(ScrollbarOrientation::kVertical, scrollbar_layer_->orientation()); GetScrollNode(scroll_layer_.get())->user_scrollable_vertical = false; - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(0.0f, scrollbar_layer_->Opacity()); @@ -1671,7 +1673,7 @@ EXPECT_EQ(ScrollbarOrientation::kVertical, scrollbar_layer_->orientation()); GetScrollNode(scroll_layer_.get())->user_scrollable_horizontal = false; - UpdateActiveTreeDrawProperties(); + UpdateScrollbarGeometriesAndDrawProperties(); scrollbar_controller_->DidScrollUpdate(); EXPECT_FLOAT_EQ(1.0f, scrollbar_layer_->Opacity());
diff --git a/cc/input/scrollbar_controller.cc b/cc/input/scrollbar_controller.cc index eee49d58..b895d0e 100644 --- a/cc/input/scrollbar_controller.cc +++ b/cc/input/scrollbar_controller.cc
@@ -86,7 +86,6 @@ InputHandlerPointerResult scroll_result; scroll_result.target_scroller = scrollbar->scroll_element_id(); scroll_result.type = PointerResultType::kScrollbarScroll; - layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries(); const ScrollbarPart scrollbar_part = GetScrollbarPartFromPointerDown(position_in_widget); const bool perform_jump_click_on_track = @@ -174,7 +173,6 @@ if (clipped) return false; - layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries(); const ScrollbarOrientation orientation = scrollbar->orientation(); const gfx::Rect forward_track_rect = scrollbar->ForwardTrackRect(); @@ -237,8 +235,6 @@ } float ScrollbarController::GetScrollDistanceForAbsoluteJump() const { - layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries(); - bool clipped = false; const gfx::PointF pointer_position_in_layer = GetScrollbarRelativePosition(last_known_pointer_position_, &clipped); @@ -442,7 +438,6 @@ // // |<- scrollbar_thumb_length ->| // - layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries(); const ScrollbarLayerImplBase* scrollbar = ScrollbarLayer(); float scroll_layer_length = scrollbar->scroll_layer_length(); float scrollbar_track_length = scrollbar->TrackLength(); @@ -504,8 +499,6 @@ return; } - layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries(); - bool clipped; gfx::PointF scroller_relative_position( GetScrollbarRelativePosition(last_known_pointer_position_, &clipped)); @@ -614,9 +607,7 @@ if (!(scroll_node && scrollbar_scroll_is_active_)) return; - layer_tree_host_impl_->active_tree()->UpdateScrollbarGeometries(); float scroll_layer_length = scrollbar->scroll_layer_length(); - gfx::PointF current_offset = scroll_tree.current_scroll_offset(scroll_node->element_id);
diff --git a/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc b/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc index 3a97bfa..aaa3682 100644 --- a/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc +++ b/cc/input/single_scrollbar_animation_controller_thinning_unittest.cc
@@ -86,6 +86,7 @@ scrollbar_layer_->SetOffsetToTransformParent(gfx::Vector2dF(90, 0)); CreateEffectNode(scrollbar_layer_).has_potential_opacity_animation = true; + host_impl()->active_tree()->UpdateAllScrollbarGeometriesForTesting(); UpdateActiveTreeDrawProperties(); scrollbar_controller_ = SingleScrollbarAnimationControllerThinning::Create(
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index 69d6a2d0..6632ca7 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -1454,8 +1454,6 @@ layer->SetContentsOpaqueForText(inputs.contents_opaque_for_text); layer->SetShouldCheckBackfaceVisibility(should_check_backface_visibility()); - layer->UpdateScrollable(); - // The property trees must be safe to access because they will be used below // to call |SetScrollOffsetClobberActiveValue|. DCHECK(layer->layer_tree_impl()->lifecycle().AllowsPropertyTreeAccess());
diff --git a/cc/layers/layer_impl.cc b/cc/layers/layer_impl.cc index 28fc06e..2990d218 100644 --- a/cc/layers/layer_impl.cc +++ b/cc/layers/layer_impl.cc
@@ -336,47 +336,6 @@ return scroll_tree.ScrollBy(*scroll_node, scroll, layer_tree_impl()); } -void LayerImpl::UpdateScrollable() { - if (!element_id()) { - scrollable_ = false; - return; - } - - const auto* scroll_node = GetScrollTree().FindNodeFromElementId(element_id()); - bool was_scrollable = scrollable_; - scrollable_ = scroll_node && (scroll_node->user_scrollable_horizontal || - scroll_node->user_scrollable_vertical); - if (was_scrollable == scrollable_) { - if (!scrollable_) - return; - if (scroll_container_bounds_ == scroll_node->container_bounds && - scroll_contents_bounds_ == scroll_node->bounds) - return; - } - - const bool container_bounds_changed = - scrollable_ && scroll_node->container_bounds != scroll_container_bounds_; - scroll_container_bounds_ = - scrollable_ ? scroll_node->container_bounds : gfx::Size(); - scroll_contents_bounds_ = scrollable_ ? scroll_node->bounds : gfx::Size(); - - // Scrollbar positions depend on the bounds. - layer_tree_impl()->SetScrollbarGeometriesNeedUpdate(); - - if (layer_tree_impl()->settings().scrollbar_animator == - LayerTreeSettings::AURA_OVERLAY) { - if (layer_tree_impl()->settings().enable_fluent_overlay_scrollbar) { - // Show scrollbars when resizing scrollable areas and - // not when the inside content gets expanded. - set_needs_show_scrollbars(scrollable_ && container_bounds_changed); - } else { - set_needs_show_scrollbars(scrollable_); - } - } - - NoteLayerPropertyChanged(); -} - void LayerImpl::SetTouchActionRegion(TouchActionRegion region) { // Avoid recalculating the cached |all_touch_action_regions_| value. if (touch_action_region_ == region) @@ -434,8 +393,6 @@ layer->effect_tree_index_ = effect_tree_index_; layer->clip_tree_index_ = clip_tree_index_; layer->scroll_tree_index_ = scroll_tree_index_; - if (needs_show_scrollbars_) - layer->needs_show_scrollbars_ = needs_show_scrollbars_; if (layer_property_changed_not_from_property_trees_ || layer_property_changed_from_property_trees_) @@ -446,7 +403,6 @@ layer->layer_property_changed_from_property_trees_ = true; layer->SetBounds(bounds_); - layer->UpdateScrollable(); layer->UnionUpdateRect(update_rect_); @@ -460,7 +416,6 @@ } // Reset any state that should be cleared for the next update. - needs_show_scrollbars_ = false; ResetChangeTracking(); } @@ -554,11 +509,6 @@ return; bounds_ = bounds; - - // Scrollbar positions depend on the scrolling layer bounds. - if (scrollable_) - layer_tree_impl()->SetScrollbarGeometriesNeedUpdate(); - NoteLayerPropertyChanged(); } @@ -668,8 +618,10 @@ void LayerImpl::SetCurrentScrollOffset(const gfx::PointF& scroll_offset) { DCHECK(IsActive()); - if (GetScrollTree().SetScrollOffset(element_id(), scroll_offset)) - layer_tree_impl()->DidUpdateScrollOffset(element_id()); + if (GetScrollTree().SetScrollOffset(element_id(), scroll_offset)) { + layer_tree_impl()->DidUpdateScrollOffset( + element_id(), /*pushed_from_main_or_pending_tree=*/false); + } } SimpleEnclosedRegion LayerImpl::VisibleOpaqueRegion() const {
diff --git a/cc/layers/layer_impl.h b/cc/layers/layer_impl.h index ee5e691..b06dd481 100644 --- a/cc/layers/layer_impl.h +++ b/cc/layers/layer_impl.h
@@ -258,11 +258,6 @@ // initial scroll gfx::Vector2dF ScrollBy(const gfx::Vector2dF& scroll); - // Called during a commit or activation, after the property trees are pushed. - // It detects changes of scrollable status and scroll container size in the - // scroll property, and invalidate scrollbar geometries etc. for the changes. - void UpdateScrollable(); - // Some properties on the LayerImpl are rarely set, and so are bundled // under a single unique_ptr. struct CC_EXPORT RareProperties { @@ -471,9 +466,6 @@ ElementListType GetElementTypeForAnimation() const; - void set_needs_show_scrollbars(bool yes) { needs_show_scrollbars_ = yes; } - bool needs_show_scrollbars() { return needs_show_scrollbars_; } - void set_raster_even_if_not_drawn(bool yes) { raster_even_if_not_drawn_ = yes; } @@ -536,18 +528,6 @@ gfx::Vector2dF offset_to_transform_parent_; - // These fields are copies of |container_bounds|, |bounds| and |scrollable| - // fields in the associated ScrollNode, and are updated in UpdateScrollable(). - // The copy is for change detection only. - // TODO(wangxianzhu): Actually we only need scroll_container_bounds_ in - // pre-CompositeAfterPaint where the scroll node is associated with the - // scrolling contents layer, and only need scroll_contents_bounds_ in - // CompositeAfterPaint where the scroll node is associated with the scroll - // container layer. Remove scroll_container_bounds_ when we launch CAP. - gfx::Size scroll_container_bounds_; - gfx::Size scroll_contents_bounds_; - bool scrollable_ : 1 = false; - // Tracks if drawing-related properties have changed since last redraw. // TODO(wutao): We want to distinquish the sources of change so that we can // reuse the cache of render pass. For example, we can reuse the cache when @@ -610,12 +590,6 @@ bool needs_push_properties_ : 1 = false; - // The needs_show_scrollbars_ bit tracks a pending request to show the overlay - // scrollbars. It's set by UpdateScrollable() on the scroll layer (not the - // scrollbar layers) and consumed by LayerTreeImpl::PushPropertiesTo() and - // LayerTreeImpl::HandleScrollbarShowRequests(). - bool needs_show_scrollbars_ : 1 = false; - // This is set for layers that have a property because of which they are not // drawn (singular transforms), but they can become visible soon (the property // is being animated). For this reason, while these layers are not drawn, they
diff --git a/cc/layers/layer_impl_unittest.cc b/cc/layers/layer_impl_unittest.cc index 52e11749..b24214e 100644 --- a/cc/layers/layer_impl_unittest.cc +++ b/cc/layers/layer_impl_unittest.cc
@@ -204,8 +204,9 @@ VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES(layer->ScrollBy(arbitrary_vector2d)); VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES(layer->ScrollBy(gfx::Vector2d())); - VERIFY_NEEDS_UPDATE_DRAW_PROPERTIES( - layer->layer_tree_impl()->DidUpdateScrollOffset(layer->element_id())); + VERIFY_NO_NEEDS_UPDATE_DRAW_PROPERTIES( + layer->layer_tree_impl()->DidUpdateScrollOffset( + layer->element_id(), /*pushed_from_main_or_pending_tree=*/false)); layer->layer_tree_impl() ->property_trees() ->scroll_tree_mutable()
diff --git a/cc/layers/scrollbar_layer_impl_base.cc b/cc/layers/scrollbar_layer_impl_base.cc index 7850f6b..fa4130b9 100644 --- a/cc/layers/scrollbar_layer_impl_base.cc +++ b/cc/layers/scrollbar_layer_impl_base.cc
@@ -83,26 +83,6 @@ return true; } -float ScrollbarLayerImplBase::current_pos() const { - DCHECK(!layer_tree_impl()->ScrollbarGeometriesNeedUpdate()); - return current_pos_; -} - -float ScrollbarLayerImplBase::clip_layer_length() const { - DCHECK(!layer_tree_impl()->ScrollbarGeometriesNeedUpdate()); - return clip_layer_length_; -} - -float ScrollbarLayerImplBase::scroll_layer_length() const { - DCHECK(!layer_tree_impl()->ScrollbarGeometriesNeedUpdate()); - return scroll_layer_length_; -} - -float ScrollbarLayerImplBase::vertical_adjust() const { - DCHECK(!layer_tree_impl()->ScrollbarGeometriesNeedUpdate()); - return vertical_adjust_; -} - bool ScrollbarLayerImplBase::CanScrollOrientation() const { PropertyTrees* property_trees = layer_tree_impl()->property_trees(); const auto* scroll_node = @@ -123,12 +103,6 @@ return false; } - // Ensure the clip_layer_length and scroll_layer_length values are up-to-date. - // TODO(pdr): Instead of using the clip and scroll layer lengths which require - // an update, refactor to use the scroll tree (ScrollTree::MaxScrollOffset - // as in LayerTreeHostImpl::TryScroll). - layer_tree_impl()->UpdateScrollbarGeometries(); - // Ensure clip_layer_length is smaller than scroll_layer_length, not including // small deltas due to floating point error. return !MathUtil::IsFloatNearlyTheSame(clip_layer_length(), @@ -150,6 +124,9 @@ clip_layer_length_ = clip_layer_length; property_changed_for_other_reasons_ = true; NoteLayerPropertyChanged(); + if (GetScrollbarAnimator() == LayerTreeSettings::AURA_OVERLAY) { + layer_tree_impl()->RequestShowScrollbars(scroll_element_id_); + } } void ScrollbarLayerImplBase::SetScrollLayerLength(float scroll_layer_length) { @@ -158,7 +135,11 @@ scroll_layer_length_ = scroll_layer_length; property_changed_for_other_reasons_ = true; NoteLayerPropertyChanged(); - return; + if (GetScrollbarAnimator() == LayerTreeSettings::AURA_OVERLAY && + // We don't show fluent scrollbars when the contents change size. + !IsFluentOverlayScrollbarEnabled()) { + layer_tree_impl()->RequestShowScrollbars(scroll_element_id_); + } } void ScrollbarLayerImplBase::SetThumbThicknessScaleFactor(float factor) {
diff --git a/cc/layers/scrollbar_layer_impl_base.h b/cc/layers/scrollbar_layer_impl_base.h index 6bc47a8..a3d99e13 100644 --- a/cc/layers/scrollbar_layer_impl_base.h +++ b/cc/layers/scrollbar_layer_impl_base.h
@@ -32,10 +32,10 @@ void SetScrollLayerLength(float scroll_layer_length); void SetVerticalAdjust(float vertical_adjust); - float current_pos() const; - float clip_layer_length() const; - float scroll_layer_length() const; - float vertical_adjust() const; + float current_pos() const { return current_pos_; } + float clip_layer_length() const { return clip_layer_length_; } + float scroll_layer_length() const { return scroll_layer_length_; } + float vertical_adjust() const { return vertical_adjust_; } bool is_overlay_scrollbar() const { return is_overlay_scrollbar_; } void set_is_overlay_scrollbar(bool is_overlay) {
diff --git a/cc/layers/scrollbar_layer_unittest.cc b/cc/layers/scrollbar_layer_unittest.cc index 5c1dc77220..68ed14b7 100644 --- a/cc/layers/scrollbar_layer_unittest.cc +++ b/cc/layers/scrollbar_layer_unittest.cc
@@ -506,7 +506,6 @@ static_cast<PaintedScrollbarLayerImpl*>( layer_impl_tree_root->layer_tree_impl()->LayerById( scrollbar_layer->id())); - layer_impl_tree_root->layer_tree_impl()->UpdateScrollbarGeometries(); EXPECT_EQ(10.f, cc_scrollbar_layer->current_pos()); EXPECT_EQ(30, cc_scrollbar_layer->scroll_layer_length() - @@ -520,7 +519,6 @@ layer_tree_host_->UpdateLayers(); layer_impl_tree_root = layer_tree_host_->CommitToActiveTree(); - layer_impl_tree_root->layer_tree_impl()->UpdateScrollbarGeometries(); EXPECT_EQ(100.f, cc_scrollbar_layer->current_pos()); EXPECT_EQ(300, cc_scrollbar_layer->scroll_layer_length() - @@ -529,7 +527,6 @@ LayerImpl* scroll_layer_impl = layer_impl_tree_root->layer_tree_impl()->LayerById(scroll_layer->id()); scroll_layer_impl->ScrollBy(gfx::Vector2d(12, 34)); - layer_impl_tree_root->layer_tree_impl()->UpdateScrollbarGeometries(); EXPECT_EQ(112.f, cc_scrollbar_layer->current_pos()); EXPECT_EQ(300, cc_scrollbar_layer->scroll_layer_length() - @@ -540,7 +537,6 @@ do { \ scrollbar_layer->Update(); \ root_layer_impl = layer_tree_host_->CommitToActiveTree(); \ - root_layer_impl->layer_tree_impl()->UpdateScrollbarGeometries(); \ scrollbar_layer_impl = static_cast<decltype(scrollbar_layer_impl)>( \ root_layer_impl->layer_tree_impl()->LayerById(scrollbar_layer->id())); \ } while (false) @@ -890,14 +886,12 @@ auto* scrollbar_layer_impl = static_cast<ScrollbarLayerImplBase*>( scroll_layer_impl->layer_tree_impl()->LayerById(child2->id())); + scrollbar_layer_impl->SetBounds(gfx::Size(kTrackLength, kThumbThickness)); scroll_layer_impl->ScrollBy(gfx::Vector2dF(4.f, 0.f)); - scrollbar_layer_impl->SetBounds(gfx::Size(kTrackLength, kThumbThickness)); - scrollbar_layer_impl->SetCurrentPos(4.f); - - DCHECK(layer_tree_host_->active_tree()->ScrollbarGeometriesNeedUpdate()); - layer_tree_host_->active_tree()->UpdateScrollbarGeometries(); - + EXPECT_EQ(4.f, scrollbar_layer_impl->current_pos()); + EXPECT_EQ(10, scrollbar_layer_impl->scroll_layer_length()); + EXPECT_EQ(2, scrollbar_layer_impl->clip_layer_length()); { auto render_pass = viz::CompositorRenderPass::Create(); @@ -1058,8 +1052,7 @@ CreateScrollNode(scroll_layer, gfx::Size(980, 980)); CopyProperties(scroll_layer, scrollbar_layer); - DCHECK(impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); + impl.host_impl()->active_tree()->UpdateAllScrollbarGeometriesForTesting(); impl.CalcDrawProps(viewport_size); // Fake clip layer length to scrollbar to mock rounding error. @@ -1075,96 +1068,6 @@ EXPECT_TRUE(scrollbar_layer->CanScrollOrientation()); } -TEST_F(ScrollbarLayerTest, LayerChangesAffectingScrollbarGeometries) { - LayerTreeImplTestBase impl; - SetupViewport(impl.root_layer(), gfx::Size(), gfx::Size(900, 900)); - - auto* scroll_layer = impl.OuterViewportScrollLayer(); - EXPECT_FALSE(GetScrollNode(scroll_layer)->user_scrollable_horizontal); - EXPECT_FALSE(GetScrollNode(scroll_layer)->user_scrollable_vertical); - - const int kTrackStart = 0; - const int kThumbThickness = 10; - const bool kIsLeftSideVerticalScrollbar = false; - SolidColorScrollbarLayerImpl* scrollbar_layer = - impl.AddLayerInActiveTree<SolidColorScrollbarLayerImpl>( - ScrollbarOrientation::kHorizontal, kThumbThickness, kTrackStart, - kIsLeftSideVerticalScrollbar); - scrollbar_layer->SetScrollElementId(scroll_layer->element_id()); - EXPECT_TRUE(impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); - - GetScrollNode(scroll_layer)->container_bounds = gfx::Size(900, 900); - scroll_layer->SetBounds(gfx::Size(900, 900)); - scroll_layer->UpdateScrollable(); - EXPECT_FALSE(GetScrollNode(scroll_layer)->user_scrollable_horizontal); - EXPECT_FALSE(GetScrollNode(scroll_layer)->user_scrollable_vertical); - // If the scroll layer is not scrollable, the bounds and the container bounds - // do not affect scrollbar geometries. - EXPECT_FALSE( - impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - - // Changing scrollable to true should require an update. - GetScrollNode(scroll_layer)->user_scrollable_horizontal = true; - scroll_layer->UpdateScrollable(); - EXPECT_TRUE(impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); - - scroll_layer->SetBounds(gfx::Size(980, 980)); - // Changes to the bounds should also require an update. - EXPECT_TRUE(impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); - - // Changes to the container bounds should require an update. - GetScrollNode(scroll_layer)->container_bounds = gfx::Size(500, 500); - scroll_layer->UpdateScrollable(); - EXPECT_TRUE(impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); - - // Not changing the current value should not require an update. - scroll_layer->SetBounds(gfx::Size(980, 980)); - EXPECT_FALSE( - impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - scroll_layer->UpdateScrollable(); - EXPECT_FALSE( - impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - - // Changing scrollable to false should require an update. - GetScrollNode(scroll_layer)->user_scrollable_horizontal = false; - scroll_layer->UpdateScrollable(); - EXPECT_TRUE(impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); -} - -TEST_F(ScrollbarLayerTest, UpdateScrollbarGeometriesScrollNodeOnContainer) { - LayerTreeImplTestBase impl; - - LayerImpl* scroll_layer = impl.AddLayerInActiveTree<LayerImpl>(); - scroll_layer->SetElementId(LayerIdToElementIdForTesting(scroll_layer->id())); - scroll_layer->SetBounds(gfx::Size(100, 100)); - - CopyProperties(impl.root_layer(), scroll_layer); - CreateTransformNode(scroll_layer); - // In CompositeAfterPaint, the scroll node is associated with the scroll - // container layer. Its |container_bounds| is the same as the bounds of the - // layer, and its |bounds| is the bounds of the scrolling contents. - CreateScrollNode(scroll_layer, gfx::Size(100, 100)).bounds = - gfx::Size(1000, 1000); - - EXPECT_TRUE(impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); - - GetScrollNode(scroll_layer)->bounds = gfx::Size(1000, 2000); - scroll_layer->UpdateScrollable(); - EXPECT_TRUE(impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); - - scroll_layer->UpdateScrollable(); - EXPECT_FALSE( - impl.host_impl()->active_tree()->ScrollbarGeometriesNeedUpdate()); - impl.host_impl()->active_tree()->UpdateScrollbarGeometries(); -} - TEST_P(AuraScrollbarLayerTest, ScrollbarLayerCreateAfterSetScrollable) { // Scrollbar Layer can be created after SetScrollable is called and in a // separate commit. Ensure we do not missing the DidRequestShowFromMainThread
diff --git a/cc/test/fake_layer_tree_host.cc b/cc/test/fake_layer_tree_host.cc index 4535143..67a799a 100644 --- a/cc/test/fake_layer_tree_host.cc +++ b/cc/test/fake_layer_tree_host.cc
@@ -100,52 +100,29 @@ LayerImpl* FakeLayerTreeHost::CommitToActiveTree() { CHECK(host_impl_->CommitsToActiveTree()); - // TODO(pdr): Update the LayerTreeImpl lifecycle states here so lifecycle - // violations can be caught. - // When doing a full commit, we would call - // layer_tree_host_->ActivateCommitState() and the second argument would come - // from layer_tree_host_->active_commit_state(); we use pending_commit_state() - // just to keep the test code simple. - host_impl_->BeginCommit(pending_commit_state()->source_frame_number, - pending_commit_state()->trace_id); - TreeSynchronizer::SynchronizeTrees( - *pending_commit_state(), thread_unsafe_commit_state(), active_tree()); - active_tree()->SetPropertyTrees(*property_trees()); - TreeSynchronizer::PushLayerProperties( - *pending_commit_state(), thread_unsafe_commit_state(), active_tree()); - mutator_host()->PushPropertiesTo(host_impl_->mutator_host(), - *property_trees()); - - active_tree() - ->property_trees() - ->scroll_tree_mutable() - .PushScrollUpdatesFromMainThread( - *property_trees(), active_tree(), - GetSettings().commit_fractional_scroll_deltas); - + CommitToTree(active_tree()); + // This is part of LayerTreeHostImpl::CommitComplete(), but unit tests don't + // expect this function to do other things, e.g. animation updates. + active_tree()->HandleScrollbarShowRequests(); return active_tree()->root_layer(); } LayerImpl* FakeLayerTreeHost::CommitToPendingTree() { CHECK(!host_impl_->CommitsToActiveTree()); - // pending_commit_state() is used here because this is a phony commit that - // doesn't actually call WillCommit() or ActivateCommitState(). - pending_tree()->set_source_frame_number(SourceFrameNumber()); - TreeSynchronizer::SynchronizeTrees( - *pending_commit_state(), thread_unsafe_commit_state(), pending_tree()); - pending_tree()->SetPropertyTrees(*property_trees()); - TreeSynchronizer::PushLayerProperties( - *pending_commit_state(), thread_unsafe_commit_state(), pending_tree()); - mutator_host()->PushPropertiesTo(host_impl_->mutator_host(), - *property_trees()); + return CommitToTree(pending_tree()); +} - pending_tree() - ->property_trees() - ->scroll_tree_mutable() - .PushScrollUpdatesFromMainThread( - *property_trees(), pending_tree(), - GetSettings().commit_fractional_scroll_deltas); - return pending_tree()->root_layer(); +LayerImpl* FakeLayerTreeHost::CommitToTree(LayerTreeImpl* tree) { + // pending_commit_state() is used in this function because this is a phony + // commit that doesn't actually call WillCommit() or ActivateCommitState(). + tree->set_source_frame_number(SourceFrameNumber()); + PropertyTreesChangeState change_state; + property_trees()->GetChangeState(change_state); + std::swap(change_state, pending_commit_state()->property_trees_change_state); + host_impl_->FinishCommit(*pending_commit_state(), + thread_unsafe_commit_state()); + std::swap(change_state, pending_commit_state()->property_trees_change_state); + return tree->root_layer(); } } // namespace cc
diff --git a/cc/test/fake_layer_tree_host.h b/cc/test/fake_layer_tree_host.h index 0d81eb9..86aec0f 100644 --- a/cc/test/fake_layer_tree_host.h +++ b/cc/test/fake_layer_tree_host.h
@@ -97,6 +97,7 @@ LayerImpl* CommitToActiveTree(); LayerImpl* CommitToPendingTree(); + LayerImpl* CommitToTree(LayerTreeImpl* tree); FakeLayerTreeHostImpl* host_impl() { return host_impl_; } LayerTreeImpl* active_tree() {
diff --git a/cc/test/property_tree_test_utils.cc b/cc/test/property_tree_test_utils.cc index d75a714..0204fec 100644 --- a/cc/test/property_tree_test_utils.cc +++ b/cc/test/property_tree_test_utils.cc
@@ -322,10 +322,7 @@ ScrollNode& CreateScrollNode(LayerImpl* layer, const gfx::Size& scroll_container_bounds, int parent_id) { - auto& node = - CreateScrollNodeInternal(layer, scroll_container_bounds, parent_id); - layer->UpdateScrollable(); - return node; + return CreateScrollNodeInternal(layer, scroll_container_bounds, parent_id); } ScrollNode& CreateScrollNodeForNonCompositedScroller(
diff --git a/cc/tiles/tile_manager.cc b/cc/tiles/tile_manager.cc index 761ef975..2c0f2344 100644 --- a/cc/tiles/tile_manager.cc +++ b/cc/tiles/tile_manager.cc
@@ -362,7 +362,7 @@ completion_cb_(std::move(completion_cb)) {} void RunOnWorkerThread() override { - TRACE_EVENT0("cc", "TaskSetFinishedTaskImpl::RunOnWorkerThread"); + TRACE_EVENT0("cc", "DidFinishRunningAllTilesTask::RunOnWorkerThread"); bool has_pending_queries = false; if (pending_raster_queries_) { has_pending_queries =
diff --git a/cc/trees/draw_properties_unittest.cc b/cc/trees/draw_properties_unittest.cc index a46315f..ca6359f 100644 --- a/cc/trees/draw_properties_unittest.cc +++ b/cc/trees/draw_properties_unittest.cc
@@ -68,7 +68,7 @@ ->scroll_tree_mutable() .SetScrollOffsetDeltaForTesting(layer_impl->element_id(), delta)) layer_impl->layer_tree_impl()->DidUpdateScrollOffset( - layer_impl->element_id()); + layer_impl->element_id(), /*pushed_from_main_or_pending_tree=*/false); } static float MaximumAnimationToScreenScale(LayerImpl* layer_impl) {
diff --git a/cc/trees/layer_tree_host_impl_unittest.cc b/cc/trees/layer_tree_host_impl_unittest.cc index b237038..80b8320c 100644 --- a/cc/trees/layer_tree_host_impl_unittest.cc +++ b/cc/trees/layer_tree_host_impl_unittest.cc
@@ -834,7 +834,7 @@ ->scroll_tree_mutable() .SetScrollOffsetDeltaForTesting(layer_impl->element_id(), delta)) layer_impl->layer_tree_impl()->DidUpdateScrollOffset( - layer_impl->element_id()); + layer_impl->element_id(), /*pushed_from_main_or_pending_tree=*/false); } void BeginImplFrameAndAnimate(viz::BeginFrameArgs begin_frame_args, @@ -5304,6 +5304,7 @@ SetupScrollbarLayer(OuterViewportScrollLayer(), scrollbar); host_impl_->active_tree()->DidBecomeActive(); + host_impl_->active_tree()->UpdateAllScrollbarGeometriesForTesting(); host_impl_->active_tree()->HandleScrollbarShowRequests(); host_impl_->active_tree()->SetLocalSurfaceIdFromParent(viz::LocalSurfaceId( 1, base::UnguessableToken::CreateForTesting(2u, 3u))); @@ -5460,7 +5461,8 @@ .UpdateScrollOffsetBaseForTesting( InnerViewportScrollLayer()->element_id(), gfx::PointF(5, 5))) host_impl_->active_tree()->DidUpdateScrollOffset( - InnerViewportScrollLayer()->element_id()); + InnerViewportScrollLayer()->element_id(), + /*pushed_from_main_or_pending_tree=*/false); EXPECT_FALSE(did_request_next_frame_); EXPECT_FALSE(did_request_redraw_); EXPECT_EQ(base::TimeDelta(), requested_animation_delay_); @@ -5638,8 +5640,8 @@ SetupScrollbarLayer(child, scrollbar_2_); scrollbar_2_->SetBounds(scrollbar_size_2); + host_impl_->active_tree()->UpdateAllScrollbarGeometriesForTesting(); UpdateDrawProperties(host_impl_->active_tree()); - host_impl_->active_tree()->UpdateScrollbarGeometries(); host_impl_->active_tree()->DidBecomeActive(); ResetScrollbars(); @@ -5961,7 +5963,7 @@ child->SetBounds(content_size); child->SetBounds(inner_viewport_size); - host_impl_->active_tree()->UpdateScrollbarGeometries(); + host_impl_->active_tree()->UpdateAllScrollbarGeometriesForTesting(); EXPECT_EQ(300, horiz_scrollbar->clip_layer_length()); } @@ -6042,7 +6044,7 @@ // Changing one of the child layers should result in a scrollbar animation // update. animation_task_.Reset(); - child->set_needs_show_scrollbars(true); + host_impl_->active_tree()->RequestShowScrollbars(child_scroll_element_id); UpdateDrawProperties(host_impl_->active_tree()); host_impl_->active_tree()->HandleScrollbarShowRequests(); EXPECT_FALSE(animation_task_.is_null()); @@ -6081,7 +6083,7 @@ vert_scrollbar->SetOffsetToTransformParent( gfx::Vector2dF(300 - kScrollbarThickness, 0)); - host_impl_->active_tree()->UpdateScrollbarGeometries(); + host_impl_->active_tree()->UpdateAllScrollbarGeometriesForTesting(); EXPECT_EQ(1ul, host_impl_->ScrollbarsFor(root_scroll->element_id()).size()); auto* scrollbar_controller = @@ -7303,8 +7305,8 @@ touch_action_region.Union(TouchAction::kNone, gfx::Rect(scrollbar_size)); scrollbar_layer->SetTouchActionRegion(touch_action_region); scrollbar_layer->SetOffsetToTransformParent(gfx::Vector2dF(0, 35)); + host_impl_->active_tree()->UpdateAllScrollbarGeometriesForTesting(); UpdateDrawProperties(host_impl_->active_tree()); - host_impl_->active_tree()->UpdateScrollbarGeometries(); DrawFrame(); @@ -7329,7 +7331,6 @@ // the actual content bounds shouldn't. { host_impl_->browser_controls_manager()->ScrollBy(gfx::Vector2dF(0, 25)); - host_impl_->active_tree()->UpdateScrollbarGeometries(); EXPECT_VIEWPORT_GEOMETRIES(0.5f); EXPECT_EQ(gfx::SizeF(50, 75), active_tree->ScrollableSize()); EXPECT_EQ(gfx::Size(50, 15), scrollbar_layer->bounds()); @@ -7340,7 +7341,6 @@ // Fully hide the browser controls. { host_impl_->browser_controls_manager()->ScrollBy(gfx::Vector2dF(0, 25)); - host_impl_->active_tree()->UpdateScrollbarGeometries(); EXPECT_VIEWPORT_GEOMETRIES(0); EXPECT_EQ(gfx::SizeF(50, 100), active_tree->ScrollableSize()); EXPECT_EQ(gfx::Size(50, 15), scrollbar_layer->bounds()); @@ -13805,13 +13805,12 @@ base::OnceClosure& animation_task) { GetEffectNode(root_scrollbar)->opacity = 0; GetEffectNode(child_scrollbar)->opacity = 0; + active_tree->UpdateAllScrollbarGeometriesForTesting(); UpdateDrawProperties(active_tree); animation_task.Reset(); }; reset_scrollbars(host_impl_->active_tree(), animation_task_); - UpdateDrawProperties(host_impl_->active_tree()); - host_impl_->active_tree()->UpdateScrollbarGeometries(); host_impl_->active_tree()->DidBecomeActive(); EXPECT_EQ(root_scrollbar->Opacity(), 0); @@ -13897,6 +13896,7 @@ scrollbar->SetTrackStart(0); scrollbar->SetTrackLength(575); scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0)); + layer_tree_impl->UpdateAllScrollbarGeometriesForTesting(); // Set up the scroll node and other state required for scrolling. GetInputHandler().ScrollBegin( @@ -14119,6 +14119,7 @@ scrollbar->SetThumbLength(50); scrollbar->SetTrackRect(gfx::Rect(0, 15, 15, 575)); scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0)); + layer_tree_impl->UpdateAllScrollbarGeometriesForTesting(); TestInputHandlerClient input_handler_client; GetInputHandler().BindToClient(&input_handler_client); @@ -14245,6 +14246,7 @@ gfx::Rect(gfx::Point(345, 570), gfx::Size(15, 15))); scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0)); + layer_tree_impl->UpdateAllScrollbarGeometriesForTesting(); GetInputHandler().ScrollBegin( BeginState(gfx::Point(350, 18), gfx::Vector2dF(), @@ -14535,7 +14537,9 @@ gfx::Rect(gfx::Point(345, 0), gfx::Size(15, 15))); scrollbar->SetForwardButtonRect( gfx::Rect(gfx::Point(345, 570), gfx::Size(15, 15))); + scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0)); + layer_tree_impl->UpdateAllScrollbarGeometriesForTesting(); TestInputHandlerClient input_handler_client; GetInputHandler().BindToClient(&input_handler_client); @@ -14635,7 +14639,9 @@ gfx::Rect(gfx::Point(345, 0), gfx::Size(15, 15))); scrollbar->SetForwardButtonRect( gfx::Rect(gfx::Point(345, 570), gfx::Size(15, 15))); + scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0)); + layer_tree_impl->UpdateAllScrollbarGeometriesForTesting(); TestInputHandlerClient input_handler_client; GetInputHandler().BindToClient(&input_handler_client); @@ -14905,7 +14911,9 @@ gfx::Rect(gfx::Point(345, 0), gfx::Size(15, 15))); scrollbar->SetForwardButtonRect( gfx::Rect(gfx::Point(345, 570), gfx::Size(15, 15))); + scrollbar->SetOffsetToTransformParent(gfx::Vector2dF(345, 0)); + layer_tree_impl->UpdateAllScrollbarGeometriesForTesting(); TestInputHandlerClient input_handler_client; GetInputHandler().BindToClient(&input_handler_client); @@ -16165,7 +16173,7 @@ touch_action_region.Union(TouchAction::kNone, gfx::Rect(scrollbar_size_1)); scrollbar_1->SetTouchActionRegion(touch_action_region); - host_impl_->active_tree()->UpdateScrollbarGeometries(); + host_impl_->active_tree()->UpdateAllScrollbarGeometriesForTesting(); host_impl_->active_tree()->DidBecomeActive(); DrawFrame(); @@ -16265,8 +16273,8 @@ scrollbar_2->SetBounds(scrollbar_size_2); scrollbar_2->SetOffsetToTransformParent(child->offset_to_transform_parent()); + host_impl_->active_tree()->UpdateAllScrollbarGeometriesForTesting(); UpdateDrawProperties(host_impl_->active_tree()); - host_impl_->active_tree()->UpdateScrollbarGeometries(); host_impl_->active_tree()->DidBecomeActive(); ScrollbarAnimationController* scrollbar_2_animation_controller =
diff --git a/cc/trees/layer_tree_host_unittest_scroll.cc b/cc/trees/layer_tree_host_unittest_scroll.cc index 3f697da..513c8c7 100644 --- a/cc/trees/layer_tree_host_unittest_scroll.cc +++ b/cc/trees/layer_tree_host_unittest_scroll.cc
@@ -1933,7 +1933,7 @@ ->scroll_tree_mutable() .SetScrollOffsetDeltaForTesting(layer_impl->element_id(), delta)) layer_impl->layer_tree_impl()->DidUpdateScrollOffset( - layer_impl->element_id()); + layer_impl->element_id(), /*pushed_from_main_or_pending_tree=*/false); } int root_scroll_layer_id_;
diff --git a/cc/trees/layer_tree_impl.cc b/cc/trees/layer_tree_impl.cc index 9613a57..80ecd84 100644 --- a/cc/trees/layer_tree_impl.cc +++ b/cc/trees/layer_tree_impl.cc
@@ -214,10 +214,9 @@ } } -void LayerTreeImpl::DidUpdateScrollOffset(ElementId id) { - // Scrollbar positions depend on the current scroll offset. - SetScrollbarGeometriesNeedUpdate(); - +void LayerTreeImpl::DidUpdateScrollOffset( + ElementId id, + bool pushed_from_main_or_pending_tree) { DCHECK(lifecycle().AllowsPropertyTreeAccess()); const ScrollTree& scroll_tree = property_trees()->scroll_tree(); const auto* scroll_node = scroll_tree.FindNodeFromElementId(id); @@ -266,90 +265,113 @@ if (IsActiveTree()) { // Ensure the other trees are kept in sync. - if (host_impl_->pending_tree()) - host_impl_->pending_tree()->DidUpdateScrollOffset(id); - if (host_impl_->recycle_tree()) - host_impl_->recycle_tree()->DidUpdateScrollOffset(id); + if (host_impl_->pending_tree() && !pushed_from_main_or_pending_tree) { + host_impl_->pending_tree()->DidUpdateScrollOffset( + id, pushed_from_main_or_pending_tree); + } + if (host_impl_->recycle_tree()) { + host_impl_->recycle_tree()->DidUpdateScrollOffset( + id, pushed_from_main_or_pending_tree); + } + + // If the scroll offset is pushed from main or pending tree, we'll call + // UpdateAllScrollbarGeometries() soon, so no need to update here. Also we + // can't do that here because the needed data may not be complete yet. + if (!pushed_from_main_or_pending_tree) { + if (scroll_node == InnerViewportScrollNode() || + scroll_node == OuterViewportScrollNode()) { + UpdateViewportScrollbarGeometries(); + } else { + UpdateScrollbarGeometries(*scroll_node); + } + } } } -void LayerTreeImpl::UpdateScrollbarGeometries() { +void LayerTreeImpl::UpdateAllScrollbarGeometries() { if (!IsActiveTree()) return; + // Property tree and layer properties such should be up-to-date. DCHECK(lifecycle().AllowsPropertyTreeAccess()); - - // Layer properties such as bounds should be up-to-date. DCHECK(lifecycle().AllowsLayerPropertyAccess()); - if (!scrollbar_geometries_need_update_) - return; - for (auto& pair : element_id_to_scrollbar_layer_ids_) { - ElementId scrolling_element_id = pair.first; - - const auto& scroll_tree = property_trees()->scroll_tree(); - const auto* scroll_node = - scroll_tree.FindNodeFromElementId(scrolling_element_id); - if (!scroll_node) - continue; - gfx::PointF current_offset = - scroll_tree.current_scroll_offset(scrolling_element_id); - gfx::SizeF scrolling_size(scroll_node->bounds); - gfx::Size bounds_size(scroll_tree.container_bounds(scroll_node->id)); - - bool is_viewport_scrollbar = scroll_node == InnerViewportScrollNode() || - scroll_node == OuterViewportScrollNode(); - if (is_viewport_scrollbar) { - gfx::SizeF viewport_bounds(bounds_size); - if (scroll_node == InnerViewportScrollNode()) { - DCHECK_EQ(scroll_node, InnerViewportScrollNode()); - auto* outer_scroll_node = OuterViewportScrollNode(); - DCHECK(outer_scroll_node); - - // Add offset and bounds contribution of outer viewport. - current_offset += - scroll_tree.current_scroll_offset(outer_scroll_node->element_id) - .OffsetFromOrigin(); - gfx::SizeF outer_viewport_bounds( - scroll_tree.container_bounds(outer_scroll_node->id)); - viewport_bounds.SetToMin(outer_viewport_bounds); - // The scrolling size is only determined by the outer viewport. - scrolling_size = gfx::SizeF(outer_scroll_node->bounds); - } else { - DCHECK_EQ(scroll_node, OuterViewportScrollNode()); - auto* inner_scroll_node = InnerViewportScrollNode(); - DCHECK(inner_scroll_node); - // Add offset and bounds contribution of inner viewport. - current_offset += - scroll_tree.current_scroll_offset(inner_scroll_node->element_id) - .OffsetFromOrigin(); - gfx::SizeF inner_viewport_bounds( - scroll_tree.container_bounds(inner_scroll_node->id)); - viewport_bounds.SetToMin(inner_viewport_bounds); - } - viewport_bounds.InvScale(current_page_scale_factor()); - bounds_size = ToCeiledSize(viewport_bounds); - } - - for (auto* scrollbar : ScrollbarsFor(scrolling_element_id)) { - if (scrollbar->orientation() == ScrollbarOrientation::kHorizontal) { - scrollbar->SetCurrentPos(current_offset.x()); - scrollbar->SetClipLayerLength(bounds_size.width()); - scrollbar->SetScrollLayerLength(scrolling_size.width()); - } else { - scrollbar->SetCurrentPos(current_offset.y()); - scrollbar->SetClipLayerLength(bounds_size.height()); - scrollbar->SetScrollLayerLength(scrolling_size.height()); - } - if (is_viewport_scrollbar) { - scrollbar->SetVerticalAdjust( - property_trees_.inner_viewport_container_bounds_delta().y()); - } + if (const auto* scroll_node = + property_trees()->scroll_tree().FindNodeFromElementId(pair.first)) { + UpdateScrollbarGeometries(*scroll_node); } } +} - scrollbar_geometries_need_update_ = false; +void LayerTreeImpl::UpdateViewportScrollbarGeometries() { + if (!IsActiveTree()) { + return; + } + if (auto* inner_scroll = InnerViewportScrollNode()) { + UpdateScrollbarGeometries(*inner_scroll); + } + if (auto* outer_scroll = OuterViewportScrollNode()) { + UpdateScrollbarGeometries(*outer_scroll); + } +} + +void LayerTreeImpl::UpdateScrollbarGeometries(const ScrollNode& scroll_node) { + DCHECK(IsActiveTree()); + const auto& scroll_tree = property_trees()->scroll_tree(); + gfx::PointF current_offset = + scroll_tree.current_scroll_offset(scroll_node.element_id); + gfx::SizeF scrolling_size(scroll_node.bounds); + gfx::Size bounds_size(scroll_tree.container_bounds(scroll_node.id)); + + bool is_viewport_scrollbar = &scroll_node == InnerViewportScrollNode() || + &scroll_node == OuterViewportScrollNode(); + if (is_viewport_scrollbar) { + gfx::SizeF viewport_bounds(bounds_size); + if (&scroll_node == InnerViewportScrollNode()) { + auto* outer_scroll_node = OuterViewportScrollNode(); + DCHECK(outer_scroll_node); + + // Add offset and bounds contribution of outer viewport. + current_offset += + scroll_tree.current_scroll_offset(outer_scroll_node->element_id) + .OffsetFromOrigin(); + gfx::SizeF outer_viewport_bounds( + scroll_tree.container_bounds(outer_scroll_node->id)); + viewport_bounds.SetToMin(outer_viewport_bounds); + // The scrolling size is only determined by the outer viewport. + scrolling_size = gfx::SizeF(outer_scroll_node->bounds); + } else { + DCHECK_EQ(&scroll_node, OuterViewportScrollNode()); + auto* inner_scroll_node = InnerViewportScrollNode(); + DCHECK(inner_scroll_node); + // Add offset and bounds contribution of inner viewport. + current_offset += + scroll_tree.current_scroll_offset(inner_scroll_node->element_id) + .OffsetFromOrigin(); + gfx::SizeF inner_viewport_bounds( + scroll_tree.container_bounds(inner_scroll_node->id)); + viewport_bounds.SetToMin(inner_viewport_bounds); + } + viewport_bounds.InvScale(current_page_scale_factor()); + bounds_size = ToCeiledSize(viewport_bounds); + } + + for (auto* scrollbar : ScrollbarsFor(scroll_node.element_id)) { + if (scrollbar->orientation() == ScrollbarOrientation::kHorizontal) { + scrollbar->SetCurrentPos(current_offset.x()); + scrollbar->SetClipLayerLength(bounds_size.width()); + scrollbar->SetScrollLayerLength(scrolling_size.width()); + } else { + scrollbar->SetCurrentPos(current_offset.y()); + scrollbar->SetClipLayerLength(bounds_size.height()); + scrollbar->SetScrollLayerLength(scrolling_size.height()); + } + if (is_viewport_scrollbar) { + scrollbar->SetVerticalAdjust( + property_trees_.inner_viewport_container_bounds_delta().y()); + } + } } const RenderSurfaceImpl* LayerTreeImpl::RootRenderSurface() const { @@ -495,8 +517,7 @@ // Viewport scrollbar positions are determined using the viewport bounds // delta. - SetScrollbarGeometriesNeedUpdate(); - set_needs_update_draw_properties(); + UpdateViewportScrollbarGeometries(); } bool LayerTreeImpl::IsRootLayer(const LayerImpl* layer) const { @@ -689,6 +710,8 @@ // and draw properties are invalidated. MoveChangeTrackingToLayers(); + UpdateAllScrollbarGeometries(); + lifecycle().AdvanceTo(LayerTreeLifecycle::kNotSyncing); } @@ -905,6 +928,7 @@ // Note: this needs to happen after SetPropertyTrees. target_tree->HandleTickmarksVisibilityChange(); + target_tree->UpdateAllScrollbarGeometries(); target_tree->HandleScrollbarShowRequests(); target_tree->AddPresentationCallbacks(std::move(presentation_callbacks_)); presentation_callbacks_.clear(); @@ -956,18 +980,21 @@ } } +void LayerTreeImpl::RequestShowScrollbars(ElementId scroll_element_id) { + if (IsActiveTree()) { + show_scrollbar_requests_.insert(scroll_element_id); + } +} + void LayerTreeImpl::HandleScrollbarShowRequests() { - for (auto* layer : *this) { - if (!layer->needs_show_scrollbars()) - continue; - ScrollbarAnimationController* controller = - host_impl_->ScrollbarAnimationControllerForElementId( - layer->element_id()); - if (controller) { + for (ElementId scroll_element_id : show_scrollbar_requests_) { + if (ScrollbarAnimationController* controller = + host_impl_->ScrollbarAnimationControllerForElementId( + scroll_element_id)) { controller->DidRequestShow(); - layer->set_needs_show_scrollbars(false); } } + show_scrollbar_requests_.clear(); } void LayerTreeImpl::MoveChangeTrackingToLayers() { @@ -1458,7 +1485,7 @@ set_needs_update_draw_properties(); // Viewport scrollbar sizes depend on the page scale factor. - SetScrollbarGeometriesNeedUpdate(); + UpdateViewportScrollbarGeometries(); } void LayerTreeImpl::SetDeviceScaleFactor(float device_scale_factor) { @@ -1642,11 +1669,6 @@ TRACE_EVENT0("cc,benchmark", "LayerTreeImpl::UpdateDrawProperties"); - // Ensure the scrollbar geometries are up-to-date for hit testing and quads - // generation. This may cause damage on the scrollbar layers which is why - // it occurs before we reset |needs_update_draw_properties_|. - UpdateScrollbarGeometries(); - // Calling UpdateDrawProperties must clear this flag, so there can be no // early outs before this. needs_update_draw_properties_ = false; @@ -2293,9 +2315,6 @@ host_impl_->RegisterScrollbarAnimationController( scroll_element_id, scrollbar_layer->Opacity()); } - - // The new scrollbar's geometries need to be initialized. - SetScrollbarGeometriesNeedUpdate(); } void LayerTreeImpl::UnregisterScrollbar(
diff --git a/cc/trees/layer_tree_impl.h b/cc/trees/layer_tree_impl.h index b7c9147..0e68b4d 100644 --- a/cc/trees/layer_tree_impl.h +++ b/cc/trees/layer_tree_impl.h
@@ -644,6 +644,7 @@ void RegisterScrollbar(ScrollbarLayerImplBase* scrollbar_layer); void UnregisterScrollbar(ScrollbarLayerImplBase* scrollbar_layer); ScrollbarSet ScrollbarsFor(ElementId scroll_element_id) const; + void RequestShowScrollbars(ElementId scroll_element_id); LayerImpl* FindLayerThatIsHitByPoint(const gfx::PointF& screen_space_point); @@ -726,24 +727,8 @@ void RequestForceSendMetadata() { force_send_metadata_request_ = true; } bool TakeForceSendMetadataRequest(); - void DidUpdateScrollOffset(ElementId id); - - // Mark the scrollbar geometries (e.g., thumb size and position) as needing an - // update. - void SetScrollbarGeometriesNeedUpdate() { - if (IsActiveTree()) { - scrollbar_geometries_need_update_ = true; - // Scrollbar geometries are updated in |UpdateDrawProperties|. - set_needs_update_draw_properties(); - } - } - bool ScrollbarGeometriesNeedUpdate() const { - return scrollbar_geometries_need_update_; - } - // Update the geometries of all scrollbars (e.g., thumb size and position). An - // update only occurs if a scroll-related layer has changed (see: - // SetScrollbarGeometriesNeedUpdate). - void UpdateScrollbarGeometries(); + void DidUpdateScrollOffset(ElementId id, + bool pushed_from_main_or_pending_tree); // See LayerTreeHost. bool have_scroll_event_handlers() const { @@ -856,6 +841,10 @@ // removed. Note that this method will never remove the root layer. size_t RemoveLayers(base::span<int> layer_ids); + void UpdateAllScrollbarGeometriesForTesting() { + UpdateAllScrollbarGeometries(); + } + protected: float ClampPageScaleFactorToLimits(float page_scale_factor) const; void PushPageScaleFactorAndLimits(const float* page_scale_factor, @@ -881,6 +870,11 @@ const gfx::PointF& screen_space_point, const Functor& func); + // Update the geometries of all scrollbars (e.g., thumb size and position). + void UpdateAllScrollbarGeometries(); + void UpdateViewportScrollbarGeometries(); + void UpdateScrollbarGeometries(const ScrollNode& scroll_node); + raw_ptr<LayerTreeHostImpl> host_impl_; int source_frame_number_; uint64_t trace_id_ = 0; @@ -912,10 +906,6 @@ bool needs_update_tiles_ : 1 = false; - // True if a scrollbar geometry value has changed. For example, if the scroll - // offset changes, scrollbar thumb positions need to be updated. - bool scrollbar_geometries_need_update_ : 1 = false; - // In impl-side painting mode, this is true when the tree may contain // structural differences relative to the active tree. bool needs_full_tree_sync_ : 1 = true; @@ -967,11 +957,16 @@ int horizontal = Layer::INVALID_ID; int vertical = Layer::INVALID_ID; }; - // Each scroll layer can have up to two scrollbar layers (vertical and + // Each scroller can have up to two scrollbar layers (vertical and/or // horizontal). This mapping is maintained as part of scrollbar registration. base::flat_map<ElementId, ScrollbarLayerIds> element_id_to_scrollbar_layer_ids_; + // Tracks a pending requests to show overlay scrollbars. It's set by the + // scrollbar layer and consumed by PushPropertiesTo() and + // HandleScrollbarShowRequests(). + base::flat_set<ElementId> show_scrollbar_requests_; + std::vector<raw_ptr<PictureLayerImpl, VectorExperimental>> picture_layers_; // After commit (or impl-side invalidation), the LayerTreeHostImpl must walk
diff --git a/cc/trees/property_tree.cc b/cc/trees/property_tree.cc index 1623c81..589270f 100644 --- a/cc/trees/property_tree.cc +++ b/cc/trees/property_tree.cc
@@ -1598,8 +1598,10 @@ scroll_offset.x(), "y", scroll_offset.y()); ScrollNode* scroll_node = Node(scroll_tree_index); if (SetScrollOffset(id, - ClampScrollOffsetToLimits(scroll_offset, *scroll_node))) - layer_tree_impl->DidUpdateScrollOffset(id); + ClampScrollOffsetToLimits(scroll_offset, *scroll_node))) { + layer_tree_impl->DidUpdateScrollOffset( + id, /*pushed_from_main_or_pending_tree=*/false); + } layer_tree_impl->DidAnimateScrollOffset(); } @@ -1875,8 +1877,10 @@ if (property_trees()->is_active()) needs_scroll_update |= synced_scroll_offset->PushPendingToActive(); - if (needs_scroll_update) - sync_tree->DidUpdateScrollOffset(id); + if (needs_scroll_update) { + sync_tree->DidUpdateScrollOffset( + id, /*pushed_from_main_or_pending_tree=*/true); + } } } @@ -1894,8 +1898,10 @@ for (auto map_entry : pending_property_trees->scroll_tree().synced_scroll_offset_map_) { synced_scroll_offset_map_[map_entry.first] = map_entry.second; - if (map_entry.second->PushPendingToActive()) - active_tree->DidUpdateScrollOffset(map_entry.first); + if (map_entry.second->PushPendingToActive()) { + active_tree->DidUpdateScrollOffset( + map_entry.first, /*pushed_from_main_or_pending_tree=*/true); + } } } @@ -2015,8 +2021,11 @@ gfx::PointF old_offset = current_scroll_offset(scroll_node.element_id); gfx::PointF new_offset = ClampScrollOffsetToLimits(old_offset + adjusted_scroll, scroll_node); - if (SetScrollOffset(scroll_node.element_id, new_offset)) - layer_tree_impl->DidUpdateScrollOffset(scroll_node.element_id); + if (SetScrollOffset(scroll_node.element_id, new_offset)) { + layer_tree_impl->DidUpdateScrollOffset( + scroll_node.element_id, + /*pushed_from_main_or_pending_tree=*/false); + } TRACE_EVENT_END("input", /* ScrollTree::ScrollBy */ "old_offset", old_offset, "new_offset", new_offset); @@ -2065,6 +2074,10 @@ PropertyTreesChangeState::PropertyTreesChangeState() = default; PropertyTreesChangeState::~PropertyTreesChangeState() = default; +PropertyTreesChangeState::PropertyTreesChangeState(PropertyTreesChangeState&&) = + default; +PropertyTreesChangeState& PropertyTreesChangeState::operator=( + PropertyTreesChangeState&&) = default; PropertyTrees::PropertyTrees(const ProtectedSequenceSynchronizer& synchronizer) : synchronizer_(synchronizer),
diff --git a/cc/trees/property_tree.h b/cc/trees/property_tree.h index 7af2f34..7868a76 100644 --- a/cc/trees/property_tree.h +++ b/cc/trees/property_tree.h
@@ -722,9 +722,11 @@ ~PropertyTreesCachedData(); }; -struct PropertyTreesChangeState { +struct CC_EXPORT PropertyTreesChangeState { PropertyTreesChangeState(); ~PropertyTreesChangeState(); + PropertyTreesChangeState(PropertyTreesChangeState&&); + PropertyTreesChangeState& operator=(PropertyTreesChangeState&&); bool changed = false; bool needs_rebuild = false; bool full_tree_damaged = false;
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index cc9b792..c9875bd 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -287,7 +287,7 @@ android_resources("java_overlay_resources") { # Target for overrides of //ui/android:ui_java_resources resource_overlay = true - sources = [ "java/res_overlay/values/styles.xml" ] + sources = [ "java/res_overlay/values-v33/styles.xml" ] deps = [ "//ui/android:ui_java_resources" ] }
diff --git a/chrome/android/features/tab_ui/BUILD.gn b/chrome/android/features/tab_ui/BUILD.gn index a82ed285..0cd7e86e0 100644 --- a/chrome/android/features/tab_ui/BUILD.gn +++ b/chrome/android/features/tab_ui/BUILD.gn
@@ -74,6 +74,7 @@ "java/res/layout/bottom_tab_strip_toolbar.xml", "java/res/layout/color_picker_item.xml", "java/res/layout/custom_message_card_item.xml", + "java/res/layout/dynamic_bottom_tab_strip_toolbar.xml", "java/res/layout/large_message_card_item.xml", "java/res/layout/price_card.xml", "java/res/layout/strip_tab_drag_shadow_view.xml",
diff --git a/chrome/android/features/tab_ui/java/res/layout/dynamic_bottom_tab_strip_toolbar.xml b/chrome/android/features/tab_ui/java/res/layout/dynamic_bottom_tab_strip_toolbar.xml new file mode 100644 index 0000000..4283aef --- /dev/null +++ b/chrome/android/features/tab_ui/java/res/layout/dynamic_bottom_tab_strip_toolbar.xml
@@ -0,0 +1,93 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- +Copyright 2024 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> + +<org.chromium.chrome.browser.tasks.tab_management.TabGroupUiToolbarView + xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + android:id="@+id/tab_group_ui_toolbar_view" + android:layout_width="match_parent" + android:layout_height="match_parent" + xmlns:tools="http://schemas.android.com/tools" + android:background="?attr/colorSurface"> + <androidx.constraintlayout.widget.ConstraintLayout + android:id="@+id/main_content" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:layout_gravity="center_vertical" + android:animateLayoutChanges="true"> + <!-- + Chain style packed with horizontal bias 0.0 forces this to effectively + have gravity "start" and bring anything attached to the constraint + chain along with it. Setting constrainedWidth to true in conjunction + with wrap_content for width allows the chain to dynamically resize + without any of the views overlapping as the maximum width of the views + inside of the FrameLayout are restricted by the constraints. + --> + <FrameLayout + android:id="@+id/toolbar_container_view" + android:layout_width="wrap_content" + android:layout_height="match_parent" + app:layout_constraintHorizontal_chainStyle="packed" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constrainedWidth="true" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.5" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintEnd_toStartOf="@+id/toolbar_new_tab_button"/> + <!-- z-index above the recycler view by putting after FrameLayout. --> + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/tab_strip_fading_edge_start" + android:layout_height="match_parent" + android:layout_width="@dimen/tab_strip_fading_edge_width" + android:src="@drawable/tab_strip_fading_edge_start" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.5" + app:layout_constraintStart_toStartOf="parent" + android:importantForAccessibility="no"/> + <!-- Use negative margin start to overlay the recycler view. --> + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/tab_strip_fading_edge_end" + android:layout_height="match_parent" + android:layout_width="@dimen/tab_strip_fading_edge_width" + android:layout_marginStart="@dimen/tab_strip_fading_edge_width_negative" + android:src="@drawable/tab_strip_fading_edge_end" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.5" + app:layout_constraintStart_toEndOf="@+id/toolbar_container_view" + android:importantForAccessibility="no"/> + + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/toolbar_new_tab_button" + style="@style/BottomToolbarButton" + android:src="@drawable/plus" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.5" + app:layout_constraintStart_toEndOf="@+id/toolbar_container_view" + app:layout_constraintEnd_toStartOf="@+id/toolbar_show_group_dialog_button" + android:contentDescription="@string/bottom_tab_grid_new_tab" + app:tint="@color/default_icon_color_tint_list" /> + + <!-- + TODO(crbug.com/362280397): add a guideline and make in the "leftmost" + of the following view and the container for the avatars. + --> + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/toolbar_show_group_dialog_button" + style="@style/BottomToolbarButton" + android:src="@drawable/ic_expand_less_black_24dp" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:layout_constraintVertical_bias="0.5" + app:layout_constraintEnd_toEndOf="parent" + app:tint="@color/default_icon_color_tint_list" + tools:ignore="ContentDescription" /> + </androidx.constraintlayout.widget.ConstraintLayout> +</org.chromium.chrome.browser.tasks.tab_management.TabGroupUiToolbarView>
diff --git a/chrome/android/features/tab_ui/java/res/values/dimens.xml b/chrome/android/features/tab_ui/java/res/values/dimens.xml index ef7d9e3..fb98698 100644 --- a/chrome/android/features/tab_ui/java/res/values/dimens.xml +++ b/chrome/android/features/tab_ui/java/res/values/dimens.xml
@@ -29,6 +29,7 @@ <dimen name="share_button_corner_radius">16dp</dimen> <dimen name="tab_group_toolbar_title_margin_start">8dp</dimen> <dimen name="tab_strip_fading_edge_width">8dp</dimen> + <dimen name="tab_strip_fading_edge_width_negative">-8dp</dimen> <dimen name="tab_strip_button_width">48dp</dimen> <dimen name="swipe_to_dismiss_threshold">144dp</dimen> <dimen name="selection_tab_grid_toggle_button_inset">14dp</dimen>
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java index 6712015..4e9b44c7 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiCoordinator.java
@@ -9,6 +9,7 @@ import android.view.LayoutInflater; import android.view.ViewGroup; +import androidx.annotation.LayoutRes; import androidx.annotation.NonNull; import org.chromium.base.Callback; @@ -20,6 +21,7 @@ import org.chromium.base.supplier.Supplier; import org.chromium.chrome.browser.browser_controls.BrowserControlsStateProvider; import org.chromium.chrome.browser.data_sharing.DataSharingTabManager; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.layouts.LayoutStateProvider; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.tab.Tab; @@ -97,10 +99,14 @@ mScrimCoordinator = scrimCoordinator; mOmniboxFocusStateSupplier = omniboxFocusStateSupplier; mModel = new PropertyModel(TabGroupUiProperties.ALL_KEYS); + @LayoutRes + int layoutId = + ChromeFeatureList.isEnabled(ChromeFeatureList.DATA_SHARING) + ? R.layout.dynamic_bottom_tab_strip_toolbar + : R.layout.bottom_tab_strip_toolbar; mToolbarView = (TabGroupUiToolbarView) - LayoutInflater.from(mContext) - .inflate(R.layout.bottom_tab_strip_toolbar, parentView, false); + LayoutInflater.from(mContext).inflate(layoutId, parentView, false); mTabListContainerView = mToolbarView.getViewContainer(); mBottomSheetController = bottomSheetController; mDataSharingTabManager = dataSharingTabManager;
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java index ccfa872..3f579e2 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiToolbarView.java
@@ -11,7 +11,6 @@ import android.view.View; import android.view.ViewGroup; import android.widget.FrameLayout; -import android.widget.LinearLayout; import androidx.annotation.ColorRes; import androidx.core.content.ContextCompat; @@ -28,7 +27,7 @@ private ChromeImageView mFadingEdgeStart; private ChromeImageView mFadingEdgeEnd; private ViewGroup mContainerView; - private LinearLayout mMainContent; + private ViewGroup mMainContent; public TabGroupUiToolbarView(Context context, AttributeSet attrs) { super(context, attrs);
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java index 4cdbacc6..e89c2c17 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegate.java
@@ -142,14 +142,4 @@ @NonNull LazyOneshotSupplier<HubManager> hubManagerSupplier, @NonNull Supplier<TabGroupUiActionHandler> tabGroupUiActionHandlerSupplier, @NonNull Supplier<ModalDialogManager> modalDialogManagerSupplier); - - /** - * Create a {@link CrossDevicePane} for the Hub. - * - * @param context Used to inflate UI. - * @param onToolbarAlphaChange Observer to notify when alpha changes during animations. - * @return The pane implementation that displays and allows interactions with cross device tabs. - */ - Pane createCrossDevicePane( - @NonNull Context context, @NonNull DoubleConsumer onToolbarAlphaChange); }
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java index a0392194..890d6cc 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabManagementDelegateImpl.java
@@ -180,10 +180,4 @@ tabGroupUiActionHandlerSupplier, modalDialogManagerSupplier); } - - @Override - public Pane createCrossDevicePane( - @NonNull Context context, @NonNull DoubleConsumer onToolbarAlphaChange) { - return new CrossDevicePane(context, onToolbarAlphaChange); - } }
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd index 989550ff5..671a0b2c 100644 --- a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd +++ b/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings.grd
@@ -877,11 +877,6 @@ <ph name="TITLE_OF_GROUP">%s<ex>shopping</ex></ph> tab group options </message> - <!-- Cross Device Pane Strings--> - <message name="IDS_ACCESSIBILITY_CROSS_DEVICE_TABS" desc="Content description for the button to show the cross device tabs UI."> - Tabs from other devices - </message> - <!-- Tabs Settings Strings --> <message name="IDS_TABS_SETTINGS_TITLE" desc="A title to show in the top toolbar when the Tabs settings page is open."> Tabs
diff --git a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java index 9d79faab..1b864f9 100644 --- a/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java +++ b/chrome/android/features/tab_ui/javatests/src/org/chromium/chrome/browser/tasks/tab_management/TabGroupUiTest.java
@@ -221,7 +221,7 @@ @EnableFeatures(ChromeFeatureList.DATA_SHARING) public void testRenderStrip_toggleNotificationBubble() throws IOException { final ChromeTabbedActivity cta = sActivityTestRule.getActivity(); - AtomicReference<RecyclerView> recyclerViewReference = new AtomicReference<>(); + AtomicReference<ViewGroup> controlsReference = new AtomicReference<>(); TabUiTestHelper.addBlankTabs(cta, false, 1); enterTabSwitcher(cta); verifyTabSwitcherCardCount(cta, 2); @@ -247,9 +247,10 @@ ImageView notificationView = stripRecyclerView.findViewById(R.id.tab_strip_notification_bubble); notificationView.setVisibility(View.VISIBLE); - recyclerViewReference.set(stripRecyclerView); + controlsReference.set(bottomToolbar); }); - mRenderTestRule.render(recyclerViewReference.get(), "tab_strip_notification_bubble_on"); + mRenderTestRule.render( + controlsReference.get(), "bottom_controls_tab_strip_notification_bubble_on"); ThreadUtils.runOnUiThreadBlocking( () -> { @@ -260,9 +261,10 @@ ImageView notificationView = stripRecyclerView.findViewById(R.id.tab_strip_notification_bubble); notificationView.setVisibility(View.GONE); - recyclerViewReference.set(stripRecyclerView); + controlsReference.set(bottomToolbar); }); - mRenderTestRule.render(recyclerViewReference.get(), "tab_strip_notification_bubble_off"); + mRenderTestRule.render( + controlsReference.get(), "bottom_controls_tab_strip_notification_bubble_off"); } @Test
diff --git a/chrome/android/features/tab_ui/tab_management_java_sources.gni b/chrome/android/features/tab_ui/tab_management_java_sources.gni index 2de6b8c..25769f65 100644 --- a/chrome/android/features/tab_ui/tab_management_java_sources.gni +++ b/chrome/android/features/tab_ui/tab_management_java_sources.gni
@@ -45,7 +45,6 @@ "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ColorPickerItemViewBinder.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ColorPickerMediator.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/Corner.java", - "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CrossDevicePane.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CustomMessageCardProvider.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CustomMessageCardView.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CustomMessageCardViewBinder.java", @@ -211,7 +210,6 @@ "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/ActionConfirmationManagerUnitTest.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CloseAllTabsHelperUnitTest.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CollaborationActivityMessageCardViewModelUnitTest.java", - "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CrossDevicePaneUnitTest.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/IncognitoTabSwitcherPaneUnitTest.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabArchiveSettingsFragmentUnitTest.java", "//chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabGridDialogMenuCoordinatorUnitTest.java",
diff --git a/chrome/android/java/res_overlay/values/styles.xml b/chrome/android/java/res_overlay/values-v33/styles.xml similarity index 100% rename from chrome/android/java/res_overlay/values/styles.xml rename to chrome/android/java/res_overlay/values-v33/styles.xml
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 3663cf9..b385b26 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -167,6 +167,7 @@ import org.chromium.chrome.browser.quick_delete.QuickDeleteDelegateImpl; import org.chromium.chrome.browser.quick_delete.QuickDeleteMetricsDelegate; import org.chromium.chrome.browser.read_later.ReadingListBackPressHandler; +import org.chromium.chrome.browser.recent_tabs.CrossDevicePaneFactory; import org.chromium.chrome.browser.reengagement.ReengagementNotificationController; import org.chromium.chrome.browser.safety_hub.SafetyHubMagicStackBuilder; import org.chromium.chrome.browser.search_engines.SearchEngineChoiceNotification; @@ -938,8 +939,7 @@ } private Pane createCrossDevicePane() { - return TabManagementDelegateProvider.getDelegate() - .createCrossDevicePane(this, adaptOnToolbarAlphaChange()); + return CrossDevicePaneFactory.create(this, adaptOnToolbarAlphaChange()); } private void setupCompositorContent() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java index c569aa46..34357e12 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/MainSettings.java
@@ -522,7 +522,8 @@ && getArguments() .getBoolean(PasswordManagerHelper.START_PASSWORDS_EXPORT); if (startPasswordsExportFlow) { - PasswordManagerHelper.getForProfile(getProfile()).launchExportFlow(getContext()); + PasswordManagerHelper.getForProfile(getProfile()) + .launchExportFlow(getContext(), mModalDialogManagerSupplier); getArguments().putBoolean(PasswordManagerHelper.START_PASSWORDS_EXPORT, false); } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java index 4f6a34b..93c382e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tasks/ReturnToChromeUtil.java
@@ -86,7 +86,7 @@ ChromeFeatureList.newIntCachedFieldTrialParameter( ChromeFeatureList.START_SURFACE_RETURN_TIME, HOME_SURFACE_RETURN_TIME_SECONDS_PARAM, - 14400); // 4 hours + 28800); // 8 hours private ReturnToChromeUtil() {}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java index b54e7b1..d5e5555 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappRegistry.java
@@ -216,7 +216,10 @@ String scope = getWebApkScopeFromStorage(storage); if (scope.isEmpty()) continue; - if (scope.startsWith(origin)) return true; + if (scope.startsWith(origin) + && PackageUtils.isPackageInstalled(storage.getWebApkPackageName())) { + return true; + } } return false; }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java index 02e37ce..a478051 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java
@@ -764,6 +764,7 @@ public void testHasWebApkForOrigin() throws Exception { final String startUrl = START_URL + "/test_page.html"; final String testOrigin = START_URL; + final String testPackageName = "org.chromium.webapk"; assertFalse(WebappRegistry.getInstance().hasAtLeastOneWebApkForOrigin(testOrigin)); @@ -772,8 +773,13 @@ assertFalse(WebappRegistry.getInstance().hasAtLeastOneWebApkForOrigin(testOrigin)); BrowserServicesIntentDataProvider webApkIntentDataProvider = - new WebApkIntentDataProviderBuilder("org.chromium.webapk", startUrl).build(); + new WebApkIntentDataProviderBuilder(testPackageName, startUrl).build(); registerWebapp(webApkIntentDataProvider); + // Still fails because the WebAPK is "no longer installed" according to PackageManager. + assertFalse(WebappRegistry.getInstance().hasAtLeastOneWebApkForOrigin(testOrigin)); + + Shadows.shadowOf(RuntimeEnvironment.application.getPackageManager()) + .addPackage(testPackageName); assertTrue(WebappRegistry.getInstance().hasAtLeastOneWebApkForOrigin(testOrigin)); }
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 6619270..405f261 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -8682,6 +8682,9 @@ <message name="IDS_NTP_MODULES_MORE_ACTIONS" desc="The tooltip and accessibility label for the 3 dot menu on a module."> More actions for <ph name="MODULE_NAME">$1<ex>shopping suggestions</ex></ph> </message> + <message name="IDS_NTP_MODULE_HEADER_MORE_ACTIONS_MENU" desc="Text read to screen reader users when navigating to a module's more actions menu."> + More actions + </message> <message name="IDS_NTP_MODULES_CUSTOMIZE_BUTTON_TEXT" desc="Text shown on the customize button of an NTP module."> Customize cards </message>
diff --git a/chrome/app/generated_resources_grd/IDS_NTP_MODULE_HEADER_MORE_ACTIONS_MENU.png.sha1 b/chrome/app/generated_resources_grd/IDS_NTP_MODULE_HEADER_MORE_ACTIONS_MENU.png.sha1 new file mode 100644 index 0000000..bcc2509 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_NTP_MODULE_HEADER_MORE_ACTIONS_MENU.png.sha1
@@ -0,0 +1 @@ +862f4b37bbd94f650bf6a87aa4dc7bb510c86bd4 \ No newline at end of file
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index 024c902..89b5afa 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3598,9 +3598,6 @@ "diagnostics/recon_diagnostics.h", "diagnostics/sqlite_diagnostics.cc", "diagnostics/sqlite_diagnostics.h", - "digital_credentials/digital_identity_bluetooth_adapter_status_change_observer.h", - "digital_credentials/digital_identity_fido_handler_observer.cc", - "digital_credentials/digital_identity_fido_handler_observer.h", "digital_credentials/digital_identity_provider_desktop.cc", "digital_credentials/digital_identity_provider_desktop.h", "direct_sockets/chrome_direct_sockets_delegate.cc",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index b41047d..a0e62c41 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -3686,28 +3686,26 @@ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || \ BUILDFLAG(IS_CHROMEOS) +const flags_ui::FeatureEntry::FeatureParam kPwaNavigationCapturingDefaultOn[] = + {{"link_capturing_state", "on_by_default"}}; +const flags_ui::FeatureEntry::FeatureParam kPwaNavigationCapturingDefaultOff[] = + {{"link_capturing_state", "off_by_default"}}; const flags_ui::FeatureEntry::FeatureParam - kDesktopPWAsLinkCapturingDefaultOn[] = { - {"link_capturing_state", "on_by_default"}}; -const flags_ui::FeatureEntry::FeatureParam - kDesktopPWAsLinkCapturingDefaultOff[] = { - {"link_capturing_state", "off_by_default"}}; -const flags_ui::FeatureEntry::FeatureParam - kDesktopPWAsLinkCapturingReimplDefaultOn[] = { + kPwaNavigationCapturingReimplDefaultOn[] = { {"link_capturing_state", "reimpl_default_on"}}; const flags_ui::FeatureEntry::FeatureParam - kDesktopPWAsLinkCapturingReimplDefaultOff[] = { + kPwaNavigationCapturingReimplDefaultOff[] = { {"link_capturing_state", "reimpl_default_off"}}; const flags_ui::FeatureEntry::FeatureVariation - kDesktopPWAsLinkCapturingVariations[] = { - {"On by default", kDesktopPWAsLinkCapturingDefaultOn, - std::size(kDesktopPWAsLinkCapturingDefaultOn), nullptr}, - {"Off by default", kDesktopPWAsLinkCapturingDefaultOff, - std::size(kDesktopPWAsLinkCapturingDefaultOff), nullptr}, - {"(Reimpl) On by default", kDesktopPWAsLinkCapturingReimplDefaultOn, - std::size(kDesktopPWAsLinkCapturingReimplDefaultOn), nullptr}, - {"(Reimpl) Off by default", kDesktopPWAsLinkCapturingReimplDefaultOff, - std::size(kDesktopPWAsLinkCapturingReimplDefaultOff), nullptr}}; + kPwaNavigationCapturingVariations[] = { + {"On by default", kPwaNavigationCapturingDefaultOn, + std::size(kPwaNavigationCapturingDefaultOn), nullptr}, + {"Off by default", kPwaNavigationCapturingDefaultOff, + std::size(kPwaNavigationCapturingDefaultOff), nullptr}, + {"(Reimpl) On by default", kPwaNavigationCapturingReimplDefaultOn, + std::size(kPwaNavigationCapturingReimplDefaultOn), nullptr}, + {"(Reimpl) Off by default", kPwaNavigationCapturingReimplDefaultOff, + std::size(kPwaNavigationCapturingReimplDefaultOff), nullptr}}; #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || // BUILDFLAG(IS_CHROMEOS) @@ -10780,8 +10778,7 @@ flag_descriptions::kDesktopPWAsUserLinkCapturingScopeExtensionsName, flag_descriptions::kDesktopPWAsUserLinkCapturingScopeExtensionsDescription, kOsLinux | kOsMac | kOsWin, - FEATURE_VALUE_TYPE( - features::kDesktopPWAsLinkCapturingWithScopeExtensions)}, + FEATURE_VALUE_TYPE(features::kPwaNavigationCapturingWithScopeExtensions)}, {"sync-enable-contact-info-data-type-in-transport-mode", flag_descriptions::kSyncEnableContactInfoDataTypeInTransportModeName, @@ -10793,13 +10790,13 @@ #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || \ BUILDFLAG(IS_CHROMEOS) - {"enable-user-link-capturing-pwa", - flag_descriptions::kDesktopPWAsUserLinkCapturingName, - flag_descriptions::kDesktopPWAsUserLinkCapturingDescription, + {"enable-user-navigation-capturing-pwa", + flag_descriptions::kPwaNavigationCapturingName, + flag_descriptions::kPwaNavigationCapturingDescription, kOsLinux | kOsMac | kOsWin | kOsCrOS, - FEATURE_WITH_PARAMS_VALUE_TYPE(features::kDesktopPWAsLinkCapturing, - kDesktopPWAsLinkCapturingVariations, - "DesktopPWAsLinkCapturing")}, + FEATURE_WITH_PARAMS_VALUE_TYPE(features::kPwaNavigationCapturing, + kPwaNavigationCapturingVariations, + "PwaNavigationCapturing")}, #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) || // BUILDFLAG(IS_CHROMEOS)
diff --git a/chrome/browser/apps/link_capturing/BUILD.gn b/chrome/browser/apps/link_capturing/BUILD.gn index 65f6ec1..1a7069c1 100644 --- a/chrome/browser/apps/link_capturing/BUILD.gn +++ b/chrome/browser/apps/link_capturing/BUILD.gn
@@ -90,7 +90,10 @@ "link_capturing_features.h", ] public_deps = [ "//base" ] - deps = [ "//chrome/common:chrome_features" ] + deps = [ + "//chrome/common:chrome_features", + "//content/public/common", + ] } source_set("test_support") {
diff --git a/chrome/browser/apps/link_capturing/link_capturing_feature_test_support.cc b/chrome/browser/apps/link_capturing/link_capturing_feature_test_support.cc index 42c9dc6..d67bbc557 100644 --- a/chrome/browser/apps/link_capturing/link_capturing_feature_test_support.cc +++ b/chrome/browser/apps/link_capturing/link_capturing_feature_test_support.cc
@@ -13,7 +13,7 @@ #include "chrome/browser/apps/link_capturing/link_capturing_features.h" #include "chrome/browser/web_applications/web_app_command_scheduler.h" #include "chrome/browser/web_applications/web_app_provider.h" -#include "chrome/common/chrome_features.h" +#include "content/public/common/content_features.h" #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/apps/intent_helper/preferred_apps_test_util.h" @@ -29,12 +29,12 @@ return {{::apps::features::kLinkCapturingUiUpdate, {}}}; #else // TODO(crbug.com/351775835): Integrate testing for all enum states of - // `LinkCapturingState`. + // `CapturingState`. bool should_override_by_default = override_captures_by_default.value_or( - ::features::kLinkCapturingDefaultState.default_value == - ::features::LinkCapturingState::kDefaultOn); - return {{::features::kDesktopPWAsLinkCapturing, - {{::features::kLinkCapturingDefaultState.name, + ::features::kNavigationCapturingDefaultState.default_value == + ::features::CapturingState::kDefaultOn); + return {{::features::kPwaNavigationCapturing, + {{::features::kNavigationCapturingDefaultState.name, std::string(should_override_by_default ? "on_by_default" : "off_by_default")}}}}; #endif // BUILDFLAG(IS_CHROMEOS) @@ -44,7 +44,7 @@ #if BUILDFLAG(IS_CHROMEOS) return {::apps::features::kLinkCapturingUiUpdate}; #else - return {::features::kDesktopPWAsLinkCapturing}; + return {::features::kPwaNavigationCapturing}; #endif // BUILDFLAG(IS_CHROMEOS) }
diff --git a/chrome/browser/apps/link_capturing/link_capturing_features.cc b/chrome/browser/apps/link_capturing/link_capturing_features.cc index 9800317..115b545 100644 --- a/chrome/browser/apps/link_capturing/link_capturing_features.cc +++ b/chrome/browser/apps/link_capturing/link_capturing_features.cc
@@ -7,6 +7,7 @@ #include "base/feature_list.h" #include "build/build_config.h" #include "chrome/common/chrome_features.h" +#include "content/public/common/content_features.h" namespace apps::features { @@ -22,16 +23,16 @@ #if BUILDFLAG(IS_CHROMEOS) return base::FeatureList::IsEnabled(kLinkCapturingUiUpdate); #else - return base::FeatureList::IsEnabled(::features::kDesktopPWAsLinkCapturing); + return base::FeatureList::IsEnabled(::features::kPwaNavigationCapturing); #endif // BUILDFLAG(IS_CHROMEOS) } -bool IsLinkCapturingReimplementationEnabled() { - return base::FeatureList::IsEnabled(::features::kDesktopPWAsLinkCapturing) && - (::features::kLinkCapturingDefaultState.Get() == - ::features::LinkCapturingState::kReimplDefaultOn || - ::features::kLinkCapturingDefaultState.Get() == - ::features::LinkCapturingState::kReimplDefaultOff); +bool IsNavigationCapturingReimplEnabled() { + return base::FeatureList::IsEnabled(::features::kPwaNavigationCapturing) && + (::features::kNavigationCapturingDefaultState.Get() == + ::features::CapturingState::kReimplDefaultOn || + ::features::kNavigationCapturingDefaultState.Get() == + ::features::CapturingState::kReimplDefaultOff); } } // namespace apps::features
diff --git a/chrome/browser/apps/link_capturing/link_capturing_features.h b/chrome/browser/apps/link_capturing/link_capturing_features.h index 0099932..61fe4e2 100644 --- a/chrome/browser/apps/link_capturing/link_capturing_features.h +++ b/chrome/browser/apps/link_capturing/link_capturing_features.h
@@ -16,13 +16,13 @@ #endif // BUILDFLAG(IS_CHROMEOS) // Returns true if the updated UX for link capturing needs to be shown. Only set -// to true if kDesktopPWAsLinkCapturing is enabled on desktop platforms, and +// to true if kPwaNavigationCapturing is enabled on desktop platforms, and // kLinkCapturingUiUpdate on CrOS platforms. bool ShouldShowLinkCapturingUX(); -// Returns true if the `DesktopPWAsLinkCapturing` flag is enabled with the +// Returns true if the `kPwaNavigationCapturing` flag is enabled with the // reimplementation parameters set. -bool IsLinkCapturingReimplementationEnabled(); +bool IsNavigationCapturingReimplEnabled(); } // namespace apps::features
diff --git a/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.cc b/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.cc index ff05d36b..8afae16 100644 --- a/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.cc +++ b/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle.cc
@@ -160,7 +160,7 @@ std::unique_ptr<Delegate> delegate) { // If the reimplementation params of the link capturing feature flag is // enabled, turn off the "old" link capturing behavior. - if (features::IsLinkCapturingReimplementationEnabled()) { + if (features::IsNavigationCapturingReimplEnabled()) { return nullptr; }
diff --git a/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle_browsertest.cc b/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle_browsertest.cc index c128a9c..e2e4089 100644 --- a/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle_browsertest.cc +++ b/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle_browsertest.cc
@@ -16,9 +16,9 @@ #include "chrome/browser/web_applications/os_integration/os_integration_manager.h" #include "chrome/browser/web_applications/test/os_integration_test_override_impl.h" #include "chrome/browser/web_applications/test/web_app_test_observers.h" -#include "chrome/common/chrome_features.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" +#include "content/public/common/content_features.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" @@ -89,7 +89,7 @@ GURL start_url_; webapps::AppId app_id_; base::test::ScopedFeatureList feature_list_{ - features::kDesktopPWAsLinkCapturing}; + features::kPwaNavigationCapturing}; web_app::OsIntegrationTestOverrideBlockingRegistration faked_os_integration_; };
diff --git a/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle_unittest.cc b/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle_unittest.cc index 0cfe7ea4..dd1e547 100644 --- a/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle_unittest.cc +++ b/chrome/browser/apps/link_capturing/link_capturing_navigation_throttle_unittest.cc
@@ -8,7 +8,7 @@ #include <string> #include "base/test/scoped_feature_list.h" -#include "chrome/common/chrome_features.h" +#include "content/public/common/content_features.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/base/page_transition_types.h" #include "url/gurl.h" @@ -280,7 +280,7 @@ std::map<std::string, std::string> parameters; parameters["link_capturing_state"] = FlagBoolToReimpl(); scoped_feature_list_.InitAndEnableFeatureWithParameters( - features::kDesktopPWAsLinkCapturing, parameters); + features::kPwaNavigationCapturing, parameters); } std::string FlagBoolToReimpl() {
diff --git a/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.cc b/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.cc index d481be2..2d62af1 100644 --- a/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.cc +++ b/chrome/browser/apps/link_capturing/web_apps_intent_picker_delegate.cc
@@ -153,7 +153,7 @@ if (entry_type == PickerEntryType::kWeb) { // Launch app directly only if |url| is in the scope of |app_id|. if (base::FeatureList::IsEnabled( - ::features::kDesktopPWAsLinkCapturingWithScopeExtensions)) { + ::features::kPwaNavigationCapturingWithScopeExtensions)) { return provider_->registrar_unsafe().IsUrlInAppExtendedScope(url, app_id); } else { return provider_->registrar_unsafe().IsUrlInAppScope(url, app_id);
diff --git a/chrome/browser/ash/login/lock/screen_locker.cc b/chrome/browser/ash/login/lock/screen_locker.cc index af4b110c..7ebc4840 100644 --- a/chrome/browser/ash/login/lock/screen_locker.cc +++ b/chrome/browser/ash/login/lock/screen_locker.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ash/login/lock/screen_locker.h" +#include <optional> + #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "ash/public/cpp/login_screen.h" @@ -11,6 +13,7 @@ #include "base/command_line.h" #include "base/containers/contains.h" #include "base/functional/bind.h" +#include "base/functional/callback_helpers.h" #include "base/lazy_instance.h" #include "base/location.h" #include "base/memory/weak_ptr.h" @@ -948,8 +951,10 @@ } } -void ScreenLocker::OnPinCanAuthenticate(const AccountId& account_id, - bool can_authenticate) { +void ScreenLocker::OnPinCanAuthenticate( + const AccountId& account_id, + bool can_authenticate, + std::optional<base::Time> available_at) { LoginScreen::Get()->GetModel()->SetPinEnabledForUser(account_id, can_authenticate); }
diff --git a/chrome/browser/ash/login/lock/screen_locker.h b/chrome/browser/ash/login/lock/screen_locker.h index 551606d..f5833985 100644 --- a/chrome/browser/ash/login/lock/screen_locker.h +++ b/chrome/browser/ash/login/lock/screen_locker.h
@@ -6,6 +6,7 @@ #define CHROME_BROWSER_ASH_LOGIN_LOCK_SCREEN_LOCKER_H_ #include <memory> +#include <optional> #include <set> #include <string> #include <vector> @@ -224,7 +225,9 @@ void MaybeDisablePinAndFingerprintFromTimeout(const std::string& source, const AccountId& account_id); - void OnPinCanAuthenticate(const AccountId& account_id, bool can_authenticate); + void OnPinCanAuthenticate(const AccountId& account_id, + bool can_authenticate, + std::optional<base::Time> available_at); void UpdateFingerprintStateForUser(const user_manager::User* user);
diff --git a/chrome/browser/ash/login/lock/views_screen_locker.cc b/chrome/browser/ash/login/lock/views_screen_locker.cc index 72a36a5f..cb679ae 100644 --- a/chrome/browser/ash/login/lock/views_screen_locker.cc +++ b/chrome/browser/ash/login/lock/views_screen_locker.cc
@@ -208,8 +208,10 @@ account_id, enable_challenge_response); } -void ViewsScreenLocker::OnPinCanAuthenticate(const AccountId& account_id, - bool can_authenticate) { +void ViewsScreenLocker::OnPinCanAuthenticate( + const AccountId& account_id, + bool can_authenticate, + std::optional<base::Time> available_at) { LoginScreen::Get()->GetModel()->SetPinEnabledForUser(account_id, can_authenticate); }
diff --git a/chrome/browser/ash/login/lock/views_screen_locker.h b/chrome/browser/ash/login/lock/views_screen_locker.h index a13e0029..db98eb7 100644 --- a/chrome/browser/ash/login/lock/views_screen_locker.h +++ b/chrome/browser/ash/login/lock/views_screen_locker.h
@@ -5,6 +5,7 @@ #ifndef CHROME_BROWSER_ASH_LOGIN_LOCK_VIEWS_SCREEN_LOCKER_H_ #define CHROME_BROWSER_ASH_LOGIN_LOCK_VIEWS_SCREEN_LOCKER_H_ +#include <optional> #include <string> #include "base/functional/callback.h" @@ -75,7 +76,9 @@ bool success); void UpdatePinKeyboardState(const AccountId& account_id); void UpdateChallengeResponseAuthAvailability(const AccountId& account_id); - void OnPinCanAuthenticate(const AccountId& account_id, bool can_authenticate); + void OnPinCanAuthenticate(const AccountId& account_id, + bool can_authenticate, + std::optional<base::Time> available_at); std::unique_ptr<UserSelectionScreen> user_selection_screen_;
diff --git a/chrome/browser/ash/login/quick_unlock/pin_backend.cc b/chrome/browser/ash/login/quick_unlock/pin_backend.cc index f0759b2..bbab1e0 100644 --- a/chrome/browser/ash/login/quick_unlock/pin_backend.cc +++ b/chrome/browser/ash/login/quick_unlock/pin_backend.cc
@@ -4,6 +4,8 @@ #include "chrome/browser/ash/login/quick_unlock/pin_backend.h" +#include <optional> + #include "ash/constants/ash_features.h" #include "base/base64.h" #include "base/functional/bind.h" @@ -11,6 +13,7 @@ #include "base/metrics/histogram_functions.h" #include "base/strings/string_util.h" #include "base/task/single_thread_task_runner.h" +#include "base/time/time.h" #include "chrome/browser/ash/login/quick_unlock/auth_token.h" #include "chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.h" #include "chrome/browser/ash/login/quick_unlock/pin_storage_prefs.h" @@ -50,6 +53,13 @@ FROM_HERE, base::BindOnce(std::move(result), value)); } +void PostResponse(PinBackend::AvailabilityCallback result, + bool enabled, + std::optional<base::Time> available_at) { + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, base::BindOnce(std::move(result), enabled, available_at)); +} + void PostResponse(AuthOperationCallback result, std::unique_ptr<UserContext> user_context, bool success) { @@ -328,11 +338,11 @@ void PinBackend::CanAuthenticate(const AccountId& account_id, Purpose purpose, - BoolCallback result) { + AvailabilityCallback result_callback) { if (resolving_backend_) { on_cryptohome_support_received_.push_back( base::BindOnce(&PinBackend::CanAuthenticate, base::Unretained(this), - account_id, purpose, std::move(result))); + account_id, purpose, std::move(result_callback))); return; } @@ -341,18 +351,20 @@ user_manager::UserManager::Get()->FindUser(account_id); if (!user) { NOTREACHED_IN_MIGRATION() << "CanAuthenticate called with invalid user"; - std::move(result).Run(false); + std::move(result_callback).Run(false, std::nullopt); return; } auto user_context = std::make_unique<UserContext>(*user); cryptohome_backend_->CanAuthenticate(std::move(user_context), purpose, - std::move(result)); + std::move(result_callback)); } else { QuickUnlockStorage* storage = GetPrefsBackend(account_id); - PostResponse(std::move(result), - storage && storage->HasStrongAuth() && - storage->pin_storage_prefs()->IsPinAuthenticationAvailable( - purpose)); + // pref based pin should be immediately available. + PostResponse( + std::move(result_callback), + storage && storage->HasStrongAuth() && + storage->pin_storage_prefs()->IsPinAuthenticationAvailable(purpose), + std::nullopt); } }
diff --git a/chrome/browser/ash/login/quick_unlock/pin_backend.h b/chrome/browser/ash/login/quick_unlock/pin_backend.h index 23f215d..dad435a 100644 --- a/chrome/browser/ash/login/quick_unlock/pin_backend.h +++ b/chrome/browser/ash/login/quick_unlock/pin_backend.h
@@ -5,9 +5,11 @@ #ifndef CHROME_BROWSER_ASH_LOGIN_QUICK_UNLOCK_PIN_BACKEND_H_ #define CHROME_BROWSER_ASH_LOGIN_QUICK_UNLOCK_PIN_BACKEND_H_ +#include <optional> #include <string> #include "base/functional/callback.h" +#include "base/time/time.h" #include "chromeos/ash/components/login/auth/public/auth_callbacks.h" #include "chromeos/ash/components/login/auth/public/key.h" #include "chromeos/ash/services/auth_factor_config/chrome_browser_delegates.h" @@ -28,6 +30,8 @@ class PinBackend : public ash::auth::PinBackendDelegate { public: using BoolCallback = base::OnceCallback<void(bool)>; + using AvailabilityCallback = + base::OnceCallback<void(bool, std::optional<base::Time>)>; // Fetch the PinBackend instance. static PinBackend* GetInstance(); @@ -81,7 +85,7 @@ // restrictions. void CanAuthenticate(const AccountId& account_id, Purpose purpose, - BoolCallback result); + AvailabilityCallback result_callback); // Try to check a pin `key` value for the given user. The `key` must be plain // text and not contain a salt. The `user_context` must not have an
diff --git a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc index 9f4d74e..98235209 100644 --- a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc +++ b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.cc
@@ -4,11 +4,14 @@ #include "chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.h" +#include <optional> + #include "ash/constants/ash_features.h" #include "ash/constants/ash_pref_names.h" #include "base/functional/bind.h" #include "base/logging.h" #include "base/task/single_thread_task_runner.h" +#include "base/time/time.h" #include "chrome/browser/ash/login/quick_unlock/auth_token.h" #include "chrome/browser/ash/login/quick_unlock/pin_backend.h" #include "chrome/browser/ash/login/quick_unlock/pin_salt_storage.h" @@ -34,12 +37,13 @@ using ::cryptohome::KeyLabel; -void CheckCryptohomePinFactor(PinStorageCryptohome::BoolCallback callback, - bool require_unlocked, - std::unique_ptr<UserContext> user_context, - std::optional<AuthenticationError> error) { +void CheckCryptohomePinFactor( + PinStorageCryptohome::AvailabilityCallback callback, + bool require_unlocked, + std::unique_ptr<UserContext> user_context, + std::optional<AuthenticationError> error) { if (error.has_value()) { - std::move(callback).Run(false); + std::move(callback).Run(false, std::nullopt); return; } @@ -47,16 +51,16 @@ const cryptohome::AuthFactor* pin_factor = config.FindFactorByType(cryptohome::AuthFactorType::kPin); if (!pin_factor) { - std::move(callback).Run(false); + std::move(callback).Run(false, std::nullopt); return; } if (require_unlocked && pin_factor->GetPinStatus().IsLockedFactor()) { - std::move(callback).Run(false); + std::move(callback).Run(false, pin_factor->GetPinStatus().AvailableAt()); return; } - std::move(callback).Run(true); + std::move(callback).Run(true, pin_factor->GetPinStatus().AvailableAt()); } // Called after cryptohomed backend is available; used to check if the @@ -164,9 +168,15 @@ void PinStorageCryptohome::IsPinSetInCryptohome( std::unique_ptr<UserContext> user_context, BoolCallback result) { + // Pass the enabled boolean result, ignore the availability timestamp. + auto availability_callback = [](BoolCallback callback, bool enabled, + std::optional<base::Time> available_at) { + std::move(callback).Run(enabled); + }; auth_factor_editor_.GetAuthFactorsConfiguration( std::move(user_context), - base::BindOnce(&CheckCryptohomePinFactor, std::move(result), + base::BindOnce(&CheckCryptohomePinFactor, + base::BindOnce(availability_callback, std::move(result)), false /*require_unlocked*/)); } @@ -243,15 +253,15 @@ void PinStorageCryptohome::CanAuthenticate( std::unique_ptr<UserContext> user_context, Purpose purpose, - BoolCallback result) { + AvailabilityCallback result_callback) { if (IsCryptohomePinDisabledByPolicy(user_context->GetAccountId(), purpose)) { - std::move(result).Run(false); + std::move(result_callback).Run(false, std::nullopt); return; } auth_factor_editor_.GetAuthFactorsConfiguration( std::move(user_context), - base::BindOnce(&CheckCryptohomePinFactor, std::move(result), + base::BindOnce(&CheckCryptohomePinFactor, std::move(result_callback), true /*require_unlocked*/)); }
diff --git a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.h b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.h index ff9bbea..661de15 100644 --- a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.h +++ b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome.h
@@ -12,6 +12,7 @@ #include "base/functional/callback.h" #include "base/memory/weak_ptr.h" +#include "base/time/time.h" #include "chrome/browser/ash/login/quick_unlock/pin_salt_storage.h" #include "chromeos/ash/components/login/auth/auth_factor_editor.h" #include "chromeos/ash/components/login/auth/auth_performer.h" @@ -30,6 +31,8 @@ class PinStorageCryptohome { public: using BoolCallback = base::OnceCallback<void(bool)>; + using AvailabilityCallback = + base::OnceCallback<void(bool, std::optional<base::Time>)>; // Check to see if the cryptohome implementation can store PINs. static void IsSupported(BoolCallback result); @@ -59,7 +62,7 @@ AuthOperationCallback callback); void CanAuthenticate(std::unique_ptr<UserContext> user_context, Purpose purpose, - BoolCallback result); + AvailabilityCallback result_callback); void TryAuthenticate(std::unique_ptr<UserContext> user_context, const Key& key, Purpose purpose,
diff --git a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc index 57599dd4..fddb332 100644 --- a/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc +++ b/chrome/browser/ash/login/quick_unlock/pin_storage_cryptohome_unittest.cc
@@ -9,6 +9,7 @@ #include <vector> #include "base/functional/bind.h" +#include "base/functional/callback_helpers.h" #include "base/logging.h" #include "base/run_loop.h" #include "chrome/browser/ash/login/quick_unlock/fake_pin_salt_storage.h" @@ -99,7 +100,8 @@ storage_->CanAuthenticate( std::make_unique<UserContext>(*user_context_), Purpose::kAny, base::BindOnce( - [](base::OnceClosure closure, bool* res, bool can_auth) { + [](base::OnceClosure closure, bool* res, bool can_auth, + std::optional<base::Time> available_at) { *res = can_auth; std::move(closure).Run(); },
diff --git a/chrome/browser/ash/login/screens/perks_discovery_screen.cc b/chrome/browser/ash/login/screens/perks_discovery_screen.cc index 459276a..026bc347 100644 --- a/chrome/browser/ash/login/screens/perks_discovery_screen.cc +++ b/chrome/browser/ash/login/screens/perks_discovery_screen.cc
@@ -20,8 +20,15 @@ constexpr const char kUserActionFinish[] = "finished"; constexpr const char kUserActionLoaded[] = "loaded"; -constexpr const char kPerkGamgeeId[] = "Gamgee"; -constexpr const char kPerkStandardGamgeeId[] = "StandardGamgee"; + +// Campaign ids from +// google3/chromeos/growth/campaigns/stop_gap_campaigns/stop_gap_campaigns_enums.ts +constexpr const int kPerkGamgeeId100 = 49; +constexpr const int kPerkGamgeeIdExperiment = 33; +constexpr const int kPerkGamgeeIdControl = 38; +constexpr const int kPerkStandardGamgeeId100 = 48; +constexpr const int kPerkStandardGamgeeIdExperiment = 32; +constexpr const int kPerkStandardGamgeeIdControl = 37; // Current max amount of perks we should get from the server. constexpr const int kMaxPerksFetched = 10; @@ -235,6 +242,17 @@ campaign_id_ = growth::GetCampaignId(campaign).value(); group_id_ = growth::GetCampaignGroupId(campaign); + if (campaign_id_ == kPerkGamgeeId100 || + campaign_id_ == kPerkGamgeeIdControl || + campaign_id_ == kPerkGamgeeIdExperiment || + campaign_id_ == kPerkStandardGamgeeId100 || + campaign_id_ == kPerkStandardGamgeeIdExperiment || + campaign_id_ == kPerkStandardGamgeeIdControl) { + // Mark the gamgee perk screen as shown for this user. + ProfileManager::GetActiveUserProfile()->GetPrefs()->SetBoolean( + prefs::kOobePerksDiscoveryGamgeeShown, true); + } + auto* payload = GetPayloadBySlot(campaign, growth::Slot::kOobePerkDiscovery); if (!payload) { LOG(ERROR) << "Payload object is null. Failed to retrieve payload for " @@ -248,16 +266,6 @@ if (view_ && !perks_data_.empty()) { view_->SetPerksData(perks_data_); - auto perk = std::find_if(perks_data_.cbegin(), perks_data_.cend(), - [&](const SinglePerkDiscoveryPayload& perk_data) { - return ((perk_data.id == kPerkGamgeeId) || - (perk_data.id == kPerkStandardGamgeeId)); - }); - if (perk != perks_data_.end()) { - // Mark the gamgee perk screen as shown for this user. - PrefService* prefs = ProfileManager::GetActiveUserProfile()->GetPrefs(); - prefs->SetBoolean(prefs::kOobePerksDiscoveryGamgeeShown, true); - } return; }
diff --git a/chrome/browser/ash/login/ui/login_display_host_mojo.cc b/chrome/browser/ash/login/ui/login_display_host_mojo.cc index 31919540..1cbe098 100644 --- a/chrome/browser/ash/login/ui/login_display_host_mojo.cc +++ b/chrome/browser/ash/login/ui/login_display_host_mojo.cc
@@ -27,6 +27,7 @@ #include "base/feature_list.h" #include "base/functional/bind.h" #include "base/functional/callback.h" +#include "base/functional/callback_helpers.h" #include "base/location.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" @@ -161,7 +162,8 @@ // user's cryptohome. So just pass an arbitrary purpose here. account_id, quick_unlock::Purpose::kAny, base::BindOnce( - [](const AccountId& account_id, bool can_authenticate) { + [](const AccountId& account_id, bool can_authenticate, + std::optional<base::Time> available_at) { if (!LoginScreen::Get() || !LoginScreen::Get()->GetModel()) { return; }
diff --git a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManager.java b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManager.java index bc1f0cd..55bc0dc 100644 --- a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManager.java +++ b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManager.java
@@ -13,8 +13,6 @@ import org.chromium.base.Log; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.Supplier; -import org.chromium.base.task.PostTask; -import org.chromium.base.task.TaskTraits; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.share.ChromeShareExtras; import org.chromium.chrome.browser.share.ChromeShareExtras.DetailedContentType; @@ -230,28 +228,23 @@ Callback<DataSharingService.GroupDataOrFailureOutcome> createGroupCallback = (result) -> { - // TODO: SDK delegeta should run results on UI thread. - PostTask.postTask( - TaskTraits.UI_DEFAULT, - () -> { - if (result.actionFailure != PeopleGroupActionFailure.UNKNOWN - || result.groupData == null) { - Log.e(TAG, "Group creation failed " + result.actionFailure); - createGroupFinishedCallback.onResult(false); - } else { - tabGroupService.makeTabGroupShared( - localTabGroupId, result.groupData.groupToken.groupId); - createGroupFinishedCallback.onResult(true); + if (result.actionFailure != PeopleGroupActionFailure.UNKNOWN + || result.groupData == null) { + Log.e(TAG, "Group creation failed " + result.actionFailure); + createGroupFinishedCallback.onResult(false); + } else { + tabGroupService.makeTabGroupShared( + localTabGroupId, result.groupData.groupToken.groupId); + createGroupFinishedCallback.onResult(true); - showShareSheet(result.groupData); - } - mBottomSheetControllerSupplier - .get() - .hideContent( - bottomSheetContent, - /* animate= */ false, - StateChangeReason.INTERACTION_COMPLETE); - }); + showShareSheet(result.groupData); + } + mBottomSheetControllerSupplier + .get() + .hideContent( + bottomSheetContent, + /* animate= */ false, + StateChangeReason.INTERACTION_COMPLETE); }; Callback<List<String>> pickerCallback = @@ -322,7 +315,7 @@ */ public void showRecentActivity(String collaborationId) {} - private BottomSheetContent showBottomSheet( + protected BottomSheetContent showBottomSheet( Context context, Callback<Integer> onClosedCallback) { ViewGroup bottomSheetView = (ViewGroup)
diff --git a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManagerUnitTest.java b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManagerUnitTest.java index d8e687d0..a85e09b 100644 --- a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManagerUnitTest.java +++ b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/DataSharingTabManagerUnitTest.java
@@ -6,6 +6,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; @@ -20,35 +21,51 @@ import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.Mock; +import org.mockito.MockitoAnnotations; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; +import org.chromium.base.Callback; import org.chromium.base.Token; import org.chromium.base.supplier.ObservableSupplier; import org.chromium.base.supplier.ObservableSupplierImpl; import org.chromium.base.supplier.Supplier; import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.share.ShareDelegate; import org.chromium.chrome.browser.tab_group_sync.TabGroupSyncServiceFactory; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; import org.chromium.components.data_sharing.DataSharingService; +import org.chromium.components.data_sharing.DataSharingService.GroupDataOrFailureOutcome; import org.chromium.components.data_sharing.DataSharingUIDelegate; +import org.chromium.components.data_sharing.GroupData; +import org.chromium.components.data_sharing.GroupMember; import org.chromium.components.data_sharing.GroupToken; import org.chromium.components.data_sharing.ParseURLStatus; +import org.chromium.components.data_sharing.PeopleGroupActionFailure; +import org.chromium.components.data_sharing.member_role.MemberRole; +import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils; +import org.chromium.components.dom_distiller.core.DomDistillerUrlUtilsJni; import org.chromium.components.tab_group_sync.LocalTabGroupId; import org.chromium.components.tab_group_sync.SavedTabGroup; import org.chromium.components.tab_group_sync.SavedTabGroupTab; import org.chromium.components.tab_group_sync.TabGroupSyncService; import org.chromium.ui.base.TestActivity; import org.chromium.ui.base.WindowAndroid; +import org.chromium.url.GURL; + +import java.util.Arrays; +import java.util.List; /** Unit test for {@link DataSharingTabManager} */ @RunWith(BaseRobolectricTestRunner.class) public class DataSharingTabManagerUnitTest { @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Rule public JniMocker jniMocker = new JniMocker(); @Rule public ActivityScenarioRule<TestActivity> mActivityScenarioRule = @@ -58,6 +75,10 @@ private static final LocalTabGroupId LOCAL_ID = new LocalTabGroupId(Token.createRandom()); private static final Integer TAB_ID = 123; private static final String ACCESS_TOKEN = "access_token"; + private static final String TEST_GROUP_DISPLAY_NAME = "Test Group"; + private static final String GAIA_ID = "GAIA_ID"; + private static final String EMAIL = "fake@gmail.com"; + private static final GURL TEST_URL = new GURL("https://www.example.com/"); @Mock private TabGroupSyncService mTabGroupSyncService; @Mock private DataSharingService mDataSharingService; @@ -65,8 +86,11 @@ @Mock private DataSharingTabSwitcherDelegate mDataSharingTabSwitcherDelegate; @Mock private Profile mProfile; @Mock private BottomSheetController mBottomSheetController; - @Mock private ObservableSupplier<ShareDelegate> mShareDelegateSupplier; @Mock private WindowAndroid mWindowAndroid; + @Mock private BottomSheetContent mBottomSheetContent; + @Mock private ShareDelegate mShareDelegate; + @Mock private DomDistillerUrlUtils.Natives mDistillerUrlUtilsJniMock; + @Mock Callback<Boolean> mCreateGroupFinishedCallback; @Captor private ArgumentCaptor<BottomSheetObserver> mBottomSheetObserverCaptor; @@ -76,18 +100,23 @@ @Before public void setUp() { + MockitoAnnotations.initMocks(this); + jniMocker.mock(DomDistillerUrlUtilsJni.TEST_HOOKS, mDistillerUrlUtilsJniMock); + DataSharingServiceFactory.setForTesting(mDataSharingService); DataSharingServiceFactory.setDataSharingUIDelegateForTesting(mDataSharingUIDelegate); TabGroupSyncServiceFactory.setForTesting(mTabGroupSyncService); ObservableSupplier<Profile> profileSupplier = new ObservableSupplierImpl<Profile>(mProfile); Supplier<BottomSheetController> bottomSheetControllerSupplier = new ObservableSupplierImpl<BottomSheetController>(mBottomSheetController); + ObservableSupplier<ShareDelegate> shareDelegateSupplier = + new ObservableSupplierImpl<ShareDelegate>(mShareDelegate); mDataSharingTabManager = new DataSharingTabManager( mDataSharingTabSwitcherDelegate, profileSupplier, bottomSheetControllerSupplier, - mShareDelegateSupplier, + shareDelegateSupplier, mWindowAndroid); mSavedTabGroup = new SavedTabGroup(); @@ -161,4 +190,90 @@ /* config= */ any()); mBottomSheetObserverCaptor.getValue().onSheetClosed(StateChangeReason.SWIPE); } + + @Test + public void testCreateFlowWithExistingGroup() { + doReturn(mProfile).when(mProfile).getOriginalProfile(); + doReturn(mSavedTabGroup).when(mTabGroupSyncService).getGroup(LOCAL_ID); + GroupMember groupMember = + new GroupMember( + GAIA_ID, + /* displayName= */ null, + EMAIL, + MemberRole.OWNER, + /* avatarUrl= */ null); + GroupMember[] groupMemberArray = new GroupMember[] {groupMember}; + GroupData groupData = + new GroupData(GROUP_ID, TEST_GROUP_DISPLAY_NAME, groupMemberArray, ACCESS_TOKEN); + GroupDataOrFailureOutcome outcome = + new GroupDataOrFailureOutcome(groupData, PeopleGroupActionFailure.UNKNOWN); + doAnswer( + invocation -> { + // Capture the callback passed to ensureGroupVisibility + Callback<DataSharingService.GroupDataOrFailureOutcome> callback = + invocation.getArgument(1); + callback.onResult(outcome); + return null; + }) + .when(mDataSharingService) + .ensureGroupVisibility(any(), any()); + doReturn(TEST_URL).when(mDataSharingService).getDataSharingURL(eq(groupData)); + doReturn(TEST_URL) + .when(mDistillerUrlUtilsJniMock) + .getOriginalUrlFromDistillerUrl(any(String.class)); + mDataSharingTabManager.createGroupFlow(null, TEST_GROUP_DISPLAY_NAME, LOCAL_ID, null); + // Verifying showShareSheet() method is called. + verify(mDataSharingService).getDataSharingURL(eq(groupData)); + verify(mShareDelegate).share(any(), any(), eq(ShareDelegate.ShareOrigin.TAB_GROUP)); + } + + @Test + public void testCreateFlowWithNewTabGroup() { + doReturn(mProfile).when(mProfile).getOriginalProfile(); + doReturn(null).when(mTabGroupSyncService).getGroup(LOCAL_ID); + + GroupMember groupMember = + new GroupMember( + GAIA_ID, + /* displayName= */ null, + EMAIL, + MemberRole.OWNER, + /* avatarUrl= */ null); + GroupMember[] groupMemberArray = new GroupMember[] {groupMember}; + GroupData groupData = + new GroupData(GROUP_ID, TEST_GROUP_DISPLAY_NAME, groupMemberArray, ACCESS_TOKEN); + GroupDataOrFailureOutcome outcome = + new GroupDataOrFailureOutcome(groupData, PeopleGroupActionFailure.UNKNOWN); + doAnswer( + invocation -> { + // Capture the callback passed to createGroup + Callback<DataSharingService.GroupDataOrFailureOutcome> callback = + invocation.getArgument(1); + callback.onResult(outcome); + return null; + }) + .when(mDataSharingService) + .createGroup(any(), any()); + + doReturn(TEST_URL).when(mDataSharingService).getDataSharingURL(eq(groupData)); + doReturn(TEST_URL) + .when(mDistillerUrlUtilsJniMock) + .getOriginalUrlFromDistillerUrl(any(String.class)); + + mDataSharingTabManager.createGroupFlow( + mActivity, TEST_GROUP_DISPLAY_NAME, LOCAL_ID, mCreateGroupFinishedCallback); + + ArgumentCaptor<MemberPickerListenerImpl> memberPickerListenerCaptor = + ArgumentCaptor.forClass(MemberPickerListenerImpl.class); + verify(mDataSharingUIDelegate) + .showMemberPicker(any(), any(), memberPickerListenerCaptor.capture(), any()); + Callback<List<String>> capturedPickerCallback = + memberPickerListenerCaptor.getValue().getCallback(); + List<String> selectedEmails = Arrays.asList(EMAIL); + capturedPickerCallback.onResult(selectedEmails); + + // Verifying DataSharingService createGroup API is called. + verify(mDataSharingService).createGroup(eq(TEST_GROUP_DISPLAY_NAME), any(Callback.class)); + verify(mShareDelegate).share(any(), any(), eq(ShareDelegate.ShareOrigin.TAB_GROUP)); + } }
diff --git a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/MemberPickerListenerImpl.java b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/MemberPickerListenerImpl.java index a0e738c..bdf2e20 100644 --- a/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/MemberPickerListenerImpl.java +++ b/chrome/browser/data_sharing/android/java/src/org/chromium/chrome/browser/data_sharing/MemberPickerListenerImpl.java
@@ -20,6 +20,10 @@ mCallback = callback; } + public Callback<List<String>> getCallback() { + return mCallback; + } + @Override public void onSelectionDone(List<String> selectedMemberIds, List<String> emails) { int count = 0;
diff --git a/chrome/browser/data_sharing/desktop/data_sharing_ui_delegate_desktop.cc b/chrome/browser/data_sharing/desktop/data_sharing_ui_delegate_desktop.cc index b60bc88c..af6555a6 100644 --- a/chrome/browser/data_sharing/desktop/data_sharing_ui_delegate_desktop.cc +++ b/chrome/browser/data_sharing/desktop/data_sharing_ui_delegate_desktop.cc
@@ -4,9 +4,11 @@ #include "chrome/browser/data_sharing/desktop/data_sharing_ui_delegate_desktop.h" +#include "chrome/browser/data_sharing/data_sharing_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_finder.h" #include "chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.h" +#include "components/data_sharing/public/data_sharing_service.h" #include "url/gurl.h" namespace data_sharing { @@ -17,13 +19,18 @@ DataSharingUIDelegateDesktop::~DataSharingUIDelegateDesktop() = default; void DataSharingUIDelegateDesktop::HandleShareURLIntercepted(const GURL& url) { + DataSharingService* const service = + DataSharingServiceFactory::GetForProfile(profile_); + const data_sharing::DataSharingService::ParseURLResult token = + service->ParseDataSharingURL(url); + if (!token->IsValid()) { + return; + } Browser* browser = chrome::FindLastActiveWithProfile(profile_); if (browser) { - // Placeholder implementation to simply show the UI sharing bubble. - // TODO(b/347754188): Start the receive flow. DataSharingBubbleController::GetOrCreateForBrowser( chrome::FindLastActiveWithProfile(profile_)) - ->Show(); + ->Show(token.value()); } }
diff --git a/chrome/browser/digital_credentials/digital_identity_bluetooth_adapter_status_change_observer.h b/chrome/browser/digital_credentials/digital_identity_bluetooth_adapter_status_change_observer.h deleted file mode 100644 index 9cd646e..0000000 --- a/chrome/browser/digital_credentials/digital_identity_bluetooth_adapter_status_change_observer.h +++ /dev/null
@@ -1,22 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_BLUETOOTH_ADAPTER_STATUS_CHANGE_OBSERVER_H_ -#define CHROME_BROWSER_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_BLUETOOTH_ADAPTER_STATUS_CHANGE_OBSERVER_H_ - -#include "base/observer_list_types.h" -#include "device/fido/fido_request_handler_base.h" - -// Observer for observing the bluetooth adapter's status. -class DigitalIdentityBluetoothAdapterStatusChangeObserver - : public base::CheckedObserver { - public: - virtual void OnBluetoothAdapterStatusChanged( - device::FidoRequestHandlerBase::BleStatus ble_status) = 0; - - protected: - ~DigitalIdentityBluetoothAdapterStatusChangeObserver() override = default; -}; - -#endif // CHROME_BROWSER_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_BLUETOOTH_ADAPTER_STATUS_CHANGE_OBSERVER_H_
diff --git a/chrome/browser/digital_credentials/digital_identity_fido_handler_observer.cc b/chrome/browser/digital_credentials/digital_identity_fido_handler_observer.cc deleted file mode 100644 index c521d740..0000000 --- a/chrome/browser/digital_credentials/digital_identity_fido_handler_observer.cc +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/digital_credentials/digital_identity_fido_handler_observer.h" - -#include "base/notreached.h" - -using BleStatus = device::FidoRequestHandlerBase::BleStatus; - -DigitalIdentityFidoHandlerObserver::DigitalIdentityFidoHandlerObserver( - ReadyToShowUiCallback ready_to_show_ui_callback) - : ready_to_show_ui_callback_(std::move(ready_to_show_ui_callback)) {} - -DigitalIdentityFidoHandlerObserver::~DigitalIdentityFidoHandlerObserver() = - default; - -void DigitalIdentityFidoHandlerObserver:: - AddBluetoothAdapterStatusChangeObserver( - DigitalIdentityBluetoothAdapterStatusChangeObserver* observer) { - bluetooth_observers_.AddObserver(observer); -} - -void DigitalIdentityFidoHandlerObserver:: - RemoveBluetoothAdapterStatusChangeObserver( - DigitalIdentityBluetoothAdapterStatusChangeObserver* observer) { - bluetooth_observers_.RemoveObserver(observer); -} - -void DigitalIdentityFidoHandlerObserver::OnTransportAvailabilityEnumerated( - device::FidoRequestHandlerBase::TransportAvailabilityInfo data) { - if (!ready_to_show_ui_callback_) { - return; - } - std::move(ready_to_show_ui_callback_).Run(data); -} - -bool DigitalIdentityFidoHandlerObserver::EmbedderControlsAuthenticatorDispatch( - const device::FidoAuthenticator& authenticator) { - return false; -} - -void DigitalIdentityFidoHandlerObserver::BluetoothAdapterStatusChanged( - BleStatus ble_status) { - for (auto& observer : bluetooth_observers_) { - observer.OnBluetoothAdapterStatusChanged(ble_status); - } -} - -void DigitalIdentityFidoHandlerObserver::FidoAuthenticatorAdded( - const device::FidoAuthenticator& authenticator) {} - -void DigitalIdentityFidoHandlerObserver::FidoAuthenticatorRemoved( - std::string_view device_id) {} - -bool DigitalIdentityFidoHandlerObserver::SupportsPIN() const { - return false; -} - -void DigitalIdentityFidoHandlerObserver::CollectPIN( - CollectPINOptions options, - base::OnceCallback<void(std::u16string)> provide_pin_cb) { - NOTREACHED(); -} - -void DigitalIdentityFidoHandlerObserver::FinishCollectToken() {} - -void DigitalIdentityFidoHandlerObserver::StartBioEnrollment( - base::OnceClosure next_callback) {} - -void DigitalIdentityFidoHandlerObserver::OnSampleCollected( - int bio_samples_remaining) {} - -void DigitalIdentityFidoHandlerObserver::OnRetryUserVerification(int attempts) { -}
diff --git a/chrome/browser/digital_credentials/digital_identity_fido_handler_observer.h b/chrome/browser/digital_credentials/digital_identity_fido_handler_observer.h deleted file mode 100644 index 5d0d48e4..0000000 --- a/chrome/browser/digital_credentials/digital_identity_fido_handler_observer.h +++ /dev/null
@@ -1,59 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef CHROME_BROWSER_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_FIDO_HANDLER_OBSERVER_H_ -#define CHROME_BROWSER_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_FIDO_HANDLER_OBSERVER_H_ - -#include "base/observer_list.h" -#include "chrome/browser/digital_credentials/digital_identity_bluetooth_adapter_status_change_observer.h" -#include "chrome/browser/ui/browser_commands.h" -#include "device/fido/fido_request_handler_base.h" - -// Registers observers for bluetooth powered-on state. -class DigitalIdentityFidoHandlerObserver - : public device::FidoRequestHandlerBase::Observer { - public: - using ReadyToShowUiCallback = base::OnceCallback<void( - const device::FidoRequestHandlerBase::TransportAvailabilityInfo&)>; - - explicit DigitalIdentityFidoHandlerObserver( - ReadyToShowUiCallback ready_to_show_ui_callback); - ~DigitalIdentityFidoHandlerObserver() override; - - DigitalIdentityFidoHandlerObserver( - const DigitalIdentityFidoHandlerObserver&) = delete; - DigitalIdentityFidoHandlerObserver& operator=( - const DigitalIdentityFidoHandlerObserver&) = delete; - - void AddBluetoothAdapterStatusChangeObserver( - DigitalIdentityBluetoothAdapterStatusChangeObserver* observer); - void RemoveBluetoothAdapterStatusChangeObserver( - DigitalIdentityBluetoothAdapterStatusChangeObserver* observer); - - // device::FidoRequestHandlerBase::Observer: - void OnTransportAvailabilityEnumerated( - device::FidoRequestHandlerBase::TransportAvailabilityInfo data) override; - bool EmbedderControlsAuthenticatorDispatch( - const device::FidoAuthenticator& authenticator) override; - void BluetoothAdapterStatusChanged( - device::FidoRequestHandlerBase::BleStatus ble_status) override; - void FidoAuthenticatorAdded( - const device::FidoAuthenticator& authenticator) override; - void FidoAuthenticatorRemoved(std::string_view device_id) override; - bool SupportsPIN() const override; - void CollectPIN( - CollectPINOptions options, - base::OnceCallback<void(std::u16string)> provide_pin_cb) override; - void FinishCollectToken() override; - void StartBioEnrollment(base::OnceClosure next_callback) override; - void OnSampleCollected(int bio_samples_remaining) override; - void OnRetryUserVerification(int attempts) override; - - private: - ReadyToShowUiCallback ready_to_show_ui_callback_; - base::ObserverList<DigitalIdentityBluetoothAdapterStatusChangeObserver> - bluetooth_observers_; -}; - -#endif // CHROME_BROWSER_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_FIDO_HANDLER_OBSERVER_H_
diff --git a/chrome/browser/digital_credentials/digital_identity_provider_android.cc b/chrome/browser/digital_credentials/digital_identity_provider_android.cc index b9d4b1c..e847602e 100644 --- a/chrome/browser/digital_credentials/digital_identity_provider_android.cc +++ b/chrome/browser/digital_credentials/digital_identity_provider_android.cc
@@ -8,6 +8,7 @@ #include "base/android/jni_android.h" #include "base/android/jni_string.h" +#include "base/json/json_writer.h" #include "base/values.h" #include "chrome/browser/digital_credentials/digital_identity_low_risk_origins.h" #include "chrome/browser/ui/digital_credentials/digital_identity_safety_interstitial_bridge_android.h" @@ -77,13 +78,15 @@ void DigitalIdentityProviderAndroid::Request(content::WebContents* web_contents, const url::Origin& origin, - const std::string& request, + const base::Value request, DigitalIdentityCallback callback) { callback_ = std::move(callback); JNIEnv* env = AttachCurrentThread(); ScopedJavaLocalRef<jstring> j_origin = ConvertUTF8ToJavaString(env, origin.Serialize()); - ScopedJavaLocalRef<jstring> j_request = ConvertUTF8ToJavaString(env, request); + std::optional<std::string> request_str = base::WriteJson(request); + ScopedJavaLocalRef<jstring> j_request = + ConvertUTF8ToJavaString(env, *request_str); base::android::ScopedJavaLocalRef<jobject> j_window = nullptr;
diff --git a/chrome/browser/digital_credentials/digital_identity_provider_android.h b/chrome/browser/digital_credentials/digital_identity_provider_android.h index 0b182f0..94cf5ff 100644 --- a/chrome/browser/digital_credentials/digital_identity_provider_android.h +++ b/chrome/browser/digital_credentials/digital_identity_provider_android.h
@@ -45,7 +45,7 @@ DigitalIdentityInterstitialCallback callback) override; void Request(content::WebContents* web_contents, const url::Origin& origin, - const std::string& request, + const base::Value request, DigitalIdentityCallback callback) override; private:
diff --git a/chrome/browser/digital_credentials/digital_identity_provider_desktop.cc b/chrome/browser/digital_credentials/digital_identity_provider_desktop.cc index 72fcedd2..1c888ed 100644 --- a/chrome/browser/digital_credentials/digital_identity_provider_desktop.cc +++ b/chrome/browser/digital_credentials/digital_identity_provider_desktop.cc
@@ -7,7 +7,8 @@ #include <memory> #include "base/containers/span.h" -#include "chrome/browser/digital_credentials/digital_identity_fido_handler_observer.h" +#include "base/functional/overloaded.h" +#include "base/json/json_writer.h" #include "chrome/browser/digital_credentials/digital_identity_low_risk_origins.h" #include "chrome/browser/net/system_network_context_manager.h" #include "chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.h" @@ -17,6 +18,7 @@ #include "components/constrained_window/constrained_window_views.h" #include "components/qr_code_generator/bitmap_generator.h" #include "components/url_formatter/elide_url.h" +#include "content/public/browser/digital_credentials_cross_device.h" #include "content/public/browser/digital_identity_provider.h" #include "content/public/browser/web_contents.h" #include "crypto/random.h" @@ -31,8 +33,6 @@ namespace { -using BleStatus = device::FidoRequestHandlerBase::BleStatus; - // Smaller than DistanceMetric::DISTANCE_MODAL_DIALOG_PREFERRED_WIDTH. const int kQrCodeSize = 240; @@ -40,8 +40,14 @@ content::DigitalIdentityProvider::DigitalIdentityInterstitialAbortCallback; using RequestStatusForMetrics = content::DigitalIdentityProvider::RequestStatusForMetrics; -using TransportAvailabilityInfo = - device::FidoRequestHandlerBase::TransportAvailabilityInfo; +using content::digital_credentials::cross_device::Error; +using content::digital_credentials::cross_device::Event; +using content::digital_credentials::cross_device::ProtocolError; +using content::digital_credentials::cross_device::RemoteError; +using content::digital_credentials::cross_device::Response; +using content::digital_credentials::cross_device::SystemError; +using content::digital_credentials::cross_device::SystemEvent; +using content::digital_credentials::cross_device::Transaction; void RunDigitalIdentityCallback( std::unique_ptr<DigitalIdentitySafetyInterstitialControllerDesktop> @@ -75,13 +81,7 @@ DigitalIdentityProviderDesktop::DigitalIdentityProviderDesktop() = default; -DigitalIdentityProviderDesktop::~DigitalIdentityProviderDesktop() { - // Destroy members with raw_ptrs to `request_handler_observer_`. - bluetooth_manual_dialog_controller_.reset(); - request_handler_.reset(); - - request_handler_observer_.reset(); -} +DigitalIdentityProviderDesktop::~DigitalIdentityProviderDesktop() = default; bool DigitalIdentityProviderDesktop::IsLowRiskOrigin( const url::Origin& to_check) const { @@ -105,41 +105,94 @@ void DigitalIdentityProviderDesktop::Request(content::WebContents* web_contents, const url::Origin& rp_origin, - const std::string& request, + base::Value request, DigitalIdentityCallback callback) { web_contents_ = web_contents->GetWeakPtr(); rp_origin_ = rp_origin; callback_ = std::move(callback); - const auto fido_request_type = device::FidoRequestType::kGetAssertion; std::array<uint8_t, device::cablev2::kQRKeySize> qr_generator_key; crypto::RandBytes(qr_generator_key); - discovery_factory_ = std::make_unique<device::FidoDiscoveryFactory>(); - discovery_factory_->set_cable_data(fido_request_type, {}, qr_generator_key); - discovery_factory_->set_network_context_factory(base::BindRepeating([]() { - return SystemNetworkContextManager::GetInstance()->GetContext(); - })); + transaction_ = Transaction::New( + rp_origin, std::move(request), qr_generator_key, + base::BindRepeating([]() { + return SystemNetworkContextManager::GetInstance()->GetContext(); + }), + base::BindRepeating(&DigitalIdentityProviderDesktop::OnEvent, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&DigitalIdentityProviderDesktop::OnFinished, + weak_ptr_factory_.GetWeakPtr())); - qr_url_ = device::cablev2::qr::Encode(qr_generator_key, fido_request_type); - - request_handler_ = std::make_unique<device::DigitalIdentityRequestHandler>( - discovery_factory_.get()); - request_handler_observer_ = - std::make_unique<DigitalIdentityFidoHandlerObserver>( - base::BindOnce(&DigitalIdentityProviderDesktop::OnReadyToShowUi, - weak_ptr_factory_.GetWeakPtr())); - request_handler_->set_observer(request_handler_observer_.get()); + qr_url_ = device::cablev2::qr::Encode( + qr_generator_key, device::cablev2::CredentialRequestType::kPresentation); } -void DigitalIdentityProviderDesktop::OnReadyToShowUi( - const TransportAvailabilityInfo& availability_info) { - if (availability_info.ble_status == BleStatus::kOn) { - ShowQrCodeDialog(); +void DigitalIdentityProviderDesktop::OnEvent(Event event) { + absl::visit(base::Overloaded{ + [this](SystemEvent event) { + switch (event) { + case SystemEvent::kBluetoothNotPowered: + ShowBluetoothManualTurnOnDialog(); + break; + case SystemEvent::kNeedPermission: + // The user is being asked for Bluetooth permission by + // the system. Nothing for Chrome UI to do. + break; + case SystemEvent::kReady: + bluetooth_manual_dialog_controller_.reset(); + ShowQrCodeDialog(); + break; + } + }, + [](device::cablev2::Event event) { + // caBLE events notify when the user has started the + // transaction on their phone. The desktop UI could update + // at this point to instruct the user to complete the action + // there. + }, + }, + event); +} + +void DigitalIdentityProviderDesktop::OnFinished( + base::expected<Response, Error> result) { + if (result.has_value()) { + std::string encoded_result = + base::WriteJsonWithOptions(result.value().value(), + base::JSONWriter::OPTIONS_PRETTY_PRINT) + .value_or(""); + std::move(callback_).Run(std::move(encoded_result)); return; } - ShowBluetoothManualTurnOnDialog(); + absl::visit( + base::Overloaded{ + [this](SystemError error) { + EndRequestWithError(RequestStatusForMetrics::kErrorOther); + }, + [this](ProtocolError error) { + EndRequestWithError(RequestStatusForMetrics::kErrorOther); + }, + [this](RemoteError error) { + switch (error) { + case RemoteError::kNoCredential: + EndRequestWithError( + RequestStatusForMetrics::kErrorNoCredential); + break; + case RemoteError::kUserCanceled: + EndRequestWithError( + RequestStatusForMetrics::kErrorUserDeclined); + break; + case RemoteError::kDeviceAborted: + EndRequestWithError(RequestStatusForMetrics::kErrorAborted); + break; + case RemoteError::kOther: + EndRequestWithError(RequestStatusForMetrics::kErrorOther); + break; + } + }}, + result.error()); } DigitalIdentityMultiStepDialog* @@ -158,7 +211,7 @@ url_formatter::FormatOriginForSecurityDisplay( rp_origin_, url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); EnsureDialogCreated()->TryShow( - /*ok_button=*/std::nullopt, base::OnceClosure(), + /*accept_button=*/std::nullopt, base::OnceClosure(), ui::DialogModel::Button::Params(), base::BindOnce(&DigitalIdentityProviderDesktop::OnCanceled, weak_ptr_factory_.GetWeakPtr()), @@ -168,26 +221,31 @@ void DigitalIdentityProviderDesktop::ShowBluetoothManualTurnOnDialog() { bluetooth_manual_dialog_controller_ = std::make_unique<DigitalIdentityBluetoothManualDialogController>( - EnsureDialogCreated(), request_handler_observer_.get()); + EnsureDialogCreated()); bluetooth_manual_dialog_controller_->Show( - base::BindRepeating(&DigitalIdentityProviderDesktop::OnBluetoothTurnedOn, - weak_ptr_factory_.GetWeakPtr()), - base::BindRepeating(&DigitalIdentityProviderDesktop::OnCanceled, - weak_ptr_factory_.GetWeakPtr())); + base::BindOnce( + &DigitalIdentityProviderDesktop::OnUserRequestedBluetoothPowerOn, + weak_ptr_factory_.GetWeakPtr()), + base::BindOnce(&DigitalIdentityProviderDesktop::OnCanceled, + weak_ptr_factory_.GetWeakPtr())); } -void DigitalIdentityProviderDesktop::OnBluetoothTurnedOn() { - bluetooth_manual_dialog_controller_.reset(); - ShowQrCodeDialog(); +void DigitalIdentityProviderDesktop::OnUserRequestedBluetoothPowerOn() { + transaction_->PowerBluetoothAdapter(); } void DigitalIdentityProviderDesktop::OnCanceled() { + EndRequestWithError(RequestStatusForMetrics::kErrorOther); +} + +void DigitalIdentityProviderDesktop::EndRequestWithError( + RequestStatusForMetrics status) { if (callback_.is_null()) { return; } bluetooth_manual_dialog_controller_.reset(); - dialog_ = nullptr; - std::move(callback_).Run( - base::unexpected(RequestStatusForMetrics::kErrorOther)); + dialog_.reset(); + + std::move(callback_).Run(base::unexpected(status)); }
diff --git a/chrome/browser/digital_credentials/digital_identity_provider_desktop.h b/chrome/browser/digital_credentials/digital_identity_provider_desktop.h index d2c6571..a3ae239 100644 --- a/chrome/browser/digital_credentials/digital_identity_provider_desktop.h +++ b/chrome/browser/digital_credentials/digital_identity_provider_desktop.h
@@ -6,18 +6,19 @@ #define CHROME_BROWSER_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_PROVIDER_DESKTOP_H_ #include "base/memory/weak_ptr.h" -#include "chrome/browser/digital_credentials/digital_identity_fido_handler_observer.h" #include "chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.h" #include "chrome/browser/ui/views/digital_credentials/digital_identity_multi_step_dialog.h" +#include "content/public/browser/digital_credentials_cross_device.h" #include "content/public/browser/digital_identity_provider.h" -#include "device/fido/digital_identity_request_handler.h" -#include "device/fido/fido_discovery_factory.h" -#include "device/fido/fido_request_handler_base.h" namespace content { class WebContents; } +namespace device::cablev2 { +enum class Event; +} + // Desktop-specific implementation of `DigitalIdentityProvider`. Uses FIDO // hybrid flow to retrieve credentials stored on a mobile device. class DigitalIdentityProviderDesktop : public content::DigitalIdentityProvider { @@ -34,13 +35,17 @@ DigitalIdentityInterstitialCallback callback) override; void Request(content::WebContents* web_contents, const url::Origin& rp_origin, - const std::string& request, + base::Value request, DigitalIdentityCallback callback) override; private: - void OnReadyToShowUi( - const device::FidoRequestHandlerBase::TransportAvailabilityInfo& - availability_info); + // Called whenever some significant event occurs during the transaction. + void OnEvent(content::digital_credentials::cross_device::Event); + + // Called when the transaction is finished (successfully or not). + void OnFinished( + base::expected<content::digital_credentials::cross_device::Response, + content::digital_credentials::cross_device::Error>); // Ensures `dialog_` is initialized and returns it. DigitalIdentityMultiStepDialog* EnsureDialogCreated(); @@ -51,21 +56,26 @@ // Shows dialog which prompts user to manually turn on bluetooth. void ShowBluetoothManualTurnOnDialog(); - // Called once the user has turned on bluetooth and clicked "Try Again". - void OnBluetoothTurnedOn(); + // Called when the user clicks a button on the dialog requesting Bluetooth + // power. + void OnUserRequestedBluetoothPowerOn(); // Called when the request has failed, possibly as a result of the user // canceling the dialog. void OnCanceled(); + // Called to end the request with an error. + void EndRequestWithError( + content::DigitalIdentityProvider::RequestStatusForMetrics); + // The web contents to which the dialog is modal to. base::WeakPtr<content::WebContents> web_contents_; url::Origin rp_origin_; std::string qr_url_; - // Whether bluetooth is powered on. - bool is_ble_powered_ = false; + std::unique_ptr<content::digital_credentials::cross_device::Transaction> + transaction_; // Shows dialog requesting that the user manually turn on bluetooth. std::unique_ptr<DigitalIdentityBluetoothManualDialogController> @@ -75,11 +85,6 @@ // step. std::unique_ptr<DigitalIdentityMultiStepDialog> dialog_; - std::unique_ptr<device::FidoDiscoveryFactory> discovery_factory_; - - std::unique_ptr<device::DigitalIdentityRequestHandler> request_handler_; - std::unique_ptr<DigitalIdentityFidoHandlerObserver> request_handler_observer_; - DigitalIdentityCallback callback_; base::WeakPtrFactory<DigitalIdentityProviderDesktop> weak_ptr_factory_{this};
diff --git a/chrome/browser/enterprise/connectors/test/deep_scanning_test_utils.cc b/chrome/browser/enterprise/connectors/test/deep_scanning_test_utils.cc index 4938c84..50e07a0d 100644 --- a/chrome/browser/enterprise/connectors/test/deep_scanning_test_utils.cc +++ b/chrome/browser/enterprise/connectors/test/deep_scanning_test_utils.cc
@@ -928,31 +928,30 @@ enabled_opt_in_events, bool machine_scope) { ScopedListPrefUpdate settings_list(prefs, kOnSecurityEventPref); + settings_list->clear(); + prefs->ClearPref(kOnSecurityEventScopePref); if (!enabled) { - settings_list->clear(); - prefs->ClearPref(kOnSecurityEventScopePref); return; } - if (settings_list->empty()) { - base::Value::Dict settings; + base::Value::Dict settings; - settings.Set(kKeyServiceProvider, base::Value("google")); - if (!enabled_event_names.empty()) { - base::Value::List enabled_event_name_list; - for (const auto& enabled_event_name : enabled_event_names) { - enabled_event_name_list.Append(enabled_event_name); - } - settings.Set(kKeyEnabledEventNames, std::move(enabled_event_name_list)); + settings.Set(kKeyServiceProvider, base::Value("google")); + if (!enabled_event_names.empty()) { + base::Value::List enabled_event_name_list; + for (const auto& enabled_event_name : enabled_event_names) { + enabled_event_name_list.Append(enabled_event_name); } - - if (!enabled_opt_in_events.empty()) { - settings.Set(kKeyEnabledOptInEvents, - CreateOptInEventsList(enabled_opt_in_events)); - } - - settings_list->Append(std::move(settings)); + settings.Set(kKeyEnabledEventNames, std::move(enabled_event_name_list)); } + + if (!enabled_opt_in_events.empty()) { + settings.Set(kKeyEnabledOptInEvents, + CreateOptInEventsList(enabled_opt_in_events)); + } + + settings_list->Append(std::move(settings)); + prefs->SetInteger( kOnSecurityEventScopePref, machine_scope ? policy::POLICY_SCOPE_MACHINE : policy::POLICY_SCOPE_USER);
diff --git a/chrome/browser/enterprise/profile_management/oidc_auth_response_capture_navigation_throttle.cc b/chrome/browser/enterprise/profile_management/oidc_auth_response_capture_navigation_throttle.cc index ce68460..7bc5a068 100644 --- a/chrome/browser/enterprise/profile_management/oidc_auth_response_capture_navigation_throttle.cc +++ b/chrome/browser/enterprise/profile_management/oidc_auth_response_capture_navigation_throttle.cc
@@ -20,12 +20,16 @@ #include "chrome/browser/enterprise/signin/oidc_metrics_utils.h" #include "chrome/browser/profiles/profile.h" #include "components/policy/core/common/policy_logger.h" +#include "components/url_matcher/url_matcher.h" +#include "components/url_matcher/url_util.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_throttle.h" #include "content/public/browser/web_contents.h" #include "url/gurl.h" +using url_matcher::URLMatcher; + namespace { constexpr char kEnrollmentFallbackHost[] = "chromeenterprise.google"; @@ -34,11 +38,14 @@ // Msft Entra will first navigate to a reprocess URL and redirect to our // enrolllment URL, we need to capture this to correctly create the navigation // throttle. -constexpr char kOidcEntraLoginHost[] = "login.microsoftonline.com"; -constexpr char kOidcEntraReprocessPath[] = "/common/reprocess"; -constexpr char kOidcEntraLoginPath[] = "/common/login"; +// Reprocess URL can have two forms, "/common/reprocess" and +// "/<GUID>/reprocess", same for /login. +constexpr char kOidcEntraReprocessPattern[] = + "https://login.microsoftonline.com/.*/reprocess"; +constexpr char kOidcEntraLoginPattern[] = + "https://login.microsoftonline.com/.*/login"; // For new identities, the redirection starts from the "Keep me signed in" page. -constexpr char kOidcEntraKmsiPath[] = "/kmsi"; +constexpr char kOidcEntraKmsiPath[] = "https://login.microsoftonline.com/kmsi"; constexpr char kQuerySeparator[] = "&"; constexpr char kKeyValueSeparator[] = "="; @@ -68,6 +75,33 @@ url.path() == kEnrollmentFallbackPath; } +std::unique_ptr<URLMatcher> CreateOidcEnrollmentUrlMatcher() { + std::vector<std::string> valid_url_patterns = { + kOidcEntraReprocessPattern, kOidcEntraLoginPattern, kOidcEntraKmsiPath}; + + base::MatcherStringPattern::ID id = 0; + url_matcher::URLMatcherConditionSet::Vector condition_sets; + auto url_matcher = std::make_unique<URLMatcher>(); + + for (const auto& url_pattern : valid_url_patterns) { + url_matcher::URLMatcherConditionSet::Conditions conditions; + conditions.insert( + url_matcher->condition_factory()->CreateOriginAndPathMatchesCondition( + url_pattern)); + scoped_refptr<url_matcher::URLMatcherConditionSet> condition_set = + new url_matcher::URLMatcherConditionSet(id++, conditions); + condition_sets.push_back(std::move(condition_set)); + } + + url_matcher->AddConditionSets(condition_sets); + return url_matcher; +} + +const url_matcher::URLMatcher* GetOidcEnrollmentUrlMatcher() { + static base::NoDestructor<std::unique_ptr<URLMatcher>> matcher( + CreateOidcEnrollmentUrlMatcher()); + return matcher->get(); +} } // namespace namespace profile_management { @@ -85,10 +119,7 @@ if (!base::FeatureList::IsEnabled( profile_management::features:: kEnableGenericOidcAuthProfileManagement)) { - if (!(url.DomainIs(kOidcEntraLoginHost) && - (url.path() == kOidcEntraReprocessPath || - url.path() == kOidcEntraKmsiPath || - url.path() == kOidcEntraLoginPath))) { + if (GetOidcEnrollmentUrlMatcher()->MatchURL(url).empty()) { return nullptr; }
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 be3a3343..a813114 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
@@ -102,6 +102,14 @@ enable_generic_oidc()}}); } + OidcAuthResponseCaptureNavigationThrottleTest(bool enable_oidc_interception, + bool enable_generic_oidc) { + scoped_feature_list_.InitWithFeatureStates( + {{features::kOidcAuthProfileManagement, enable_oidc_interception}, + {features::kEnableGenericOidcAuthProfileManagement, + enable_generic_oidc}}); + } + ~OidcAuthResponseCaptureNavigationThrottleTest() override = default; void SetUp() override { @@ -594,4 +602,53 @@ testing::Combine(/*enable_oidc_interception=*/testing::Bool(), /*enable_generic_oidc=*/testing::Bool())); +// Test class dedicated to test if MaybeCreateThrottleFor creates throttle on +// correct set of URLs. +class OidcAuthNavigationThrottleCreationTest + : public OidcAuthResponseCaptureNavigationThrottleTest { + public: + OidcAuthNavigationThrottleCreationTest() + : OidcAuthResponseCaptureNavigationThrottleTest( + /*enable_oidc_interception=*/true, + /*enable_generic_oidc=*/false) {} + + ~OidcAuthNavigationThrottleCreationTest() override = default; + + void TestThrottleCreation(std::string url_string, + bool expect_throttle_created) { + content::MockNavigationHandle navigation_handle(GURL(url_string), + main_frame()); + auto throttle = + OidcAuthResponseCaptureNavigationThrottle::MaybeCreateThrottleFor( + &navigation_handle); + + ASSERT_EQ(throttle != nullptr, expect_throttle_created); + } +}; + +TEST_F(OidcAuthNavigationThrottleCreationTest, MsftThrottleCreated) { + TestThrottleCreation( + "https://login.microsoftonline.com/some-tenant-id/reprocess", + /*expect_throttle_created=*/true); + TestThrottleCreation("https://login.microsoftonline.com/common/reprocess", + /*expect_throttle_created=*/true); + TestThrottleCreation("https://login.microsoftonline.com/some-tenant-id/login", + /*expect_throttle_created=*/true); + TestThrottleCreation("https://login.microsoftonline.com/common/login", + /*expect_throttle_created=*/true); + TestThrottleCreation( + "https://login.microsoftonline.com/common/reprocess?ctx=random-value", + /*expect_throttle_created=*/true); + TestThrottleCreation("https://login.microsoftonline.com/kmsi", + /*expect_throttle_created=*/true); +} + +TEST_F(OidcAuthNavigationThrottleCreationTest, MsftThrottleNotCreated) { + TestThrottleCreation( + "https://mismatchhost.microsoftonline.com/common/reprocess", + /*expect_throttle_created=*/false); + TestThrottleCreation("https://login.microsoftonline.com/common/somethingelse", + /*expect_throttle_created=*/false); +} + } // namespace profile_management
diff --git a/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc b/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc index eb33d0d..1d5a2ab 100644 --- a/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc +++ b/chrome/browser/extensions/api/bluetooth_low_energy/bluetooth_low_energy_apitest.cc
@@ -1173,7 +1173,7 @@ EXPECT_CALL(*mock_adapter_, GetDevice(kTestLeDeviceAddress1)) .WillRepeatedly(Return(device1_.get())); static_assert( - BluetoothDevice::NUM_CONNECT_ERROR_CODES == 19, + BluetoothDevice::NUM_CONNECT_ERROR_CODES == 21, "Update required if the number of BluetoothDevice enums changes."); EXPECT_CALL(*device0_, CreateGattConnection(_, _)) .Times(13)
diff --git a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.cc b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.cc index 14214fac..ab20252 100644 --- a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.cc +++ b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.cc
@@ -340,7 +340,9 @@ } void QuickUnlockPrivateCanAuthenticatePinFunction::HandleCanAuthenticateResult( - bool result) { + bool result, + std::optional<base::Time> available_at) { + // |available_at| is ignored. Respond(ArgumentList( quick_unlock_private::CanAuthenticatePin::Results::Create(result))); }
diff --git a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.h b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.h index 6ce70ab..559da6c 100644 --- a/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.h +++ b/chrome/browser/extensions/api/quick_unlock_private/quick_unlock_private_api.h
@@ -111,7 +111,8 @@ ResponseAction Run() override; private: - void HandleCanAuthenticateResult(bool result); + void HandleCanAuthenticateResult(bool result, + std::optional<base::Time> available_at); ChromeExtensionFunctionDetails chrome_details_; };
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 5ff3d190..55e9b09 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -808,11 +808,6 @@ "expiry_milestone": 128 }, { - "name": "autofill-enable-xhr-submission-detection-ios", - "owners": [ "eic@google.com", "bling-transactions@google.com" , "bling-flags@google.com"], - "expiry_milestone": 129 - }, - { "name": "autofill-for-unclassified-fields-available", "owners": [ "tchudakov@chromium.org", "vykochko@chromium.org", "brunobraga@chromium.org" ], "expiry_milestone": 130 @@ -4129,13 +4124,13 @@ "expiry_milestone": 130 }, { - "name": "enable-user-link-capturing-pwa", - "owners": [ "dibyapal@chromium.org", "pwa-team@google.com" ], + "name": "enable-user-link-capturing-scope-extensions-pwa", + "owners": [ "dmurph@chromium.org", "pwa-team@google.com" ], "expiry_milestone": 131 }, { - "name": "enable-user-link-capturing-scope-extensions-pwa", - "owners": [ "dmurph@chromium.org", "pwa-team@google.com" ], + "name": "enable-user-navigation-capturing-pwa", + "owners": [ "dibyapal@chromium.org", "pwa-team@google.com" ], "expiry_milestone": 131 }, { @@ -6137,12 +6132,12 @@ { "name": "ntp-alpha-background-collections", "owners": [ "pauladedeji@chromium.org", "tiborg@chromium.org" ], - "expiry_milestone": 126 + "expiry_milestone": 140 }, { "name": "ntp-background-image-error-detection", "owners": [ "pauladedeji@chromium.org", "tiborg@chromium.org" ], - "expiry_milestone": 126 + "expiry_milestone": 140 }, { "name": "ntp-calendar-module", @@ -6720,7 +6715,7 @@ { "name": "omnibox-zero-suggest-prefetch-debouncing", "owners": [ "khalidpeer@chromium.org", "mahmadi@chromium.org", "chrome-omnibox-team@google.com" ], - "expiry_milestone": 130 + "expiry_milestone": 140 }, { "name": "omnibox-zero-suggest-prefetching", @@ -6730,7 +6725,7 @@ { "name": "omnibox-zero-suggest-prefetching-on-srp", "owners": [ "khalidpeer@chromium.org", "mahmadi@chromium.org", "chrome-omnibox-team@google.com" ], - "expiry_milestone": 130 + "expiry_milestone": 140 }, { "name": "omnibox-zero-suggest-prefetching-on-web",
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index 1a835e1b..fa01eb0 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -3472,8 +3472,8 @@ const char kSiteSearchSettingsPolicyDescription[] = "Allow site search engines to be defined by the SiteSearchSettings policy."; -const char kDesktopPWAsUserLinkCapturingName[] = "Desktop PWA Link Capturing"; -const char kDesktopPWAsUserLinkCapturingDescription[] = +const char kPwaNavigationCapturingName[] = "Desktop PWA Link Capturing"; +const char kPwaNavigationCapturingDescription[] = "Enables opening links from Chrome in an installed PWA. Currently under " "reimplementation."; #endif
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 94cbefa..006114b7 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -2004,8 +2004,8 @@ extern const char kSiteSearchSettingsPolicyName[]; extern const char kSiteSearchSettingsPolicyDescription[]; -extern const char kDesktopPWAsUserLinkCapturingName[]; -extern const char kDesktopPWAsUserLinkCapturingDescription[]; +extern const char kPwaNavigationCapturingName[]; +extern const char kPwaNavigationCapturingDescription[]; #endif extern const char kSkiaRendererName[];
diff --git a/chrome/browser/ip_protection/BUILD.gn b/chrome/browser/ip_protection/BUILD.gn index f214921..fa7e1542 100644 --- a/chrome/browser/ip_protection/BUILD.gn +++ b/chrome/browser/ip_protection/BUILD.gn
@@ -89,6 +89,7 @@ "//base/test:test_support", "//chrome/browser/policy:test_support", "//chrome/test:test_support", + "//components/ip_protection:ip_protection", "//components/privacy_sandbox:features", "//components/signin/public/identity_manager:identity_manager", "//components/signin/public/identity_manager:test_support",
diff --git a/chrome/browser/ip_protection/ip_protection_config_provider.cc b/chrome/browser/ip_protection/ip_protection_config_provider.cc index 86eda2f..884c6db 100644 --- a/chrome/browser/ip_protection/ip_protection_config_provider.cc +++ b/chrome/browser/ip_protection/ip_protection_config_provider.cc
@@ -23,7 +23,9 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/channel_info.h" #include "components/ip_protection/common/ip_protection_config_provider_helper.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "components/ip_protection/common/ip_protection_proxy_config_fetcher.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "components/ip_protection/common/ip_protection_token_direct_fetcher.h" #include "components/prefs/pref_service.h" #include "components/privacy_sandbox/privacy_sandbox_features.h" @@ -45,6 +47,8 @@ #include "net/third_party/quiche/src/quiche/blind_sign_auth/proto/spend_token_data.pb.h" #include "third_party/abseil-cpp/absl/status/status.h" +using ::ip_protection::TryGetAuthTokensResult; + IpProtectionConfigProvider::IpProtectionConfigProvider( signin::IdentityManager* identity_manager, privacy_sandbox::TrackingProtectionSettings* tracking_protection_settings, @@ -125,9 +129,8 @@ // If IP Protection is disabled via user settings then don't attempt to fetch // tokens. if (!IsIpProtectionEnabled()) { - TryGetAuthTokensComplete( - std::nullopt, std::move(callback), - IpProtectionTryGetAuthTokensResult::kFailedDisabledByUser); + TryGetAuthTokensComplete(std::nullopt, std::move(callback), + TryGetAuthTokensResult::kFailedDisabledByUser); return; } @@ -135,16 +138,14 @@ // try to request tokens. if (last_try_get_auth_tokens_backoff_ && *last_try_get_auth_tokens_backoff_ == base::TimeDelta::Max()) { - TryGetAuthTokensComplete( - std::nullopt, std::move(callback), - IpProtectionTryGetAuthTokensResult::kFailedNoAccount); + TryGetAuthTokensComplete(std::nullopt, std::move(callback), + TryGetAuthTokensResult::kFailedNoAccount); return; } if (!CanRequestOAuthToken()) { - TryGetAuthTokensComplete( - std::nullopt, std::move(callback), - IpProtectionTryGetAuthTokensResult::kFailedNoAccount); + TryGetAuthTokensComplete(std::nullopt, std::move(callback), + TryGetAuthTokensResult::kFailedNoAccount); return; } @@ -269,14 +270,14 @@ TryGetAuthTokensComplete( std::nullopt, std::move(callback), error.IsTransientError() - ? IpProtectionTryGetAuthTokensResult::kFailedOAuthTokenTransient - : IpProtectionTryGetAuthTokensResult::kFailedOAuthTokenPersistent); + ? TryGetAuthTokensResult::kFailedOAuthTokenTransient + : TryGetAuthTokensResult::kFailedOAuthTokenPersistent); return; } const base::TimeTicks current_time = base::TimeTicks::Now(); - base::UmaHistogramTimes("NetworkService.IpProtection.OAuthTokenFetchTime", - current_time - oauth_token_fetch_start_time); + ip_protection::Telemetry().OAuthTokenFetchComplete( + current_time - oauth_token_fetch_start_time); FetchBlindSignedToken(access_token_info, batch_size, quiche_proxy_layer, std::move(callback)); } @@ -317,25 +318,26 @@ base::TimeTicks bsa_get_tokens_start_time, TryGetAuthTokensCallback callback, absl::StatusOr<std::vector<quiche::BlindSignToken>> tokens) { + using enum TryGetAuthTokensResult; DCHECK_CURRENTLY_ON(content::BrowserThread::UI); if (is_shutting_down_) { return; } if (!tokens.ok()) { // Apply the canonical mapping from abseil status to HTTP status. - IpProtectionTryGetAuthTokensResult result; + TryGetAuthTokensResult result; switch (tokens.status().code()) { case absl::StatusCode::kInvalidArgument: - result = IpProtectionTryGetAuthTokensResult::kFailedBSA400; + result = kFailedBSA400; break; case absl::StatusCode::kUnauthenticated: - result = IpProtectionTryGetAuthTokensResult::kFailedBSA401; + result = kFailedBSA401; break; case absl::StatusCode::kPermissionDenied: - result = IpProtectionTryGetAuthTokensResult::kFailedBSA403; + result = kFailedBSA403; break; default: - result = IpProtectionTryGetAuthTokensResult::kFailedBSAOther; + result = kFailedBSAOther; break; } VLOG(2) << "IPATP::OnFetchBlindSignedTokenCompleted got an error: " @@ -346,21 +348,19 @@ if (tokens.value().size() == 0) { VLOG(2) << "IPATP::OnFetchBlindSignedTokenCompleted called with no tokens"; - TryGetAuthTokensComplete( - std::nullopt, std::move(callback), - IpProtectionTryGetAuthTokensResult::kFailedBSAOther); + TryGetAuthTokensComplete(std::nullopt, std::move(callback), + kFailedBSAOther); return; } - std::vector<network::BlindSignedAuthToken> bsa_tokens; + std::vector<ip_protection::BlindSignedAuthToken> bsa_tokens; for (const quiche::BlindSignToken& token : tokens.value()) { - std::optional<network::BlindSignedAuthToken> converted_token = + std::optional<ip_protection::BlindSignedAuthToken> converted_token = ip_protection::IpProtectionConfigProviderHelper:: CreateBlindSignedAuthToken(token); if (!converted_token.has_value() || converted_token->token.empty()) { - TryGetAuthTokensComplete( - std::nullopt, std::move(callback), - IpProtectionTryGetAuthTokensResult::kFailedBSAOther); + TryGetAuthTokensComplete(std::nullopt, std::move(callback), + kFailedBSAOther); return; } else { bsa_tokens.push_back(std::move(converted_token).value()); @@ -368,20 +368,17 @@ } const base::TimeTicks current_time = base::TimeTicks::Now(); - base::UmaHistogramTimes("NetworkService.IpProtection.TokenBatchRequestTime", - current_time - bsa_get_tokens_start_time); - TryGetAuthTokensComplete(std::make_optional(std::move(bsa_tokens)), - std::move(callback), - IpProtectionTryGetAuthTokensResult::kSuccess); + std::move(callback), kSuccess, + current_time - bsa_get_tokens_start_time); } void IpProtectionConfigProvider::TryGetAuthTokensComplete( - std::optional<std::vector<network::BlindSignedAuthToken>> bsa_tokens, + std::optional<std::vector<ip_protection::BlindSignedAuthToken>> bsa_tokens, TryGetAuthTokensCallback callback, - IpProtectionTryGetAuthTokensResult result) { - base::UmaHistogramEnumeration( - "NetworkService.IpProtection.TryGetAuthTokensResult", result); + TryGetAuthTokensResult result, + std::optional<base::TimeDelta> duration) { + ip_protection::Telemetry().TokenBatchFetchComplete(result, duration); std::optional<base::TimeDelta> backoff = CalculateBackoff(result); std::optional<base::Time> try_again_after; @@ -409,46 +406,47 @@ } std::optional<base::TimeDelta> IpProtectionConfigProvider::CalculateBackoff( - IpProtectionTryGetAuthTokensResult result) { + TryGetAuthTokensResult result) { + using enum TryGetAuthTokensResult; std::optional<base::TimeDelta> backoff; bool exponential = false; switch (result) { - case IpProtectionTryGetAuthTokensResult::kSuccess: + case kSuccess: break; - case IpProtectionTryGetAuthTokensResult::kFailedNoAccount: - case IpProtectionTryGetAuthTokensResult::kFailedOAuthTokenPersistent: - case IpProtectionTryGetAuthTokensResult::kFailedDisabledByUser: + case kFailedNoAccount: + case kFailedOAuthTokenPersistent: + case kFailedDisabledByUser: backoff = base::TimeDelta::Max(); break; - case IpProtectionTryGetAuthTokensResult::kFailedNotEligible: + case kFailedNotEligible: // TODO(crbug.com/40267788): When we add a client side account // capabilities check, if this capability/eligibility is something that // can change and be detected via callbacks to an overridden // `IdentityManager::Observer::OnExtendedAccountInfoUpdated()` method, // then update this failure so that we wait indefinitely as well (like // the cases above). - case IpProtectionTryGetAuthTokensResult::kFailedBSA403: + case kFailedBSA403: // Eligibility, whether determined locally or on the server, is unlikely // to change quickly. backoff = ip_protection::IpProtectionConfigProviderHelper::kNotEligibleBackoff; break; - case IpProtectionTryGetAuthTokensResult::kFailedOAuthTokenTransient: - case IpProtectionTryGetAuthTokensResult::kFailedBSAOther: + case kFailedOAuthTokenTransient: + case kFailedBSAOther: // Transient failure to fetch an OAuth token, or some other error from // BSA that is probably transient. backoff = ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff; exponential = true; break; - case IpProtectionTryGetAuthTokensResult::kFailedBSA400: - case IpProtectionTryGetAuthTokensResult::kFailedBSA401: + case kFailedBSA400: + case kFailedBSA401: // Both 400 and 401 suggest a bug, so do not retry aggressively. backoff = ip_protection::IpProtectionConfigProviderHelper::kBugBackoff; exponential = true; break; - case IpProtectionTryGetAuthTokensResult::kFailedOAuthTokenDeprecated: - NOTREACHED(); + case kFailedOAuthTokenDeprecated: + NOTREACHED_NORETURN(); } // Note that we calculate the backoff assuming that we've waited for
diff --git a/chrome/browser/ip_protection/ip_protection_config_provider.h b/chrome/browser/ip_protection/ip_protection_config_provider.h index 49fb5c04..6fe5fcd 100644 --- a/chrome/browser/ip_protection/ip_protection_config_provider.h +++ b/chrome/browser/ip_protection/ip_protection_config_provider.h
@@ -16,8 +16,10 @@ #include "base/time/time.h" #include "chrome/browser/ip_protection/ip_protection_config_provider_factory.h" #include "components/ip_protection/common/ip_protection_config_provider_helper.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "components/ip_protection/common/ip_protection_proxy_config_fetcher.h" #include "components/ip_protection/common/ip_protection_proxy_config_retriever.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "components/ip_protection/common/ip_protection_token_direct_fetcher.h" #include "components/privacy_sandbox/tracking_protection_settings.h" #include "components/privacy_sandbox/tracking_protection_settings_observer.h" @@ -41,43 +43,6 @@ struct BlindSignToken; } // namespace quiche -// The result of a fetch of tokens from the IP Protection auth token server. -// -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. Keep this in sync with -// IpProtectionTokenBatchRequestResult in enums.xml. -enum class IpProtectionTryGetAuthTokensResult { - // The request was successful and resulted in new tokens. - kSuccess = 0, - // No primary account is set. - kFailedNoAccount = 1, - // Chrome determined the primary account is not eligible. - kFailedNotEligible = 2, - // There was a failure fetching an OAuth token for the primary account. - // Deprecated in favor of `kFailedOAuthToken{Transient,Persistent}`. - kFailedOAuthTokenDeprecated = 3, - // There was a failure in BSA with the given status code. - kFailedBSA400 = 4, - kFailedBSA401 = 5, - kFailedBSA403 = 6, - - // Any other issue calling BSA. - kFailedBSAOther = 7, - - // There was a transient failure fetching an OAuth token for the primary - // account. - kFailedOAuthTokenTransient = 8, - // There was a persistent failure fetching an OAuth token for the primary - // account. - kFailedOAuthTokenPersistent = 9, - - // The attempt to request tokens failed because IP Protection was disabled by - // the user. - kFailedDisabledByUser = 10, - - kMaxValue = kFailedDisabledByUser, -}; - // Fetches IP protection tokens on demand for the network service. // // This class handles both requesting OAuth2 tokens for the signed-in user, and @@ -176,14 +141,16 @@ // Finish a call to `TryGetAuthTokens()` by recording the result and invoking // its callback. void TryGetAuthTokensComplete( - std::optional<std::vector<network::BlindSignedAuthToken>> bsa_tokens, + std::optional<std::vector<ip_protection::BlindSignedAuthToken>> + bsa_tokens, TryGetAuthTokensCallback callback, - IpProtectionTryGetAuthTokensResult result); + ip_protection::TryGetAuthTokensResult result, + std::optional<base::TimeDelta> duration = std::nullopt); // Calculates the backoff time for the given result, based on // `last_try_get_auth_tokens_..` fields, and updates those fields. std::optional<base::TimeDelta> CalculateBackoff( - IpProtectionTryGetAuthTokensResult result); + ip_protection::TryGetAuthTokensResult result); // Creating a generic callback in order for `RequestOAuthToken()` to work for // `TryGetAuthTokens()` and `GetProxyList()`. @@ -276,8 +243,8 @@ // will be set to `base::TimeDelta::Max()` if no further attempts to get // tokens should be made. These will be updated by calls from any receiver // (so, from either the main profile or an associated incognito mode profile). - IpProtectionTryGetAuthTokensResult last_try_get_auth_tokens_result_ = - IpProtectionTryGetAuthTokensResult::kSuccess; + ip_protection::TryGetAuthTokensResult last_try_get_auth_tokens_result_ = + ip_protection::TryGetAuthTokensResult::kSuccess; std::optional<base::TimeDelta> last_try_get_auth_tokens_backoff_; // The `mojo::Receiver` objects allowing the network service to call methods
diff --git a/chrome/browser/ip_protection/ip_protection_config_provider_browsertest.cc b/chrome/browser/ip_protection/ip_protection_config_provider_browsertest.cc index 78156a40..7d0738a 100644 --- a/chrome/browser/ip_protection/ip_protection_config_provider_browsertest.cc +++ b/chrome/browser/ip_protection/ip_protection_config_provider_browsertest.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/signin/identity_test_environment_profile_adaptor.h" #include "chrome/test/base/chrome_test_utils.h" #include "chrome/test/base/platform_browser_test.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/core/common/policy_types.h" #include "components/policy/policy_constants.h" @@ -40,6 +41,9 @@ #include "components/signin/public/identity_manager/primary_account_change_event.h" #endif +using ::ip_protection::BlindSignedAuthToken; +using ::ip_protection::GeoHint; + namespace { class ScopedIpProtectionFeatureList { public: @@ -62,7 +66,7 @@ IpProtectionConfigGetterInterceptor(IpProtectionConfigProvider* getter, std::string token, base::Time expiration, - network::GeoHint geo_hint, + GeoHint geo_hint, bool should_intercept = true) : getter_(getter), receiver_id_(getter_->receiver_id_for_testing()), @@ -89,9 +93,9 @@ network::mojom::IpProtectionProxyLayer proxy_layer, TryGetAuthTokensCallback callback) override { if (should_intercept_) { - std::vector<network::BlindSignedAuthToken> tokens; + std::vector<BlindSignedAuthToken> tokens; for (uint32_t i = 0; i < batch_size; i++) { - network::BlindSignedAuthToken token = { + BlindSignedAuthToken token = { .token = token_, .expiration = expiration_, .geo_hint = geo_hint_}; tokens.push_back(std::move(token)); } @@ -106,7 +110,7 @@ base::Time expiration() const { return expiration_; } - network::GeoHint geo_hint() const { return geo_hint_; } + GeoHint geo_hint() const { return geo_hint_; } void EnableInterception() { should_intercept_ = true; } void DisableInterception() { should_intercept_ = false; } @@ -120,7 +124,7 @@ mojo::ReceiverId receiver_id_; std::string token_; base::Time expiration_; - network::GeoHint geo_hint_; + GeoHint geo_hint_; bool should_intercept_; }; @@ -148,7 +152,7 @@ std::string token = "best_token_ever"; base::Time expiration = base::Time::Now() + base::Seconds(12345); - network::GeoHint geo_hint = { + GeoHint geo_hint = { .country_code = "US", .iso_region = "US-AL", .city_name = "ALABASTER"}; main_profile_auth_token_getter_interceptor_ = std::make_unique<IpProtectionConfigGetterInterceptor>( @@ -224,7 +228,7 @@ std::string token = "best_token_ever"; base::Time expiration = base::Time::Now() + base::Seconds(12345); - network::GeoHint geo_hint = { + GeoHint geo_hint = { .country_code = "US", .iso_region = "US-AL", .city_name = "ALABASTER"}; ASSERT_EQ(getter->receivers_for_testing().size(), 1U); auto auth_token_getter_interceptor_ = @@ -234,14 +238,14 @@ // To test that the Network Service can successfully request tokens, use the // test method on NetworkContext that will have it request tokens and then // send back the first token that it receives. - base::test::TestFuture<const std::optional<network::BlindSignedAuthToken>&, + base::test::TestFuture<const std::optional<BlindSignedAuthToken>&, std::optional<base::Time>> future; auto* ipp_proxy_delegate = getter->last_remote_for_testing(); ipp_proxy_delegate->VerifyIpProtectionConfigGetterForTesting( future.GetCallback()); - const std::optional<network::BlindSignedAuthToken>& result = - future.Get<std::optional<network::BlindSignedAuthToken>>(); + const std::optional<BlindSignedAuthToken>& result = + future.Get<std::optional<BlindSignedAuthToken>>(); ASSERT_TRUE(result); EXPECT_EQ(result->token, token); // Expiration is "fuzzed" backward in time, so expect less-than. @@ -264,8 +268,8 @@ ASSERT_NE(incognito_ipp_proxy_delegate, ipp_proxy_delegate); incognito_ipp_proxy_delegate->VerifyIpProtectionConfigGetterForTesting( future.GetCallback()); - const std::optional<network::BlindSignedAuthToken>& incognito_result = - future.Get<std::optional<network::BlindSignedAuthToken>>(); + const std::optional<BlindSignedAuthToken>& incognito_result = + future.Get<std::optional<BlindSignedAuthToken>>(); ASSERT_TRUE(incognito_result); EXPECT_EQ(incognito_result->token, token); EXPECT_LT(incognito_result->expiration, expiration); @@ -274,8 +278,8 @@ future.Clear(); ipp_proxy_delegate->VerifyIpProtectionConfigGetterForTesting( future.GetCallback()); - const std::optional<network::BlindSignedAuthToken>& second_attempt_result = - future.Get<std::optional<network::BlindSignedAuthToken>>(); + const std::optional<BlindSignedAuthToken>& second_attempt_result = + future.Get<std::optional<BlindSignedAuthToken>>(); ASSERT_TRUE(second_attempt_result); EXPECT_EQ(second_attempt_result->token, token); EXPECT_LT(second_attempt_result->expiration, expiration); @@ -395,7 +399,7 @@ // Request tokens from both contexts and ensure that the "don't retry" // cooldown time is returned. The provider should do this itself, so the // interceptors won't be used for this part. - base::test::TestFuture<const std::optional<network::BlindSignedAuthToken>&, + base::test::TestFuture<const std::optional<BlindSignedAuthToken>&, std::optional<base::Time>> future; main_profile_ipp_proxy_delegate_->VerifyIpProtectionConfigGetterForTesting( @@ -453,9 +457,8 @@ future.Clear(); main_profile_ipp_proxy_delegate_->VerifyIpProtectionConfigGetterForTesting( future.GetCallback()); - const std::optional<network::BlindSignedAuthToken>& - main_profile_third_attempt_result = - future.Get<std::optional<network::BlindSignedAuthToken>>(); + const std::optional<BlindSignedAuthToken>& main_profile_third_attempt_result = + future.Get<std::optional<BlindSignedAuthToken>>(); ASSERT_TRUE(main_profile_third_attempt_result); EXPECT_EQ(main_profile_third_attempt_result->token, main_profile_auth_token_getter_interceptor_->token()); @@ -465,9 +468,9 @@ future.Clear(); incognito_profile_ipp_proxy_delegate_ ->VerifyIpProtectionConfigGetterForTesting(future.GetCallback()); - const std::optional<network::BlindSignedAuthToken>& + const std::optional<BlindSignedAuthToken>& incognito_profile_third_attempt_result = - future.Get<std::optional<network::BlindSignedAuthToken>>(); + future.Get<std::optional<BlindSignedAuthToken>>(); ASSERT_TRUE(incognito_profile_third_attempt_result); EXPECT_EQ(incognito_profile_third_attempt_result->token, incognito_profile_auth_token_getter_interceptor_->token()); @@ -516,10 +519,10 @@ // Request tokens from both contexts and ensure that the "don't retry" // cooldown time is returned. - base::test::TestFuture<const std::optional<network::BlindSignedAuthToken>&, + base::test::TestFuture<const std::optional<BlindSignedAuthToken>&, std::optional<base::Time>> main_profile_verification_future; - base::test::TestFuture<const std::optional<network::BlindSignedAuthToken>&, + base::test::TestFuture<const std::optional<BlindSignedAuthToken>&, std::optional<base::Time>> incognito_profile_verification_future; @@ -568,14 +571,14 @@ ->VerifyIpProtectionConfigGetterForTesting( incognito_profile_verification_future.GetCallback()); - const std::optional<network::BlindSignedAuthToken>& + const std::optional<BlindSignedAuthToken>& main_profile_second_attempt_result = main_profile_verification_future - .Get<std::optional<network::BlindSignedAuthToken>>(); - const std::optional<network::BlindSignedAuthToken>& + .Get<std::optional<BlindSignedAuthToken>>(); + const std::optional<BlindSignedAuthToken>& incognito_profile_second_attempt_result = incognito_profile_verification_future - .Get<std::optional<network::BlindSignedAuthToken>>(); + .Get<std::optional<BlindSignedAuthToken>>(); ASSERT_TRUE(main_profile_second_attempt_result); ASSERT_TRUE(incognito_profile_second_attempt_result);
diff --git a/chrome/browser/ip_protection/ip_protection_config_provider_unittest.cc b/chrome/browser/ip_protection/ip_protection_config_provider_unittest.cc index b59e9fcf..15da9b2 100644 --- a/chrome/browser/ip_protection/ip_protection_config_provider_unittest.cc +++ b/chrome/browser/ip_protection/ip_protection_config_provider_unittest.cc
@@ -19,6 +19,7 @@ #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/ip_protection/common/ip_protection_config_http.h" #include "components/ip_protection/common/ip_protection_config_provider_helper.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "components/ip_protection/common/ip_protection_proxy_config_fetcher.h" #include "components/ip_protection/common/mock_blind_sign_auth.h" #include "components/prefs/testing_pref_service.h" @@ -37,6 +38,9 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/status/status.h" +using ::ip_protection::BlindSignedAuthToken; +using ::ip_protection::GeoHint; + namespace { constexpr char kTryGetAuthTokensResultHistogram[] = @@ -232,7 +236,7 @@ // Expect that the TryGetAuthTokens call returned the given tokens. void ExpectTryGetAuthTokensResult( - std::vector<network::BlindSignedAuthToken> bsa_tokens) { + std::vector<BlindSignedAuthToken> bsa_tokens) { EXPECT_EQ(std::get<0>(tokens_future_.Get()), bsa_tokens); } @@ -258,12 +262,12 @@ content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; base::test::TestFuture< - const std::optional<std::vector<network::BlindSignedAuthToken>>&, + const std::optional<std::vector<BlindSignedAuthToken>>&, std::optional<base::Time>> tokens_future_; base::test::TestFuture<const std::optional<std::vector<net::ProxyChain>>&, - const std::optional<network::GeoHint>&> + const std::optional<GeoHint>&> proxy_list_future_; // Test environment for IdentityManager. This must come after the @@ -274,7 +278,7 @@ base::Time expiration_time_; // A convenient geo hint for fake tokens. - network::GeoHint geo_hint_; + GeoHint geo_hint_; base::HistogramTester histogram_tester_; @@ -307,7 +311,7 @@ EXPECT_EQ(bsa_->oauth_token(), "access_token"); EXPECT_EQ(bsa_->num_tokens(), 2); EXPECT_EQ(bsa_->proxy_layer(), quiche::ProxyLayer::kProxyB); - std::vector<network::BlindSignedAuthToken> expected; + std::vector<BlindSignedAuthToken> expected; expected.push_back(ip_protection::IpProtectionConfigProviderHelper:: CreateMockBlindSignedAuthTokenForTesting( "single-use-1", expiration_time_, geo_hint_) @@ -319,7 +323,7 @@ ExpectTryGetAuthTokensResult(std::move(expected)); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kSuccess, 1); + ip_protection::TryGetAuthTokensResult::kSuccess, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 1); } @@ -338,7 +342,7 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedBSAOther, 1); + ip_protection::TryGetAuthTokensResult::kFailedBSAOther, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -365,14 +369,14 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedBSAOther, 1); + ip_protection::TryGetAuthTokensResult::kFailedBSAOther, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } TEST_F(IpProtectionConfigProviderTest, TokenGeoHintContainsOnlyCountry) { primary_account_behavior_ = PrimaryAccountBehavior::kReturnsToken; - network::GeoHint geo_hint_country; + GeoHint geo_hint_country; geo_hint_country.country_code = "US"; bsa_->set_tokens( {ip_protection::IpProtectionConfigProviderHelper:: @@ -388,7 +392,7 @@ EXPECT_EQ(bsa_->oauth_token(), "access_token"); EXPECT_EQ(bsa_->num_tokens(), 2); EXPECT_EQ(bsa_->proxy_layer(), quiche::ProxyLayer::kProxyB); - std::vector<network::BlindSignedAuthToken> expected; + std::vector<BlindSignedAuthToken> expected; expected.push_back(ip_protection::IpProtectionConfigProviderHelper:: CreateMockBlindSignedAuthTokenForTesting( "single-use-1", expiration_time_, geo_hint_country) @@ -400,14 +404,14 @@ ExpectTryGetAuthTokensResult(std::move(expected)); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kSuccess, 1); + ip_protection::TryGetAuthTokensResult::kSuccess, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 1); } TEST_F(IpProtectionConfigProviderTest, TokenHasMissingGeoHint) { primary_account_behavior_ = PrimaryAccountBehavior::kReturnsToken; - network::GeoHint geo_hint; + GeoHint geo_hint; bsa_->set_tokens({ip_protection::IpProtectionConfigProviderHelper:: CreateBlindSignTokenForTesting( "single-use-1", expiration_time_, geo_hint)}); @@ -422,7 +426,7 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedBSAOther, 1); + ip_protection::TryGetAuthTokensResult::kFailedBSAOther, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -442,7 +446,7 @@ ip_protection::IpProtectionConfigProviderHelper::kBugBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedBSA400, 1); + ip_protection::TryGetAuthTokensResult::kFailedBSA400, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -462,7 +466,7 @@ ip_protection::IpProtectionConfigProviderHelper::kBugBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedBSA401, 1); + ip_protection::TryGetAuthTokensResult::kFailedBSA401, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -482,7 +486,7 @@ ip_protection::IpProtectionConfigProviderHelper::kNotEligibleBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedBSA403, 1); + ip_protection::TryGetAuthTokensResult::kFailedBSA403, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -502,7 +506,7 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedBSAOther, 1); + ip_protection::TryGetAuthTokensResult::kFailedBSAOther, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -523,7 +527,7 @@ EXPECT_EQ(bsa_->oauth_token(), "access_token"); EXPECT_EQ(bsa_->num_tokens(), 2); EXPECT_EQ(bsa_->proxy_layer(), quiche::ProxyLayer::kProxyA); - std::vector<network::BlindSignedAuthToken> expected; + std::vector<BlindSignedAuthToken> expected; expected.push_back(ip_protection::IpProtectionConfigProviderHelper:: CreateMockBlindSignedAuthTokenForTesting( "single-use-1", expiration_time_, geo_hint_) @@ -535,7 +539,7 @@ ExpectTryGetAuthTokensResult(std::move(expected)); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kSuccess, 1); + ip_protection::TryGetAuthTokensResult::kSuccess, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 1); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 1); } @@ -551,7 +555,7 @@ ip_protection::IpProtectionConfigProviderHelper::kTransientBackoff); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedOAuthTokenTransient, 1); + ip_protection::TryGetAuthTokensResult::kFailedOAuthTokenTransient, 1); } // Fetching OAuth token returns a persistent error. @@ -565,7 +569,7 @@ ExpectTryGetAuthTokensResultFailed(base::TimeDelta::Max()); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedOAuthTokenPersistent, 1); + ip_protection::TryGetAuthTokensResult::kFailedOAuthTokenPersistent, 1); } // No primary account. @@ -578,7 +582,7 @@ ExpectTryGetAuthTokensResultFailed(base::TimeDelta::Max()); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedNoAccount, 1); + ip_protection::TryGetAuthTokensResult::kFailedNoAccount, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 0); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -598,7 +602,7 @@ ExpectTryGetAuthTokensResultFailed(base::TimeDelta::Max()); histogram_tester_.ExpectUniqueSample( kTryGetAuthTokensResultHistogram, - IpProtectionTryGetAuthTokensResult::kFailedDisabledByUser, 1); + ip_protection::TryGetAuthTokensResult::kFailedDisabledByUser, 1); histogram_tester_.ExpectTotalCount(kOAuthTokenFetchHistogram, 0); histogram_tester_.ExpectTotalCount(kTokenBatchHistogram, 0); } @@ -641,7 +645,7 @@ GoogleServiceAuthError::State::INVALID_GAIA_CREDENTIALS)); base::test::TestFuture< - const std::optional<std::vector<network::BlindSignedAuthToken>>&, + const std::optional<std::vector<BlindSignedAuthToken>>&, std::optional<base::Time>> tokens_future; getter_->TryGetAuthTokens(1, network::mojom::IpProtectionProxyLayer::kProxyB, @@ -663,17 +667,16 @@ tokens_future.GetCallback()); identity_test_env_.WaitForAccessTokenRequestIfNecessaryAndRespondWithToken( "access_token", base::Time::Now()); - const std::optional<std::vector<network::BlindSignedAuthToken>>& tokens = - tokens_future - .Get<std::optional<std::vector<network::BlindSignedAuthToken>>>(); + const std::optional<std::vector<BlindSignedAuthToken>>& tokens = + tokens_future.Get<std::optional<std::vector<BlindSignedAuthToken>>>(); ASSERT_TRUE(tokens); } // Backoff calculations. TEST_F(IpProtectionConfigProviderTest, CalculateBackoff) { - using enum IpProtectionTryGetAuthTokensResult; + using enum ip_protection::TryGetAuthTokensResult; - auto check = [&](IpProtectionTryGetAuthTokensResult result, + auto check = [&](ip_protection::TryGetAuthTokensResult result, std::optional<base::TimeDelta> backoff, bool exponential) { SCOPED_TRACE(::testing::Message() << "result: " << static_cast<int>(result)); @@ -806,7 +809,7 @@ auto call_get_proxy_list = [this](bool expect_success) { base::test::TestFuture<const std::optional<std::vector<net::ProxyChain>>&, - const std::optional<network::GeoHint>&> + const std::optional<GeoHint>&> future; this->getter_->GetProxyList(future.GetCallback()); ASSERT_TRUE(future.Wait()); @@ -908,7 +911,7 @@ // Do a basic check of the token formats. TEST_F(IpProtectionConfigProviderTest, TokenFormat) { - network::BlindSignedAuthToken result = + BlindSignedAuthToken result = ip_protection::IpProtectionConfigProviderHelper:: CreateMockBlindSignedAuthTokenForTesting("single-use-1", expiration_time_, geo_hint_)
diff --git a/chrome/browser/password_manager/android/BUILD.gn b/chrome/browser/password_manager/android/BUILD.gn index 898871ee..f724928 100644 --- a/chrome/browser/password_manager/android/BUILD.gn +++ b/chrome/browser/password_manager/android/BUILD.gn
@@ -199,6 +199,8 @@ "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogFragment.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogMediator.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogProperties.java", + "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportFlowCoordinator.java", + "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossImportDialogCoordinator.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessReauthenticationHelper.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordListObserver.java", "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordManagerHandler.java", @@ -248,7 +250,9 @@ testonly = true sources = [ - "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogTest.java", + "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogCoordinatorTest.java", + "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportFlowCoordinatorTest.java", + "java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossImportDialogCoordinatorTest.java", "junit/src/org/chromium/chrome/browser/password_manager/ConfirmationDialogHelperTest.java", "junit/src/org/chromium/chrome/browser/password_manager/FakeCredentialManagerLauncherTest.java", "junit/src/org/chromium/chrome/browser/password_manager/FakePasswordManagerBackendSupportHelperTest.java", @@ -301,6 +305,7 @@ "//chrome/browser/settings:internal_java", "//chrome/browser/signin/services/android:java", "//chrome/browser/sync/android:java", + "//chrome/browser/sync/test/android:test_support_java", "//chrome/test/android:chrome_java_unit_test_support", "//components/browser_ui/bottomsheet/android:java", "//components/browser_ui/settings/android:java",
diff --git a/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossDialogSettingsCoordinator.java b/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossDialogSettingsCoordinator.java index f0aee47..bf6b9f01 100644 --- a/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossDialogSettingsCoordinator.java +++ b/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossDialogSettingsCoordinator.java
@@ -18,6 +18,10 @@ /** * Shows the warning to the user explaining why they are not able to access Google Password Manager. + * This warning is displayed when user tries to access Google Password Manager in 3 cases: 1) They + * don't have GMS Core installed. 2) They have an outdated GMS Core. 3) The local passwords + * migration to GMS Core failed. The user is then proposed to either update GMS Core (if it's a + * valid option) or to run the passwords export flow. */ public class PasswordAccessLossDialogSettingsCoordinator implements ModalDialogProperties.Controller { @@ -25,14 +29,14 @@ private ModalDialogManager mModalDialogManager; private @PasswordAccessLossWarningType int mWarningType; private Callback<Context> mLaunchGmsUpdate; - private Callback<Context> mLaunchExportFlow; + private Runnable mLaunchExportFlow; public void showPasswordAccessLossDialog( Context context, @NonNull ModalDialogManager modalDialogManager, @PasswordAccessLossWarningType int warningType, Callback<Context> launchGmsUpdate, - Callback<Context> launchExportFlow) { + Runnable launchExportFlow) { mContext = context; mModalDialogManager = modalDialogManager; mWarningType = warningType; @@ -144,7 +148,7 @@ switch (mWarningType) { case PasswordAccessLossWarningType.NO_GMS_CORE: case PasswordAccessLossWarningType.NEW_GMS_CORE_MIGRATION_FAILED: - mLaunchExportFlow.onResult(mContext); + mLaunchExportFlow.run(); break; case PasswordAccessLossWarningType.NO_UPM: case PasswordAccessLossWarningType.ONLY_ACCOUNT_UPM:
diff --git a/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossDialogSettingsCoordinatorTest.java b/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossDialogSettingsCoordinatorTest.java index 2e1d450c..35f2c567 100644 --- a/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossDialogSettingsCoordinatorTest.java +++ b/chrome/browser/password_manager/android/access_loss/java/src/org/chromium/chrome/browser/access_loss/PasswordAccessLossDialogSettingsCoordinatorTest.java
@@ -36,7 +36,7 @@ new FakeModalDialogManager(ModalDialogManager.ModalDialogType.APP); @Mock private Callback<Context> mLaunchGmsCoreUpdate; - @Mock private Callback<Context> mLaunchExportFlow; + @Mock private Runnable mLaunchExportFlow; @Before public void setUp() { @@ -102,7 +102,7 @@ Assert.assertNotNull(mDialogModel); mModalDialogManager.clickPositiveButton(); - verify(mLaunchExportFlow).onResult(any()); + verify(mLaunchExportFlow).run(); Assert.assertNull(mModalDialogManager.getShownDialogModel()); } @@ -118,7 +118,7 @@ Assert.assertNotNull(mDialogModel); mModalDialogManager.clickPositiveButton(); - verify(mLaunchExportFlow).onResult(any()); + verify(mLaunchExportFlow).run(); Assert.assertNull(mModalDialogManager.getShownDialogModel()); } }
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java index b7ab721..598ef442 100644 --- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/PasswordManagerHelper.java
@@ -39,7 +39,7 @@ import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerBackendException; import org.chromium.chrome.browser.password_manager.CredentialManagerLauncher.CredentialManagerError; import org.chromium.chrome.browser.password_manager.PasswordCheckupClientHelper.PasswordCheckBackendException; -import org.chromium.chrome.browser.password_manager.settings.PasswordAccessLossExportDialogCoordinator; +import org.chromium.chrome.browser.password_manager.settings.PasswordAccessLossExportFlowCoordinator; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.chrome.browser.profiles.ProfileKeyedMap; @@ -175,10 +175,10 @@ if (warningType != PasswordAccessLossWarningType.NONE) { // Always start export flow from Chrome main settings. If this is already being called // from main settings, then launch export flow right away. - Callback<Context> startExportFlow = + Runnable startExportFlow = referrer == ManagePasswordsReferrer.CHROME_SETTINGS - ? this::launchExportFlow - : PasswordManagerHelper::showMainSettingsAndStartExport; + ? () -> launchExportFlow(context, modalDialogManagerSupplier) + : () -> showMainSettingsAndStartExport(context); new PasswordAccessLossDialogSettingsCoordinator() .showPasswordAccessLossDialog( context, @@ -464,15 +464,17 @@ } } - public void launchExportFlow(Context context) { + public void launchExportFlow( + Context context, Supplier<ModalDialogManager> modalDialogManagerSupplier) { FragmentActivity activity = (FragmentActivity) ContextUtils.activityFromContext(context); assert activity != null : "Context is expected to be a fragment activity"; - new PasswordAccessLossExportDialogCoordinator(activity, mProfile).showExportDialog(); + new PasswordAccessLossExportFlowCoordinator(activity, mProfile, modalDialogManagerSupplier) + .startExportFlow(); } @VisibleForTesting - void launchTheCredentialManager( + public void launchTheCredentialManager( @ManagePasswordsReferrer int referrer, SyncService syncService, LoadingModalDialogCoordinator loadingDialogCoordinator,
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogCoordinator.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogCoordinator.java index 1c134d8..67a389d 100644 --- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogCoordinator.java +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogCoordinator.java
@@ -10,7 +10,6 @@ import android.view.LayoutInflater; import android.view.View; -import androidx.annotation.VisibleForTesting; import androidx.fragment.app.FragmentActivity; import org.chromium.chrome.browser.password_manager.PasswordStoreBridge; @@ -20,15 +19,23 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor; /** - * Coordinates the export flow. Ties the export flow, the dialog fragment and its content view - * together. + * Shows the dialog offering the user to export their passwords. If they accept, it runs the export + * flow, namely: 1) Serializes user passwords and saves them to the file on disk. 2) Removes all + * password from the profile store (it the previous step was successful). */ public class PasswordAccessLossExportDialogCoordinator { + public interface Observer { + void onPasswordsDeletionFinished(); + } + private final FragmentActivity mActivity; private final PasswordAccessLossExportDialogFragment mFragment; private final PasswordAccessLossExportDialogMediator mMediator; - public PasswordAccessLossExportDialogCoordinator(FragmentActivity activity, Profile profile) { + public PasswordAccessLossExportDialogCoordinator( + FragmentActivity activity, + Profile profile, + PasswordAccessLossExportDialogCoordinator.Observer exportDialogObserver) { mActivity = activity; View dialogView = LayoutInflater.from(mActivity) @@ -36,19 +43,12 @@ mFragment = new PasswordAccessLossExportDialogFragment(); mMediator = new PasswordAccessLossExportDialogMediator( - activity, profile, dialogView, mFragment, new PasswordStoreBridge(profile)); - initialize(dialogView); - } - - @VisibleForTesting - PasswordAccessLossExportDialogCoordinator( - FragmentActivity activity, - PasswordAccessLossExportDialogFragment fragment, - PasswordAccessLossExportDialogMediator mediator, - View dialogView) { - mActivity = activity; - mFragment = fragment; - mMediator = mediator; + activity, + profile, + dialogView.getId(), + mFragment, + new PasswordStoreBridge(profile), + exportDialogObserver); initialize(dialogView); } @@ -74,4 +74,8 @@ public void showExportDialog() { mFragment.show(mActivity.getSupportFragmentManager(), null); } + + public PasswordAccessLossExportDialogMediator getMediatorForTesting() { + return mMediator; + } }
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogTest.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogCoordinatorTest.java similarity index 85% rename from chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogTest.java rename to chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogCoordinatorTest.java index 32b62b98..cbcc3a6 100644 --- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogTest.java +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogCoordinatorTest.java
@@ -10,6 +10,7 @@ import static org.junit.Assert.assertFalse; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -20,8 +21,6 @@ import android.content.Intent; import android.content.res.Resources; import android.net.Uri; -import android.view.LayoutInflater; -import android.view.View; import android.widget.Button; import android.widget.TextView; @@ -32,7 +31,8 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; -import org.mockito.MockitoAnnotations; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; import org.robolectric.Robolectric; import org.robolectric.RuntimeEnvironment; import org.robolectric.annotation.Config; @@ -54,6 +54,7 @@ import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge; import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridgeJni; import org.chromium.chrome.browser.password_manager.PasswordStoreBridge; +import org.chromium.chrome.browser.password_manager.PasswordStoreBridgeJni; import org.chromium.chrome.browser.password_manager.R; import org.chromium.chrome.browser.preferences.Pref; import org.chromium.chrome.browser.profiles.Profile; @@ -67,18 +68,17 @@ import java.io.InputStream; import java.io.OutputStream; -/** Tests for {@link PasswordAccessLossExportDialogFragment} */ +/** Tests for {@link PasswordAccessLossExportDialogCoordinator} */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) @Batch(Batch.PER_CLASS) -public class PasswordAccessLossExportDialogTest { +public class PasswordAccessLossExportDialogCoordinatorTest { private static final Uri TEMP_EXPORT_FILE_URI = Uri.parse("tmp/fake/test/path/file.ext"); private static final Uri SAVED_EXPORT_FILE_URI = Uri.parse("fake/test/path/file.ext"); + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); @Rule public JniMocker mJniMocker = new JniMocker(); private PasswordAccessLossExportDialogCoordinator mCoordinator; - private PasswordAccessLossExportDialogMediator mMediator; - private PasswordAccessLossExportDialogFragment mFragment; private FragmentActivity mActivity; @Mock private Profile mProfile; @Mock private PrefService mPrefService; @@ -86,17 +86,19 @@ @Mock private FileProviderUtil mFileProviderUtil; @Mock private InputStream mInputStream; @Mock private OutputStream mOutputStream; - @Mock private PasswordStoreBridge mPasswordStoreBridge; + @Mock private PasswordStoreBridge.Natives mPasswordStoreBridgeJniMock; @Mock private UserPrefs.Natives mUserPrefsJniMock; @Mock private PasswordManagerUtilBridge.Natives mPasswordManagerUtilBridgeJniMock; + @Mock private PasswordAccessLossExportDialogCoordinator.Observer mPasswordsDeletionFinished; private FakePasswordManagerHandler mPasswordManagerHandler; @Before public void setUp() { - MockitoAnnotations.openMocks(this); + mJniMocker.mock(PasswordStoreBridgeJni.TEST_HOOKS, mPasswordStoreBridgeJniMock); mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsJniMock); mJniMocker.mock(PasswordManagerUtilBridgeJni.TEST_HOOKS, mPasswordManagerUtilBridgeJniMock); when(mProfileProvider.getOriginalProfile()).thenReturn(mProfile); + when(mProfile.getOriginalProfile()).thenReturn(mProfile); mActivity = Robolectric.buildActivity(BrowserUiDummyFragmentActivity.class) @@ -104,21 +106,15 @@ .start() .resume() .get(); - View dialogView = - LayoutInflater.from(mActivity) - .inflate(R.layout.password_access_loss_export_dialog_view, null); - mFragment = new PasswordAccessLossExportDialogFragment(); - mMediator = - new PasswordAccessLossExportDialogMediator( - mActivity, mProfile, dialogView, mFragment, mPasswordStoreBridge); mCoordinator = new PasswordAccessLossExportDialogCoordinator( - mActivity, mFragment, mMediator, dialogView); + mActivity, mProfile, mPasswordsDeletionFinished); } private void setUpPasswordManagerHandler() { // Fakes password manager provider needed for passwords serialization. - mPasswordManagerHandler = new FakePasswordManagerHandler(mMediator); + mPasswordManagerHandler = + new FakePasswordManagerHandler(mCoordinator.getMediatorForTesting()); PasswordManagerHandlerProvider provider = PasswordManagerHandlerProvider.getForProfile(mProfile); provider.setPasswordManagerHandlerForTest(mPasswordManagerHandler); @@ -127,11 +123,11 @@ private void setUpPasswordStoreBridge() { doAnswer( invocation -> { - mMediator.onSavedPasswordsChanged(0); + mCoordinator.getMediatorForTesting().onSavedPasswordsChanged(0); return null; }) - .when(mPasswordStoreBridge) - .clearAllPasswordsFromProfileStore(); + .when(mPasswordStoreBridgeJniMock) + .clearAllPasswordsFromProfileStore(anyLong()); } private void setUpReauthenticationManager() { @@ -155,10 +151,15 @@ private void setUpAccessLossWarningType(@PasswordAccessLossWarningType int type) { when(mPasswordManagerUtilBridgeJniMock.getPasswordAccessLossWarningType(any())) .thenReturn(type); + if (type == PasswordAccessLossWarningType.NEW_GMS_CORE_MIGRATION_FAILED) { + when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService); + when(mPrefService.getInteger(Pref.PASSWORDS_USE_UPM_LOCAL_AND_SEPARATE_STORES)) + .thenReturn(/* UseUpmLocalAndSeparateStoresState::kOffAndMigrationPending */ 1); + } } @Test - public void testDialogStrings() { + public void testExportDialogStrings() { mCoordinator.showExportDialog(); mActivity.getSupportFragmentManager().executePendingTransactions(); @@ -182,7 +183,7 @@ @EnableFeatures( ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_ACCESS_LOSS_WARNING) @DisableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PWD_MIGRATION_WARNING) - public void testPositiveButtonClick() throws IOException { + public void testExportFlow() throws IOException { mCoordinator.showExportDialog(); setUpPasswordManagerHandler(); setUpPasswordStoreBridge(); @@ -206,7 +207,7 @@ ReauthenticationManager.recordLastReauth( System.currentTimeMillis(), ReauthenticationManager.ReauthScope.BULK); // Simulates the `onResume` call after re-authentication. - mFragment.onResume(); + mCoordinator.getMediatorForTesting().onResume(); Robolectric.flushForegroundThreadScheduler(); ShadowActivity shadowActivity = shadowOf(mActivity); @@ -228,7 +229,7 @@ // Verify that writing to the exported file was called. verify(mInputStream, times(2)).read(any(byte[].class)); verify(mOutputStream).write(any(byte[].class), anyInt(), anyInt()); - verify(mPasswordStoreBridge).clearAllPasswordsFromProfileStore(); + verify(mPasswordStoreBridgeJniMock).clearAllPasswordsFromProfileStore(anyLong()); } @Test @@ -254,7 +255,7 @@ ReauthenticationManager.recordLastReauth( System.currentTimeMillis(), ReauthenticationManager.ReauthScope.BULK); // Simulates the `onResume` call after re-authentication. - mFragment.onResume(); + mCoordinator.getMediatorForTesting().onResume(); Robolectric.flushForegroundThreadScheduler(); // Dialog is expected to be dismissed now. @@ -269,26 +270,22 @@ // This test checks the edge case, when the export dialog was displayed, but the migration // succeeded in while it was showing. setUpAccessLossWarningType(PasswordAccessLossWarningType.NEW_GMS_CORE_MIGRATION_FAILED); - when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService); when(mPrefService.getInteger(Pref.PASSWORDS_USE_UPM_LOCAL_AND_SEPARATE_STORES)) .thenReturn(/* UseUpmLocalAndSeparateStoresState::kOn */ 2); - // setUpPasswordStoreBridge(); - // setUpSyncService(); - // setUpUpm(); // Notification that the export flow succeeded should trigger passwords deletion. - mMediator.onExportFlowSucceeded(); + mCoordinator.getMediatorForTesting().onExportFlowSucceeded(); Robolectric.flushForegroundThreadScheduler(); // Password deletion should not be triggered in this case (because it would remove passwords // from GMS Core). - verify(mPasswordStoreBridge, times(0)).clearAllPasswordsFromProfileStore(); + verify(mPasswordStoreBridgeJniMock, times(0)).clearAllPasswordsFromProfileStore(anyLong()); } @Test @EnableFeatures( ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_ACCESS_LOSS_WARNING) @DisableFeatures(ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PWD_MIGRATION_WARNING) - public void testNegativeButtonClick() { + public void testExportDialogNegativeButtonClick() { mCoordinator.showExportDialog(); mActivity.getSupportFragmentManager().executePendingTransactions();
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogMediator.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogMediator.java index 2697a72..9444bb8 100644 --- a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogMediator.java +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportDialogMediator.java
@@ -8,7 +8,6 @@ import android.content.Intent; import android.net.Uri; import android.os.Bundle; -import android.view.View; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; @@ -38,23 +37,26 @@ private final FragmentActivity mActivity; private final Profile mProfile; - private final View mDialogView; + private final int mDialogViewId; private final PasswordAccessLossExportDialogFragment mExportDialogFragment; private ExportFlow mExportFlow; private PasswordStoreBridge mPasswordStoreBridge; private DialogManager mProgressBarManager; + private final PasswordAccessLossExportDialogCoordinator.Observer mExportDialogObserver; public PasswordAccessLossExportDialogMediator( FragmentActivity activity, Profile profile, - View dialogView, + int dialogViewId, PasswordAccessLossExportDialogFragment exportDialogFragment, - PasswordStoreBridge passwordStoreBridge) { + PasswordStoreBridge passwordStoreBridge, + PasswordAccessLossExportDialogCoordinator.Observer exportDialogObserver) { mActivity = activity; mProfile = profile; - mDialogView = dialogView; + mDialogViewId = dialogViewId; mExportDialogFragment = exportDialogFragment; mPasswordStoreBridge = passwordStoreBridge; + mExportDialogObserver = exportDialogObserver; } public void handlePositiveButtonClicked() { @@ -78,7 +80,7 @@ @Override public int getViewId() { - return mDialogView.getId(); + return mDialogViewId; } @Override @@ -153,7 +155,7 @@ // was executing. In this case the `UseUpmLocalAndSeparateStoresState` preference would have // been changed to `kOn`; // TODO (crbug.com/354876446): Introduce passwords deleted metrics in a separate CL. - if (!shouldDeleteAllPAsswords()) { + if (!shouldDeleteAllPasswords()) { destroy(); return; } @@ -170,7 +172,7 @@ mPasswordStoreBridge.clearAllPasswordsFromProfileStore(); } - private boolean shouldDeleteAllPAsswords() { + private boolean shouldDeleteAllPasswords() { PrefService prefService = UserPrefs.get(mProfile); if (PasswordManagerHelper.getAccessLossWarningType(prefService) == PasswordAccessLossWarningType.NO_GMS_CORE) return true; @@ -185,6 +187,7 @@ destroy(); mPasswordStoreBridge.removeObserver(this); mPasswordStoreBridge.destroy(); + mExportDialogObserver.onPasswordsDeletionFinished(); }); }
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportFlowCoordinator.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportFlowCoordinator.java new file mode 100644 index 0000000..f7340eb --- /dev/null +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportFlowCoordinator.java
@@ -0,0 +1,83 @@ +// Copyright 2024 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.password_manager.settings; + +import androidx.annotation.VisibleForTesting; +import androidx.fragment.app.FragmentActivity; + +import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.access_loss.PasswordAccessLossWarningType; +import org.chromium.chrome.browser.password_manager.PasswordManagerHelper; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.sync.SyncServiceFactory; +import org.chromium.components.prefs.PrefService; +import org.chromium.components.sync.SyncService; +import org.chromium.components.user_prefs.UserPrefs; +import org.chromium.ui.modaldialog.ModalDialogManager; + +/** + * Coordinates the export flow for the password access loss warning. It can be triggered only if the + * user doesn't have GMS Core installed or if their local passwords migration failed. The flow has + * the following steps: 1) Displays the dialog offering to export passwords to the file on disk and + * clear the profile store (see {@link PasswordAccessLossExportDialogCoordinator}). 2) Displays the + * dialog instructing the user to import the passwords in GMS Core (see {@link + * PasswordAccessLossImportDialogCoordinator}). This step is executed only if GMS Core is installed + * and up to date. + */ +public class PasswordAccessLossExportFlowCoordinator + implements PasswordAccessLossExportDialogCoordinator.Observer { + private final FragmentActivity mActivity; + private final Profile mProfile; + private final Supplier<ModalDialogManager> mModalDialogManagerSupplier; + private final PasswordAccessLossExportDialogCoordinator mExportDialogCoordinator; + + public PasswordAccessLossExportFlowCoordinator( + FragmentActivity activity, + Profile profile, + Supplier<ModalDialogManager> modalDialogManagerSupplier) { + mActivity = activity; + mProfile = profile; + mModalDialogManagerSupplier = modalDialogManagerSupplier; + mExportDialogCoordinator = + new PasswordAccessLossExportDialogCoordinator(mActivity, mProfile, this); + } + + @VisibleForTesting + public PasswordAccessLossExportFlowCoordinator( + FragmentActivity activity, + Profile profile, + Supplier<ModalDialogManager> modalDialogManagerSupplier, + PasswordAccessLossExportDialogCoordinator exportDialogCoordinator) { + mActivity = activity; + mProfile = profile; + mModalDialogManagerSupplier = modalDialogManagerSupplier; + mExportDialogCoordinator = exportDialogCoordinator; + } + + public void startExportFlow() { + mExportDialogCoordinator.showExportDialog(); + } + + private void showImportInstructionDialog() { + SyncService syncService = SyncServiceFactory.getForProfile(mProfile); + PasswordManagerHelper passwordManagerHelper = PasswordManagerHelper.getForProfile(mProfile); + new PasswordAccessLossImportDialogCoordinator( + mActivity.getApplicationContext(), + syncService, + mModalDialogManagerSupplier, + passwordManagerHelper) + .showImportInstructionDialog(); + } + + @Override + public void onPasswordsDeletionFinished() { + PrefService prefService = UserPrefs.get(mProfile); + if (PasswordManagerHelper.getAccessLossWarningType(prefService) + != PasswordAccessLossWarningType.NEW_GMS_CORE_MIGRATION_FAILED) { + return; + } + showImportInstructionDialog(); + } +}
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportFlowCoordinatorTest.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportFlowCoordinatorTest.java new file mode 100644 index 0000000..d926720 --- /dev/null +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossExportFlowCoordinatorTest.java
@@ -0,0 +1,110 @@ +// Copyright 2024 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.password_manager.settings; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import androidx.fragment.app.FragmentActivity; + +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; +import org.robolectric.annotation.Config; + +import org.chromium.base.supplier.Supplier; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.Features.EnableFeatures; +import org.chromium.base.test.util.JniMocker; +import org.chromium.chrome.browser.access_loss.PasswordAccessLossWarningType; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridge; +import org.chromium.chrome.browser.password_manager.PasswordManagerUtilBridgeJni; +import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.sync.SyncServiceFactory; +import org.chromium.components.sync.SyncService; +import org.chromium.components.user_prefs.UserPrefs; +import org.chromium.components.user_prefs.UserPrefsJni; +import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; + +/** Tests for {@link PasswordAccessLossExportFlowCoordinator} */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +@Batch(Batch.PER_CLASS) +public class PasswordAccessLossExportFlowCoordinatorTest { + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); + @Rule public JniMocker mJniMocker = new JniMocker(); + @Mock private Profile mProfile; + @Mock private PasswordAccessLossExportDialogCoordinator mExportDialogCoordinator; + @Mock private PasswordManagerUtilBridge.Natives mPasswordManagerUtilBridgeJniMock; + @Mock private UserPrefs.Natives mUserPrefsJniMock; + private FragmentActivity mActivity; + private Supplier<ModalDialogManager> mModalDialogManagerSupplier; + private FakeModalDialogManager mModalDialogManager; + private PasswordAccessLossExportFlowCoordinator mCoordinator; + + @Before + public void setUp() { + mJniMocker.mock(PasswordManagerUtilBridgeJni.TEST_HOOKS, mPasswordManagerUtilBridgeJniMock); + mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsJniMock); + when(mProfile.getOriginalProfile()).thenReturn(mProfile); + mActivity = + Robolectric.buildActivity(FragmentActivity.class).create().start().resume().get(); + mModalDialogManager = new FakeModalDialogManager(ModalDialogManager.ModalDialogType.APP); + mModalDialogManagerSupplier = () -> mModalDialogManager; + mCoordinator = + new PasswordAccessLossExportFlowCoordinator( + mActivity, mProfile, mModalDialogManagerSupplier, mExportDialogCoordinator); + } + + private void setUpAccessLossWarningType(@PasswordAccessLossWarningType int type) { + when(mPasswordManagerUtilBridgeJniMock.getPasswordAccessLossWarningType(any())) + .thenReturn(type); + } + + private void setUpSyncService() { + SyncService syncService = Mockito.mock(SyncService.class); + SyncServiceFactory.setInstanceForTesting(syncService); + } + + @Test + public void testShowsExportDialog() { + mCoordinator.startExportFlow(); + verify(mExportDialogCoordinator).showExportDialog(); + } + + @Test + @EnableFeatures( + ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_ACCESS_LOSS_WARNING) + public void testShowsImportDialogWhenDeletionFinished() { + setUpAccessLossWarningType(PasswordAccessLossWarningType.NEW_GMS_CORE_MIGRATION_FAILED); + setUpSyncService(); + mCoordinator.onPasswordsDeletionFinished(); + + // Import dialog should be displayed. + Assert.assertNotNull(mModalDialogManager.getShownDialogModel()); + } + + @Test + @EnableFeatures( + ChromeFeatureList.UNIFIED_PASSWORD_MANAGER_LOCAL_PASSWORDS_ANDROID_ACCESS_LOSS_WARNING) + public void testDoesNotShowImportDialogForNoGmsCoreWarningType() { + setUpAccessLossWarningType(PasswordAccessLossWarningType.NO_GMS_CORE); + mCoordinator.onPasswordsDeletionFinished(); + + // Import dialog should not be displayed. + Assert.assertNull(mModalDialogManager.getShownDialogModel()); + } +}
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossImportDialogCoordinator.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossImportDialogCoordinator.java new file mode 100644 index 0000000..aefa969 --- /dev/null +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossImportDialogCoordinator.java
@@ -0,0 +1,111 @@ +// Copyright 2024 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.password_manager.settings; + +import android.content.Context; +import android.content.res.Resources; + +import org.chromium.base.supplier.Supplier; +import org.chromium.chrome.browser.loading_modal.LoadingModalDialogCoordinator; +import org.chromium.chrome.browser.password_manager.ManagePasswordsReferrer; +import org.chromium.chrome.browser.password_manager.PasswordManagerHelper; +import org.chromium.components.sync.SyncService; +import org.chromium.ui.modaldialog.DialogDismissalCause; +import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.modaldialog.ModalDialogManager.ModalDialogType; +import org.chromium.ui.modaldialog.ModalDialogProperties; +import org.chromium.ui.modaldialog.ModalDialogProperties.ButtonType; +import org.chromium.ui.modelutil.PropertyModel; + +/** + * Shows the dialog instructing the user to import their passwords into the GMS Core after they've + * been saved to the file on disk. It is displayed only if the user has up to date GMS Core + * installed. If user accepts, it redirects the user to Google Password Manager (GMS Core). + */ +public class PasswordAccessLossImportDialogCoordinator { + private class ModalDialogController implements ModalDialogProperties.Controller { + + @Override + public void onClick(PropertyModel model, int buttonType) { + if (buttonType == ButtonType.POSITIVE) { + launchCredentialManager(); + } + mModalDialogManagerSupplier + .get() + .dismissDialog( + model, + buttonType == ButtonType.POSITIVE + ? DialogDismissalCause.POSITIVE_BUTTON_CLICKED + : DialogDismissalCause.NEGATIVE_BUTTON_CLICKED); + } + + @Override + public void onDismiss(PropertyModel model, int dismissalCause) { + // This is called when the dialog is being dismissed and meant for cleanup. Nothing to + // clean up here. + } + } + + private final Context mContext; + private final SyncService mSyncService; + private final Supplier<ModalDialogManager> mModalDialogManagerSupplier; + private final PasswordManagerHelper mPasswordManagerHelper; + + public PasswordAccessLossImportDialogCoordinator( + Context context, + SyncService syncService, + Supplier<ModalDialogManager> modalDialogManagerSupplier, + PasswordManagerHelper passwordManagerHelper) { + mContext = context; + mSyncService = syncService; + mModalDialogManagerSupplier = modalDialogManagerSupplier; + mPasswordManagerHelper = passwordManagerHelper; + } + + public void showImportInstructionDialog() { + Resources resources = mContext.getResources(); + PropertyModel model = + new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS) + .with(ModalDialogProperties.CONTROLLER, new ModalDialogController()) + .with( + ModalDialogProperties.TITLE, + resources, + org.chromium.chrome.browser.password_manager.R.string + .access_loss_import_dialog_title) + .with( + ModalDialogProperties.MESSAGE_PARAGRAPH_1, + resources.getString( + org.chromium.chrome.browser.password_manager.R.string + .access_loss_import_dialog_desc)) + .with( + ModalDialogProperties.POSITIVE_BUTTON_TEXT, + resources, + org.chromium.chrome.browser.password_manager.R.string + .access_loss_import_dialog_positive_button_text) + .with( + ModalDialogProperties.BUTTON_STYLES, + ModalDialogProperties.ButtonStyles.PRIMARY_FILLED_NEGATIVE_OUTLINE) + .with( + ModalDialogProperties.NEGATIVE_BUTTON_TEXT, + resources, + org.chromium.chrome.browser.password_manager.R.string.cancel) + .build(); + mModalDialogManagerSupplier.get().showDialog(model, ModalDialogType.APP); + } + + private void launchCredentialManager() { + // TODO (crbug.com/356851810): Add new referrer and replace CHROME_SETTINGS referrer with + // the new one. + LoadingModalDialogCoordinator loadingDialogCoordinator = + LoadingModalDialogCoordinator.create(mModalDialogManagerSupplier, mContext); + mPasswordManagerHelper.launchTheCredentialManager( + ManagePasswordsReferrer.CHROME_SETTINGS, + mSyncService, + loadingDialogCoordinator, + mModalDialogManagerSupplier, + mContext, + null); + } +}
diff --git a/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossImportDialogCoordinatorTest.java b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossImportDialogCoordinatorTest.java new file mode 100644 index 0000000..b3681827 --- /dev/null +++ b/chrome/browser/password_manager/android/java/src/org/chromium/chrome/browser/password_manager/settings/PasswordAccessLossImportDialogCoordinatorTest.java
@@ -0,0 +1,120 @@ +// Copyright 2024 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.password_manager.settings; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.content.Context; +import android.content.res.Resources; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnit; +import org.mockito.junit.MockitoRule; +import org.robolectric.Robolectric; +import org.robolectric.RuntimeEnvironment; +import org.robolectric.annotation.Config; + +import org.chromium.base.supplier.Supplier; +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.base.test.util.Batch; +import org.chromium.chrome.browser.password_manager.ManagePasswordsReferrer; +import org.chromium.chrome.browser.password_manager.PasswordManagerHelper; +import org.chromium.components.sync.SyncService; +import org.chromium.ui.modaldialog.ModalDialogManager; +import org.chromium.ui.modaldialog.ModalDialogProperties; +import org.chromium.ui.modelutil.PropertyModel; +import org.chromium.ui.test.util.modaldialog.FakeModalDialogManager; + +/** Tests for {@link PasswordAccessLossImportDialogCoordinator} */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +@Batch(Batch.PER_CLASS) +public class PasswordAccessLossImportDialogCoordinatorTest { + @Rule public MockitoRule mMockitoRule = MockitoJUnit.rule(); + private PasswordAccessLossImportDialogCoordinator mCoordinator; + private Supplier<ModalDialogManager> mModalDialogManagerSupplier; + private FakeModalDialogManager mModalDialogManager; + private Context mContext; + @Mock private SyncService mSyncService; + @Mock private PasswordManagerHelper mPasswordManagerHelper; + + @Before + public void setUp() { + mModalDialogManager = new FakeModalDialogManager(ModalDialogManager.ModalDialogType.APP); + mModalDialogManagerSupplier = () -> mModalDialogManager; + mContext = RuntimeEnvironment.getApplication().getApplicationContext(); + mCoordinator = + new PasswordAccessLossImportDialogCoordinator( + mContext, + mSyncService, + mModalDialogManagerSupplier, + mPasswordManagerHelper); + } + + @Test + public void testImportDialogStrings() { + mCoordinator.showImportInstructionDialog(); + + PropertyModel model = mModalDialogManager.getShownDialogModel(); + Resources resources = RuntimeEnvironment.getApplication().getResources(); + assertEquals( + resources.getString( + org.chromium.chrome.browser.password_manager.R.string + .access_loss_import_dialog_title), + model.get(ModalDialogProperties.TITLE)); + assertEquals( + resources.getString( + org.chromium.chrome.browser.password_manager.R.string + .access_loss_import_dialog_desc), + model.get(ModalDialogProperties.MESSAGE_PARAGRAPH_1)); + assertEquals( + resources.getString( + org.chromium.chrome.browser.password_manager.R.string + .access_loss_import_dialog_positive_button_text), + model.get(ModalDialogProperties.POSITIVE_BUTTON_TEXT)); + assertEquals( + resources.getString(org.chromium.chrome.browser.password_manager.R.string.cancel), + model.get(ModalDialogProperties.NEGATIVE_BUTTON_TEXT)); + } + + @Test + public void testImportDialogOpensCredentialManager() { + mCoordinator.showImportInstructionDialog(); + Robolectric.flushForegroundThreadScheduler(); + + mModalDialogManager.clickPositiveButton(); + verify(mPasswordManagerHelper) + .launchTheCredentialManager( + eq(ManagePasswordsReferrer.CHROME_SETTINGS), + eq(mSyncService), + any(), + eq(mModalDialogManagerSupplier), + eq(mContext), + isNull()); + assertNull(mModalDialogManager.getShownDialogModel()); + } + + @Test + public void testCancelImportDialog() { + mCoordinator.showImportInstructionDialog(); + Robolectric.flushForegroundThreadScheduler(); + + mModalDialogManager.clickNegativeButton(); + verify(mPasswordManagerHelper, times(0)) + .launchTheCredentialManager(anyInt(), any(), any(), any(), any(), any()); + assertNull(mModalDialogManager.getShownDialogModel()); + } +}
diff --git a/chrome/browser/recent_tabs/BUILD.gn b/chrome/browser/recent_tabs/BUILD.gn index 83ad9b8..9608d84 100644 --- a/chrome/browser/recent_tabs/BUILD.gn +++ b/chrome/browser/recent_tabs/BUILD.gn
@@ -28,6 +28,7 @@ android_library("java") { srcjar_deps = [ ":jni_headers" ] sources = [ + "android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePane.java", "android/java/src/org/chromium/chrome/browser/recent_tabs/ForeignSessionHelper.java", "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsController.java", "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerDelegate.java", @@ -36,6 +37,7 @@ deps = [ "//base:base_java", "//chrome/browser/flags:java", + "//chrome/browser/hub:java", "//chrome/browser/profiles/android:java", "//chrome/browser/tab:java", "//chrome/browser/tabmodel:java", @@ -48,7 +50,10 @@ } android_library_factory("factory_java") { - sources = [ "internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java" ] + sources = [ + "internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneFactory.java", + "internal/android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java", + ] deps = [ ":java",
diff --git a/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePane.java b/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePane.java new file mode 100644 index 0000000..f552f1bb2 --- /dev/null +++ b/chrome/browser/recent_tabs/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePane.java
@@ -0,0 +1,10 @@ +// Copyright 2024 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.recent_tabs; + +import org.chromium.chrome.browser.hub.Pane; + +/** An interface for a CrossDevicePane instance. */ +public interface CrossDevicePane extends Pane {}
diff --git a/chrome/browser/recent_tabs/internal/BUILD.gn b/chrome/browser/recent_tabs/internal/BUILD.gn index 71f4e00..45748be 100644 --- a/chrome/browser/recent_tabs/internal/BUILD.gn +++ b/chrome/browser/recent_tabs/internal/BUILD.gn
@@ -15,6 +15,8 @@ ] sources = [ + "android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneFactory.java", + "android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneImpl.java", "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerFactory.java", "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsControllerImpl.java", "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinator.java", @@ -39,6 +41,8 @@ "//base:base_java", "//chrome/browser/feature_engagement:java", "//chrome/browser/flags:java", + "//chrome/browser/hub:factory_java", + "//chrome/browser/hub:java", "//chrome/browser/profiles/android:java", "//chrome/browser/recent_tabs:java", "//chrome/browser/tab:java", @@ -60,6 +64,7 @@ android_resources("java_resources") { deps = [ ":java_strings_grd", + "//chrome/android:chrome_app_java_resources", "//components/browser_ui/widget/android:java_resources", "//ui/android:ui_java_resources", ] @@ -100,6 +105,7 @@ testonly = true sources = [ + "android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneUnitTest.java", "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsCoordinatorUnitTest.java", "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsMediatorUnitTest.java", "android/java/src/org/chromium/chrome/browser/recent_tabs/RestoreTabsPromoSheetContentUnitTest.java", @@ -118,6 +124,7 @@ "//base/test:test_support_java", "//chrome/browser/feature_engagement:java", "//chrome/browser/flags:java", + "//chrome/browser/hub:java", "//chrome/browser/profiles/android:java", "//chrome/browser/recent_tabs:helper_java", "//chrome/browser/recent_tabs:java", @@ -129,6 +136,7 @@ "//components/sync_device_info:sync_device_info_java", "//third_party/android_deps:espresso_java", "//third_party/androidx:androidx_recyclerview_recyclerview_java", + "//third_party/androidx:androidx_test_core_java", "//third_party/androidx:androidx_test_runner_java", "//third_party/hamcrest:hamcrest_java", "//third_party/hamcrest:hamcrest_library_java",
diff --git a/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneFactory.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneFactory.java new file mode 100644 index 0000000..d5a18198 --- /dev/null +++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneFactory.java
@@ -0,0 +1,25 @@ +// Copyright 2024 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.recent_tabs; + +import android.content.Context; + +import androidx.annotation.NonNull; + +import java.util.function.DoubleConsumer; + +/** A factory interface for building a {@link CrossDevicePane} instance. */ +public class CrossDevicePaneFactory { + /** + * Create an instance of the {@link CrossDevicePane}. + * + * @param context Used to inflate UI. + * @param onToolbarAlphaChange Observer to notify when alpha changes during animations. + */ + public static CrossDevicePane create( + @NonNull Context context, @NonNull DoubleConsumer onToolbarAlphaChange) { + return new CrossDevicePaneImpl(context, onToolbarAlphaChange); + } +}
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CrossDevicePane.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneImpl.java similarity index 94% rename from chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CrossDevicePane.java rename to chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneImpl.java index 0a16541..60e49eb 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CrossDevicePane.java +++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneImpl.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.tasks.tab_management; +package org.chromium.chrome.browser.recent_tabs; import android.content.Context; import android.view.ViewGroup; @@ -26,7 +26,6 @@ import org.chromium.chrome.browser.hub.PaneHubController; import org.chromium.chrome.browser.hub.PaneId; import org.chromium.chrome.browser.hub.ResourceButtonData; -import org.chromium.chrome.tab_ui.R; import org.chromium.components.browser_ui.widget.MenuOrKeyboardActionController.MenuOrKeyboardActionHandler; import java.util.function.DoubleConsumer; @@ -35,7 +34,7 @@ * A {@link Pane} representing tabs from other devices. This feature is being migrated here from the * Recent Tabs page and used to exist under the foreign session tabs section. */ -public class CrossDevicePane implements Pane { +public class CrossDevicePaneImpl implements CrossDevicePane { private final Context mContext; private final DoubleConsumer mOnToolbarAlphaChange; private final FrameLayout mRootView; @@ -50,7 +49,7 @@ * @param context Used to inflate UI. * @param onToolbarAlphaChange Observer to notify when alpha changes during animations. */ - CrossDevicePane(@NonNull Context context, @NonNull DoubleConsumer onToolbarAlphaChange) { + CrossDevicePaneImpl(@NonNull Context context, @NonNull DoubleConsumer onToolbarAlphaChange) { mContext = context; mOnToolbarAlphaChange = onToolbarAlphaChange; mReferenceButtonSupplier.set(
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CrossDevicePaneUnitTest.java b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneUnitTest.java similarity index 96% rename from chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CrossDevicePaneUnitTest.java rename to chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneUnitTest.java index 289f355..3dfd701 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/CrossDevicePaneUnitTest.java +++ b/chrome/browser/recent_tabs/internal/android/java/src/org/chromium/chrome/browser/recent_tabs/CrossDevicePaneUnitTest.java
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -package org.chromium.chrome.browser.tasks.tab_management; +package org.chromium.chrome.browser.recent_tabs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -44,7 +44,7 @@ ApplicationProvider.getApplicationContext().setTheme(R.style.Theme_BrowserUI_DayNight); mCrossDevicePane = - new CrossDevicePane( + new CrossDevicePaneImpl( ApplicationProvider.getApplicationContext(), mOnToolbarAlphaChange); }
diff --git a/chrome/browser/recent_tabs/internal/android/java/strings/android_restore_tabs_strings.grd b/chrome/browser/recent_tabs/internal/android/java/strings/android_restore_tabs_strings.grd index 69dbc8a..e541013 100644 --- a/chrome/browser/recent_tabs/internal/android/java/strings/android_restore_tabs_strings.grd +++ b/chrome/browser/recent_tabs/internal/android/java/strings/android_restore_tabs_strings.grd
@@ -241,6 +241,11 @@ <message name="IDS_RESTORE_TABS_DEVICE_SCREEN_NOT_SELECTED_DESCRIPTION" desc="Accessibility string describing that no icon exists that indicates that a device is the currently selected one."> Not selected </message> + + <!-- Cross Device Pane Strings--> + <message name="IDS_ACCESSIBILITY_CROSS_DEVICE_TABS" desc="Content description for the button to show the cross device tabs UI."> + Tabs from other devices + </message> </messages> </release> </grit> \ No newline at end of file
diff --git a/chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ACCESSIBILITY_CROSS_DEVICE_TABS.png.sha1 b/chrome/browser/recent_tabs/internal/android/java/strings/android_restore_tabs_strings_grd/IDS_ACCESSIBILITY_CROSS_DEVICE_TABS.png.sha1 similarity index 100% rename from chrome/android/features/tab_ui/java/strings/android_chrome_tab_ui_strings_grd/IDS_ACCESSIBILITY_CROSS_DEVICE_TABS.png.sha1 rename to chrome/browser/recent_tabs/internal/android/java/strings/android_restore_tabs_strings_grd/IDS_ACCESSIBILITY_CROSS_DEVICE_TABS.png.sha1
diff --git a/chrome/browser/renderer_context_menu/link_to_text_menu_observer.cc b/chrome/browser/renderer_context_menu/link_to_text_menu_observer.cc index a309b47..7effe7a 100644 --- a/chrome/browser/renderer_context_menu/link_to_text_menu_observer.cc +++ b/chrome/browser/renderer_context_menu/link_to_text_menu_observer.cc
@@ -275,7 +275,8 @@ if (toast_features::IsEnabled(toast_features::kLinkToHighlightCopiedToast) && toast_controller_) { - toast_controller_->ShowToast(ToastParams(ToastId::kLinkToHighlightCopied)); + toast_controller_->MaybeShowToast( + ToastParams(ToastId::kLinkToHighlightCopied)); } // Log usage for Shared Highlighting promo.
diff --git a/chrome/browser/renderer_context_menu/render_view_context_menu.cc b/chrome/browser/renderer_context_menu/render_view_context_menu.cc index bd034f1..f302c3bd9 100644 --- a/chrome/browser/renderer_context_menu/render_view_context_menu.cc +++ b/chrome/browser/renderer_context_menu/render_view_context_menu.cc
@@ -3270,7 +3270,7 @@ WriteURLToClipboard(params_.unfiltered_link_url); #if !BUILDFLAG(IS_ANDROID) if (toast_features::IsEnabled(toast_features::kLinkCopiedToast)) { - GetBrowser()->GetFeatures().toast_controller()->ShowToast( + GetBrowser()->GetFeatures().toast_controller()->MaybeShowToast( ToastParams(ToastId::kLinkCopied)); } #endif @@ -3289,7 +3289,7 @@ ExecCopyImageAt(); #if !BUILDFLAG(IS_ANDROID) if (toast_features::IsEnabled(toast_features::kImageCopiedToast)) { - GetBrowser()->GetFeatures().toast_controller()->ShowToast( + GetBrowser()->GetFeatures().toast_controller()->MaybeShowToast( ToastParams(ToastId::kImageCopied)); } #endif
diff --git a/chrome/browser/resources/compose/app.html b/chrome/browser/resources/compose/app.html index 6160bbc..7a3bc55 100644 --- a/chrome/browser/resources/compose/app.html +++ b/chrome/browser/resources/compose/app.html
@@ -410,18 +410,6 @@ gap:45px; } -<if expr="is_win"> - :host([enable-ui-refinements]) #resultFooter { - gap: 22px; - } -</if> - -<if expr="is_linux"> - :host([enable-ui-refinements]) #resultFooter { - gap: 15px; - } -</if> - .footer-text { display: flex; align-items: start; @@ -432,18 +420,6 @@ line-height: 16px; } -<if expr="is_win"> - :host([enable-ui-refinements]) .footer-text { - gap: 4px; - } -</if> - -<if expr="is_linux"> - :host([enable-ui-refinements]) .footer-text { - gap: 2px; - } -</if> - .footer-text .icon-buttons-row { --cr-icon-size: 16px; margin-inline-end: 8px; @@ -699,13 +675,17 @@ hidden$="[[!showOnDeviceDogfoodFooter_(response_)]]" >$i18nRaw{onDeviceUsedFooter} </b> - <span hidden="[[!showOnDeviceDogfoodFooter_(response_)]]" + <!-- <span hidden="[[!showOnDeviceDogfoodFooter_(response_)]]" >$i18nRaw{dogfoodFooter}</span> <span hidden="[[!showDefaultResultFooter_(response_, enableUiRefinements)]]" >$i18nRaw{resultFooter}</span> <span hidden="[[!showRefinementsResultFooter_(response_, enableUiRefinements)]]" - >$i18nRaw{refinementsResultFooter}</span> + >$i18nRaw{refinementsResultFooter}</span> --> + <span hidden="[[!showOnDeviceDogfoodFooter_(response_)]]" + >$i18nRaw{dogfoodFooter}</span> + <span hidden="[[showOnDeviceDogfoodFooter_(response_)]]" + >$i18nRaw{resultFooter}</span> </div> <cr-feedback-buttons id="feedbackButtons" on-selected-option-changed="onFeedbackSelectedOptionChanged_"
diff --git a/chrome/browser/resources/compose/app.ts b/chrome/browser/resources/compose/app.ts index f63e840..7a1249e 100644 --- a/chrome/browser/resources/compose/app.ts +++ b/chrome/browser/resources/compose/app.ts
@@ -864,18 +864,6 @@ loadTimeData.getBoolean('enableOnDeviceDogfoodFooter'); } - private showDefaultResultFooter_(): boolean { - return !(Boolean(this.response_?.onDeviceEvaluationUsed) && - loadTimeData.getBoolean('enableOnDeviceDogfoodFooter')) && - !this.enableUiRefinements; - } - - private showRefinementsResultFooter_(): boolean { - return !(Boolean(this.response_?.onDeviceEvaluationUsed) && - loadTimeData.getBoolean('enableOnDeviceDogfoodFooter')) && - this.enableUiRefinements; - } - private undoButtonIcon_(): string { return this.enableUiRefinements ? 'compose:undo' : 'compose:mvpUndo'; }
diff --git a/chrome/browser/resources/data_sharing/data_sharing.ts b/chrome/browser/resources/data_sharing/data_sharing.ts index 5fe73499..3b9aaaf8 100644 --- a/chrome/browser/resources/data_sharing/data_sharing.ts +++ b/chrome/browser/resources/data_sharing/data_sharing.ts
@@ -8,13 +8,20 @@ import {BrowserProxy} from './browser_proxy.js'; -// Match 'flow' param from the loaded URL to invoke corresponding dialog. -const FLOW = { - share: 'share', - join: 'join', - manage: 'manage', -}; -Object.freeze(FLOW); +// Param names in loaded URL. Should match those in +// chrome/browser/ui/views/data_sharing/data_sharing_utils.cc. +enum UrlQueryParams { + FLOW = 'flow', + GROUP_ID = 'group_id', + TOKEN_SECRET = 'token_secret', + TAB_GROUP_ID = 'tab_group_id', +} + +enum FlowValues { + SHARE = 'share', + JOIN = 'join', + MANAGE = 'manage', +} let initialized: boolean = false; @@ -25,7 +32,7 @@ window.data_sharing_sdk.setOauthAccessToken({accessToken}); if (!initialized) { initialize(); - processUrl(); + processUrl(browserProxy); browserProxy.handler.showUI(); initialized = true; } @@ -34,25 +41,52 @@ } // TODO(pengchaocai): Test in follow up CLs. -async function processUrl() { +function processUrl(browserProxy: BrowserProxy) { const currentUrl = window.location.href; const params = new URL(currentUrl).searchParams; - const flow = params.get('flow'); - const groupId = params.get('group_id'); - const tokenSecret = params.get('token_secret'); + const flow = params.get(UrlQueryParams.FLOW); + const groupId = params.get(UrlQueryParams.GROUP_ID); + const tokenSecret = params.get(UrlQueryParams.TOKEN_SECRET); + const tabGroupId = params.get(UrlQueryParams.TAB_GROUP_ID); + + // Called with when the owner presses copy link in share dialog. + function makeTabGroupShared( + options: {groupId: string, tokenSecret?: string}) { + browserProxy.handler.associateTabGroupWithGroupId( + tabGroupId!, options.groupId); + } + + function getShareLink(params: {groupId: string, tokenSecret?: string}): + Promise<string> { + return browserProxy.handler + .getShareLink(params.groupId, params.tokenSecret!) + .then(res => res.url.url); + } switch (flow) { - case FLOW.share: - await window.data_sharing_sdk.runInviteFlow({}); + case FlowValues.SHARE: + window.data_sharing_sdk.runInviteFlow({ + getShareLink: (options: {groupId: string, tokenSecret?: string}): + Promise<string> => { + makeTabGroupShared(options); + return getShareLink(options); + }, + }); break; - case FLOW.join: + case FlowValues.JOIN: // group_id and token_secret cannot be null for join flow. - await window.data_sharing_sdk.runJoinFlow( + window.data_sharing_sdk.runJoinFlow( {groupId: groupId!, tokenSecret: tokenSecret!}); break; - case FLOW.manage: + case FlowValues.MANAGE: // group_id cannot be null for manage flow. - await window.data_sharing_sdk.runManageFlow({groupId: groupId!}); + window.data_sharing_sdk.runManageFlow({ + groupId: groupId!, + getShareLink: (options: {groupId: string, tokenSecret?: string}): + Promise<string> => { + return getShareLink(options); + }, + }); break; default: const debugContainer: HTMLDivElement|null =
diff --git a/chrome/browser/resources/data_sharing/data_sharing_dev.css b/chrome/browser/resources/data_sharing/data_sharing_dev.css index b2e481a1..ed8c56b 100644 --- a/chrome/browser/resources/data_sharing/data_sharing_dev.css +++ b/chrome/browser/resources/data_sharing/data_sharing_dev.css
@@ -2,7 +2,14 @@ * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ -#debug-container { +body { + /* TODO: Sharekit team should override/remove this when testing dialog + container settings. */ + width: 520px; + height: 500px; +} + + #debug-container { display: none; }
diff --git a/chrome/browser/resources/data_sharing/data_sharing_sdk.ts b/chrome/browser/resources/data_sharing/data_sharing_sdk.ts index 0b366aab..ed22089 100644 --- a/chrome/browser/resources/data_sharing/data_sharing_sdk.ts +++ b/chrome/browser/resources/data_sharing/data_sharing_sdk.ts
@@ -63,7 +63,7 @@ } declare type DataSharingSdkGetLink = (params: DataSharingSdkGetLinkParams) => - string; + Promise<string>; declare type DataSharingMemberRole = 'unknown' | 'member' | 'owner' | 'invitee' | 'applicant'; @@ -115,12 +115,28 @@ } export { }; +// Add something to the dialog to tell which flow it is. +function appendTextForTesting(text: string) { + const newDiv: HTMLDivElement = document.createElement('div'); + newDiv.textContent = text; + document.body.appendChild(newDiv); +} + window.data_sharing_sdk = { - setOauthAccessToken: () => void {}, - createGroup: () => Promise.resolve({ id: '', members: [] }), + setOauthAccessToken: () => void{}, + createGroup: () => Promise.resolve({id: '', members: []}), readGroups: () => Promise.resolve([]), - runJoinFlow: () => Promise.resolve({}), - runInviteFlow: () => Promise.resolve({}), - runManageFlow: () => Promise.resolve({}), - updateClearcut: () => void {}, + runJoinFlow: (): Promise<DataSharingSdkResponse> => { + appendTextForTesting('A fake join dialog'); + return Promise.resolve({}); + }, + runInviteFlow: (): Promise<DataSharingSdkResponse> => { + appendTextForTesting('A fake invite dialog'); + return Promise.resolve({}); + }, + runManageFlow: (): Promise<DataSharingSdkResponse> => { + appendTextForTesting('A fake manage dialog'); + return Promise.resolve({}); + }, + updateClearcut: () => void{}, };
diff --git a/chrome/browser/resources/downloads/BUILD.gn b/chrome/browser/resources/downloads/BUILD.gn index 2710b74..94f3f98 100644 --- a/chrome/browser/resources/downloads/BUILD.gn +++ b/chrome/browser/resources/downloads/BUILD.gn
@@ -17,19 +17,28 @@ # Files holding a Polymer element definition and have an equivalent .html file. web_component_files = [ - "bypass_warning_confirmation_dialog.ts", - "bypass_warning_confirmation_interstitial.ts", "item.ts", "manager.ts", - "toolbar.ts", ] non_web_component_files = [ "browser_proxy.ts", + "bypass_warning_confirmation_dialog.html.ts", + "bypass_warning_confirmation_dialog.ts", + "dangerous_download_interstitial.html.ts", + "dangerous_download_interstitial.ts", "data.ts", "downloads.ts", "icon_loader.ts", "search_service.ts", + "toolbar.html.ts", + "toolbar.ts", + ] + + css_files = [ + "bypass_warning_confirmation_dialog.css", + "dangerous_download_interstitial.css", + "toolbar.css", ] icons_html_files = [ "icons.html" ] @@ -38,6 +47,8 @@ icons_html_files += [ "internal/icons.html" ] } + html_to_wrapper_template = "detect" + mojo_files_deps = [ "//chrome/browser/ui/webui/downloads:mojo_bindings_ts__generator" ] mojo_files = [ @@ -47,6 +58,7 @@ ts_composite = true ts_definitions = [ "//tools/typescript/definitions/chrome_send.d.ts" ] ts_deps = [ + "//third_party/lit/v3_0:build_ts", "//third_party/polymer/v3_0:library", "//ui/webui/resources/cr_components/managed_footnote:build_ts", "//ui/webui/resources/cr_elements:build_ts",
diff --git a/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.css b/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.css new file mode 100644 index 0000000..bde06a9 --- /dev/null +++ b/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.css
@@ -0,0 +1,42 @@ +/* Copyright 2024 The Chromium Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +/* #css_wrapper_metadata_start + * #type=style-lit + * #scheme=relative + * #css_wrapper_metadata_end */ + +#body { + display: flex; +} + +.tonal-button { + margin-inline-end: 8px; +} + +#icon-wrapper, +cr-icon { + height: var(--cr-icon-size); + width: var(--cr-icon-size); + color: var(--google-red-700); +} + +@media (prefers-color-scheme: dark) { + #icon-wrapper, + cr-icon { + color: var(--google-red-300); + } +} + +#icon-wrapper { + margin-inline-end: 8px; +} + +#body-text { + color: var(--cr-primary-text-color); +} + +#file-name { + font-weight: bold; +}
diff --git a/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.html b/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.html deleted file mode 100644 index cad3ae0..0000000 --- a/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.html +++ /dev/null
@@ -1,68 +0,0 @@ -<style> - #body { - display: flex; - } - - .tonal-button { - margin-inline-end: 8px; - } - - #icon-wrapper, - iron-icon { - height: var(--cr-icon-size); - width: var(--cr-icon-size); - color: var(--google-red-700); - } - - @media (prefers-color-scheme: dark) { - #icon-wrapper, - iron-icon { - color: var(--google-red-300); - } - } - - #icon-wrapper { - margin-inline-end: 8px; - } - - #body-text { - color: var(--cr-primary-text-color); - } - - #file-name { - font-weight: bold; - } -</style> -<cr-dialog show-on-attach id="dialog"> - <div slot="title">$i18n{warningBypassDialogTitle}</div> - <div slot="body" id="body"> - <div id="icon-wrapper" role="img" - aria-label="$i18n{accessibleLabelDangerous}"> - <iron-icon icon="downloads:dangerous"></iron-icon> - </div> - <div id="body-text"> - <div id="file-name">[[fileName]]</div> - <div id="danger-description">$i18n{warningBypassPromptDescription}</div> - <div id="learn-more-link"> - <!-- noopener cuts off the script connection between chrome://downloads, - which has sensitive capabilities, and the newly opened web renderer, - which may be more readily compromised. --> - <a href="$i18n{blockedLearnMoreUrl}" target="_blank" rel="noopener"> - $i18n{warningBypassPromptLearnMoreLink} - </a> - </div> - </div> - </div> - <div slot="button-container"> - <cr-button class="tonal-button" on-click="onDownloadDangerousClick_" - id="download-dangerous-button"> - $i18n{controlKeepDangerous} - </cr-button> - <!-- The cancel button is the primary action because we don't want the user - to download the dangerous file. --> - <cr-button class="action-button" on-click="onCancelClick_" - id="cancel-button"> - $i18n{warningBypassDialogCancel} - </cr-button> - </div> -</cr-dialog>
diff --git a/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.html.ts b/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.html.ts new file mode 100644 index 0000000..0d7eba5 --- /dev/null +++ b/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.html.ts
@@ -0,0 +1,45 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {DownloadsBypassWarningConfirmationDialogElement} from './bypass_warning_confirmation_dialog.js'; + +export function getHtml(this: DownloadsBypassWarningConfirmationDialogElement) { + return html`<!--_html_template_start_--> +<cr-dialog show-on-attach id="dialog"> + <div slot="title">$i18n{warningBypassDialogTitle}</div> + <div slot="body" id="body"> + <div id="icon-wrapper" role="img" + aria-label="$i18n{accessibleLabelDangerous}"> + <cr-icon icon="downloads:dangerous"></cr-icon> + </div> + <div id="body-text"> + <div id="file-name">${this.fileName}</div> + <div id="danger-description">$i18n{warningBypassPromptDescription}</div> + <div id="learn-more-link"> + <!-- noopener cuts off the script connection between chrome://downloads, + which has sensitive capabilities, and the newly opened web renderer, + which may be more readily compromised. --> + <a href="$i18n{blockedLearnMoreUrl}" target="_blank" rel="noopener"> + $i18n{warningBypassPromptLearnMoreLink} + </a> + </div> + </div> + </div> + <div slot="button-container"> + <cr-button class="tonal-button" @click="${this.onDownloadDangerousClick_}" + id="download-dangerous-button"> + $i18n{controlKeepDangerous} + </cr-button> + <!-- The cancel button is the primary action because we don't want the user + to download the dangerous file. --> + <cr-button class="action-button" @click="${this.onCancelClick_}" + id="cancel-button"> + $i18n{warningBypassDialogCancel} + </cr-button> + </div> +</cr-dialog> +<!--_html_template_end_-->`; +}
diff --git a/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.ts b/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.ts index 70b45be..8191150 100644 --- a/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.ts +++ b/chrome/browser/resources/downloads/bypass_warning_confirmation_dialog.ts
@@ -3,71 +3,74 @@ // found in the LICENSE file. /** - * @fileoverview 'bypass-warning-confirmation-dialog' is the dialog that allows - * bypassing a download warning (keeping a file flagged as dangerous). A - * 'success' indicates the warning bypass was confirmed and the dangerous file - * was downloaded. + * @fileoverview 'downloads-bypass-warning-confirmation-dialog' is the dialog + * that allows bypassing a download warning (keeping a file flagged as + * dangerous). A 'success' indicates the warning bypass was confirmed and the + * dangerous file was downloaded. */ import 'chrome://resources/cr_elements/cr_button/cr_button.js'; import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; -import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; +import 'chrome://resources/cr_elements/cr_icon/cr_icon.js'; import {getInstance as getAnnouncerInstance} from 'chrome://resources/cr_elements/cr_a11y_announcer/cr_a11y_announcer.js'; import type {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; -import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; -import {getTemplate} from './bypass_warning_confirmation_dialog.html.js'; +import {getCss} from './bypass_warning_confirmation_dialog.css.js'; +import {getHtml} from './bypass_warning_confirmation_dialog.html.js'; -export interface DownloadBypassWarningConfirmationDialogElement { +export interface DownloadsBypassWarningConfirmationDialogElement { $: { dialog: CrDialogElement, }; } -const DownloadBypassWarningConfirmationDialogBase = PolymerElement; - -export class DownloadBypassWarningConfirmationDialogElement extends - DownloadBypassWarningConfirmationDialogBase { +export class DownloadsBypassWarningConfirmationDialogElement extends + CrLitElement { static get is() { - return 'download-bypass-warning-confirmation-dialog'; + return 'downloads-bypass-warning-confirmation-dialog'; } - static get template() { - return getTemplate(); + static override get styles() { + return getCss(); } - static get properties() { + override render() { + return getHtml.bind(this)(); + } + + static override get properties() { return { - fileName: String, + fileName: {type: String}, }; } - fileName: string; + fileName: string = ''; wasConfirmed(): boolean { return this.$.dialog.getNative().returnValue === 'success'; } - private onDownloadDangerousClick_() { + protected onDownloadDangerousClick_() { getAnnouncerInstance().announce( loadTimeData.getString('screenreaderSavedDangerous')); this.$.dialog.close(); } - private onCancelClick_() { + protected onCancelClick_() { this.$.dialog.cancel(); } } declare global { interface HTMLElementTagNameMap { - 'download-bypass-warning-confirmation-dialog': - DownloadBypassWarningConfirmationDialogElement; + 'downloads-bypass-warning-confirmation-dialog': + DownloadsBypassWarningConfirmationDialogElement; } } customElements.define( - DownloadBypassWarningConfirmationDialogElement.is, - DownloadBypassWarningConfirmationDialogElement); + DownloadsBypassWarningConfirmationDialogElement.is, + DownloadsBypassWarningConfirmationDialogElement);
diff --git a/chrome/browser/resources/downloads/bypass_warning_confirmation_interstitial.html b/chrome/browser/resources/downloads/bypass_warning_confirmation_interstitial.html deleted file mode 100644 index b98996e..0000000 --- a/chrome/browser/resources/downloads/bypass_warning_confirmation_interstitial.html +++ /dev/null
@@ -1,159 +0,0 @@ -<style> - #dialog { - align-items: flex-start; - background-color: var(--google-red-40); - border: none; - box-sizing: border-box; - color: white; - display: flex; - /*Value is contrived from phishing interstitial: - font-size = [(125% * 75%) / 81.25%] - phishing interstitial html font-size = 125% - phishing interstitial body font-size = 75% - download interstitial body font-size = 81.25% - */ - font-size: 115.38%; - height: 100vh; - justify-content: center; - max-height: 100vh; - max-width: 100vw; - width: 100vw; - } - - #interstitial-wrapper { - max-width: 600px; - margin-top: 14vh; - } - - #icon { - height: 72px; - width: 72px; - } - - #main-message { - margin: 30px 0; - } - - #title { - font-size: 1.6em; - font-weight: normal; - line-height: 1.25em; - margin-bottom: 16px; - } - - #button-container { - display: flex; - font-size: 0.875em; - justify-content: space-between; - padding-bottom: 30px; - } - - #backToSafetyButton { - background: white; - border: none; - color: var(--google-primary-40); - } - - #backToSafetyButton:hover { - background: var(--google-primary-90); - } - - #continueAnywayButton[disabled] { - opacity: 0.5; - } - - .secondary-button { - border: 1px solid #fff; - background: var(--google-red-40); - color: white; - } - - .secondary-button:hover { - background: var(--google-red-500); - text-decoration: none; - } - - a, - cr-button, - cr-radio-group { - color: white; - } - - cr-radio-button { - --cr-radio-button-checked-color: #fff; - --cr-radio-button-unchecked-color: #fff; - --cr-radio-group-item-padding: 8px; - } - - #survey-wrapper { - margin-bottom: 20px; - } - - #survey-title { - margin: 8px 0; - } -</style> -<dialog id="dialog"> - <div id="interstitial-wrapper"> - <div id="main-content"> - <div id="icon-wrapper" role="img" - aria-label="$i18n{accessibleLabelDangerous}"> - <cr-icon id="icon" icon="downloads:dangerous"></cr-icon> - </div> - <div id="main-message"> - <h1 id="title">$i18n{warningBypassInterstitialTitle}</h1> - <p>$i18n{warningBypassPromptDescription} - <!-- noopener cuts off the script connection between - chrome://downloads, which has sensitive capabilities, and the newly - opened web renderer, which may be more readily compromised. --> - <a href="$i18n{blockedLearnMoreUrl}" target="_blank" rel="noopener" - aria-label="$i18n{warningBypassPromptLearnMoreLinkAccessible}"> - $i18n{warningBypassPromptLearnMoreLink} - </a> - </p> - </div> - <div id="button-container"> - <cr-button class="secondary-button" id="continueAnywayButton" - on-click="onContinueAnywayClick_"> - $i18n{warningBypassInterstitialContinue} - </cr-button> - <cr-button id="backToSafetyButton" on-click="onBackToSafetyClick_"> - $i18n{warningBypassInterstitialCancel} - </cr-button> - </div> - </div> - <div hidden="[[hideSurveyAndDownloadButton_]]" - id="survey-and-download-button-wrapper"> - <div id="survey-wrapper"> - <p id="survey-title">$i18n{warningBypassInterstitialSurveyTitle}</p> - <cr-radio-group - aria-label="$i18n{warningBypassInterstitialSurveyTitleAccessible}" - selected="[[selectedRadioOption_]]" - on-selected-changed="onSelectedRadioOptionChanged_"> - <cr-radio-button name="CreatedFile" - label="$i18n{warningBypassInterstitialSurveyCreatedFileAccessible}" - hide-label-text> - <span aria-hidden="true"> - $i18n{warningBypassInterstitialSurveyCreatedFile} - </span> - </cr-radio-button> - <cr-radio-button name="TrustSite" - label="[[trustSiteLineAccessibleText]]" hide-label-text> - <span aria-hidden="true">[[trustSiteLine]]</span> - </cr-radio-button> - <cr-radio-button name="AcceptRisk" - label="$i18n{warningBypassInterstitialSurveyAcceptRiskAccessible}" - hide-label-text> - <span aria-hidden="true"> - $i18n{warningBypassInterstitialSurveyAcceptRisk} - </span> - </cr-radio-button> - </cr-radio-group> - </div> - <cr-button class="secondary-button" id="download-button" - on-click="onDownloadClick_"> - $i18n{warningBypassInterstitialDownload} - </cr-button> - </div> - </div> -</dialog>
diff --git a/chrome/browser/resources/downloads/dangerous_download_interstitial.css b/chrome/browser/resources/downloads/dangerous_download_interstitial.css new file mode 100644 index 0000000..af9508f --- /dev/null +++ b/chrome/browser/resources/downloads/dangerous_download_interstitial.css
@@ -0,0 +1,102 @@ +/* Copyright 2024 The Chromium Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +/* #css_wrapper_metadata_start + * #type=style-lit + * #scheme=relative + * #css_wrapper_metadata_end */ + + #dialog { + align-items: flex-start; + background-color: var(--google-red-40); + border: none; + box-sizing: border-box; + color: white; + display: flex; + /*Value is contrived from phishing interstitial: + font-size = [(125% * 75%) / 81.25%] + phishing interstitial html font-size = 125% + phishing interstitial body font-size = 75% + download interstitial body font-size = 81.25% + */ + font-size: 115.38%; + height: 100vh; + justify-content: center; + max-height: 100vh; + max-width: 100vw; + width: 100vw; + } + + #interstitial-wrapper { + max-width: 600px; + margin-top: 14vh; + } + + #icon { + height: 72px; + width: 72px; + } + + #main-message { + margin: 30px 0; + } + + #title { + font-size: 1.6em; + font-weight: normal; + line-height: 1.25em; + margin-bottom: 16px; + } + + #button-container { + display: flex; + font-size: 0.875em; + justify-content: space-between; + padding-bottom: 30px; + } + + #backToSafetyButton { + background: white; + border: none; + color: var(--google-primary-40); + } + + #backToSafetyButton:hover { + background: var(--google-primary-90); + } + + #continueAnywayButton[disabled] { + opacity: 0.5; + } + + .secondary-button { + border: 1px solid #fff; + background: var(--google-red-40); + color: white; + } + + .secondary-button:hover { + background: var(--google-red-500); + text-decoration: none; + } + + a, + cr-button, + cr-radio-group { + color: white; + } + + cr-radio-button { + --cr-radio-button-checked-color: #fff; + --cr-radio-button-unchecked-color: #fff; + --cr-radio-group-item-padding: 8px; + } + + #survey-wrapper { + margin-bottom: 20px; + } + + #survey-title { + margin: 8px 0; + }
diff --git a/chrome/browser/resources/downloads/dangerous_download_interstitial.html.ts b/chrome/browser/resources/downloads/dangerous_download_interstitial.html.ts new file mode 100644 index 0000000..f50f6337 --- /dev/null +++ b/chrome/browser/resources/downloads/dangerous_download_interstitial.html.ts
@@ -0,0 +1,77 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {DownloadsDangerousDownloadInterstitialElement} from './dangerous_download_interstitial.js'; + +export function getHtml(this: DownloadsDangerousDownloadInterstitialElement) { + return html`<!--_html_template_start_--> +<dialog id="dialog"> + <div id="interstitial-wrapper"> + <div id="main-content"> + <div id="icon-wrapper" role="img" + aria-label="$i18n{accessibleLabelDangerous}"> + <cr-icon id="icon" icon="downloads:dangerous"></cr-icon> + </div> + <div id="main-message"> + <h1 id="title">$i18n{warningBypassInterstitialTitle}</h1> + <p>$i18n{warningBypassPromptDescription} + <!-- noopener cuts off the script connection between + chrome://downloads, which has sensitive capabilities, and the newly + opened web renderer, which may be more readily compromised. --> + <a href="$i18n{blockedLearnMoreUrl}" target="_blank" rel="noopener" + aria-label="$i18n{warningBypassPromptLearnMoreLinkAccessible}"> + $i18n{warningBypassPromptLearnMoreLink} + </a> + </p> + </div> + <div id="button-container"> + <cr-button class="secondary-button" id="continueAnywayButton" + @click="${this.onContinueAnywayClick_}"> + $i18n{warningBypassInterstitialContinue} + </cr-button> + <cr-button id="backToSafetyButton" + @click="${this.onBackToSafetyClick_}"> + $i18n{warningBypassInterstitialCancel} + </cr-button> + </div> + </div> + <div ?hidden="${this.hideSurveyAndDownloadButton_}" + id="survey-and-download-button-wrapper"> + <div id="survey-wrapper"> + <p id="survey-title">$i18n{warningBypassInterstitialSurveyTitle}</p> + <cr-radio-group + aria-label="$i18n{warningBypassInterstitialSurveyTitleAccessible}" + .selected="${this.selectedRadioOption_}" + @selected-changed="${this.onSelectedRadioOptionChanged_}"> + <cr-radio-button name="CreatedFile" + label="$i18n{warningBypassInterstitialSurveyCreatedFileAccessible}" + hide-label-text> + <span aria-hidden="true"> + $i18n{warningBypassInterstitialSurveyCreatedFile} + </span> + </cr-radio-button> + <cr-radio-button name="TrustSite" + label="${this.trustSiteLineAccessibleText}" hide-label-text> + <span aria-hidden="true">${this.trustSiteLine}</span> + </cr-radio-button> + <cr-radio-button name="AcceptRisk" + label="$i18n{warningBypassInterstitialSurveyAcceptRiskAccessible}" + hide-label-text> + <span aria-hidden="true"> + $i18n{warningBypassInterstitialSurveyAcceptRisk} + </span> + </cr-radio-button> + </cr-radio-group> + </div> + <cr-button class="secondary-button" id="download-button" + @click="${this.onDownloadClick_}"> + $i18n{warningBypassInterstitialDownload} + </cr-button> + </div> + </div> +</dialog> +<!--_html_template_end_-->`; +}
diff --git a/chrome/browser/resources/downloads/bypass_warning_confirmation_interstitial.ts b/chrome/browser/resources/downloads/dangerous_download_interstitial.ts similarity index 79% rename from chrome/browser/resources/downloads/bypass_warning_confirmation_interstitial.ts rename to chrome/browser/resources/downloads/dangerous_download_interstitial.ts index d3da7fc..44db09cd 100644 --- a/chrome/browser/resources/downloads/bypass_warning_confirmation_interstitial.ts +++ b/chrome/browser/resources/downloads/dangerous_download_interstitial.ts
@@ -3,7 +3,7 @@ // found in the LICENSE file. /** - * @fileoverview 'bypass-warning-confirmation-interstitial' is the interstitial + * @fileoverview 'downloads-dangerous-download-interstitial' is the interstitial * that allows bypassing a download warning (keeping a file flagged as * dangerous). A 'success' indicates the warning interstitial was confirmed and * the dangerous file was downloaded. @@ -18,10 +18,11 @@ import type {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.js'; import {assert} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; -import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import {BrowserProxy} from './browser_proxy.js'; -import {getTemplate} from './bypass_warning_confirmation_interstitial.html.js'; +import {getCss} from './dangerous_download_interstitial.css.js'; +import {getHtml} from './dangerous_download_interstitial.html.js'; import type {PageHandlerInterface} from './downloads.mojom-webui.js'; import {DangerousDownloadInterstitialSurveyOptions as surveyOptions} from './downloads.mojom-webui.js'; @@ -34,44 +35,40 @@ } export class DownloadsDangerousDownloadInterstitialElement extends - PolymerElement { + CrLitElement { static get is() { return 'downloads-dangerous-download-interstitial'; } - static get template() { - return getTemplate(); + static override get styles() { + return getCss(); } - static get properties() { + override render() { + return getHtml.bind(this)(); + } + + static override get properties() { return { - bypassPromptItemId: String, - - hideSurveyAndDownloadButton_: { - type: Boolean, - value: true, - }, - - selectedRadioOption_: String, - - trustSiteLine: String, - - trustSiteLineAccessibleText: String, + bypassPromptItemId: {type: String}, + hideSurveyAndDownloadButton_: {type: Boolean}, + selectedRadioOption_: {type: String}, + trustSiteLine: {type: String}, + trustSiteLineAccessibleText: {type: String}, }; } - bypassPromptItemId: string; - trustSiteLine: string; - trustSiteLineAccessibleText: string; + bypassPromptItemId: string = ''; + trustSiteLine: string = ''; + trustSiteLineAccessibleText: string = ''; private boundKeydown_: ((e: KeyboardEvent) => void)|null = null; - private hideSurveyAndDownloadButton_: boolean; - private selectedRadioOption_: string; + protected hideSurveyAndDownloadButton_: boolean = true; + protected selectedRadioOption_?: string; private mojoHandler_: PageHandlerInterface|null = null; - override ready() { - super.ready(); + override firstUpdated() { this.mojoHandler_ = BrowserProxy.getInstance().handler; } @@ -110,14 +107,14 @@ document.body.addEventListener('keydown', this.boundKeydown_); } - private onBackToSafetyClick_() { + protected onBackToSafetyClick_() { this.$.dialog.close(); assert(!this.$.dialog.open); this.dispatchEvent( new CustomEvent('cancel', {bubbles: true, composed: true})); } - private onContinueAnywayClick_() { + protected onContinueAnywayClick_() { const continueAnywayButton = this.$.continueAnywayButton; assert(!!continueAnywayButton); continueAnywayButton.setAttribute('disabled', 'true'); @@ -133,11 +130,11 @@ this.bypassPromptItemId); } - private onDownloadClick_() { + protected onDownloadClick_() { getAnnouncerInstance().announce( loadTimeData.getString('screenreaderSavedDangerous')); - this.$.dialog.close(this.selectedRadioOption_); + this.$.dialog.close(this.selectedRadioOption_ || ''); assert(!this.$.dialog.open); this.dispatchEvent( new CustomEvent('close', {bubbles: true, composed: true})); @@ -159,7 +156,7 @@ this.boundKeydown_ = null; } - private onSelectedRadioOptionChanged_(e: CustomEvent<{value: string}>) { + protected onSelectedRadioOptionChanged_(e: CustomEvent<{value: string}>) { this.selectedRadioOption_ = e.detail.value; } }
diff --git a/chrome/browser/resources/downloads/downloads.ts b/chrome/browser/resources/downloads/downloads.ts index 67efb035..bb295d5 100644 --- a/chrome/browser/resources/downloads/downloads.ts +++ b/chrome/browser/resources/downloads/downloads.ts
@@ -7,7 +7,7 @@ export {CrToastManagerElement} from 'chrome://resources/cr_elements/cr_toast/cr_toast_manager.js'; export {loadTimeData} from 'chrome://resources/js/load_time_data.js'; export {BrowserProxy} from './browser_proxy.js'; -export {DownloadsDangerousDownloadInterstitialElement} from './bypass_warning_confirmation_interstitial.js'; +export {DownloadsDangerousDownloadInterstitialElement} from './dangerous_download_interstitial.js'; export {MojomData} from './data.js'; export {DangerType, PageCallbackRouter, PageHandlerInterface, PageRemote, SafeBrowsingState, State, TailoredWarningType} from './downloads.mojom-webui.js'; export {IconLoader, IconLoaderImpl} from './icon_loader.js';
diff --git a/chrome/browser/resources/downloads/manager.html b/chrome/browser/resources/downloads/manager.html index 454eae3..a5abc5f 100644 --- a/chrome/browser/resources/downloads/manager.html +++ b/chrome/browser/resources/downloads/manager.html
@@ -152,9 +152,9 @@ </downloads-dangerous-download-interstitial> </template> <template is="dom-if" if="[[!dangerousDownloadInterstitial_]]" restamp> - <download-bypass-warning-confirmation-dialog + <downloads-bypass-warning-confirmation-dialog file-name="[[computeBypassWarningDialogFileName_(bypassPromptItemId_)]]" on-close="onBypassWarningConfirmationDialogClose_"> - </download-bypass-warning-confirmation-dialog> + </downloads-bypass-warning-confirmation-dialog> </template> </template>
diff --git a/chrome/browser/resources/downloads/manager.ts b/chrome/browser/resources/downloads/manager.ts index ade85e5..5180106 100644 --- a/chrome/browser/resources/downloads/manager.ts +++ b/chrome/browser/resources/downloads/manager.ts
@@ -4,7 +4,7 @@ import './strings.m.js'; import './bypass_warning_confirmation_dialog.js'; -import './bypass_warning_confirmation_interstitial.js'; +import './dangerous_download_interstitial.js'; import './item.js'; import './toolbar.js'; import 'chrome://resources/cr_components/managed_footnote/managed_footnote.js'; @@ -27,7 +27,7 @@ import {Debouncer, PolymerElement, timeOut} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {BrowserProxy} from './browser_proxy.js'; -import type {DownloadsDangerousDownloadInterstitialElement as DangerousInterstitialElement} from './bypass_warning_confirmation_interstitial.js'; +import type {DownloadsDangerousDownloadInterstitialElement as DangerousInterstitialElement} from './dangerous_download_interstitial.js'; import type {MojomData} from './data.js'; import type {PageCallbackRouter, PageHandlerInterface} from './downloads.mojom-webui.js'; import {State} from './downloads.mojom-webui.js'; @@ -313,7 +313,7 @@ private onBypassWarningConfirmationDialogClose_() { const dialog = this.shadowRoot!.querySelector( - 'download-bypass-warning-confirmation-dialog'); + 'downloads-bypass-warning-confirmation-dialog'); assert(dialog); assert(this.bypassPromptItemId_ !== ''); assert(!!this.mojoHandler_);
diff --git a/chrome/browser/resources/downloads/toolbar.css b/chrome/browser/resources/downloads/toolbar.css new file mode 100644 index 0000000..c870b6f --- /dev/null +++ b/chrome/browser/resources/downloads/toolbar.css
@@ -0,0 +1,19 @@ +/* Copyright 2024 The Chromium Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. */ + +/* #css_wrapper_metadata_start + * #type=style-lit + * #scheme=relative + * #css_wrapper_metadata_end */ + +:host { + align-items: center; + display: flex; + min-height: 56px; +} + +#toolbar { + flex: 1; + min-width: 0; +}
diff --git a/chrome/browser/resources/downloads/toolbar.html b/chrome/browser/resources/downloads/toolbar.html deleted file mode 100644 index f578c84..0000000 --- a/chrome/browser/resources/downloads/toolbar.html +++ /dev/null
@@ -1,19 +0,0 @@ -<style include="cr-hidden-style"> - :host { - align-items: center; - display: flex; - min-height: 56px; - } - - #toolbar { - flex: 1; - min-width: 0; - } -</style> -<cr-toolbar id="toolbar" page-name="$i18n{title}" autofocus always-show-logo - search-prompt="$i18n{search}" clear-label="$i18n{clearSearch}" - spinner-active="{{spinnerActive}}" on-search-changed="onSearchChanged_"> - <cr-button id="clear-all" on-click="onClearAllClick_"> - $i18n{clearAll} - </cr-button> -</cr-toolbar>
diff --git a/chrome/browser/resources/downloads/toolbar.html.ts b/chrome/browser/resources/downloads/toolbar.html.ts new file mode 100644 index 0000000..513e50b --- /dev/null +++ b/chrome/browser/resources/downloads/toolbar.html.ts
@@ -0,0 +1,20 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {DownloadsToolbarElement} from './toolbar.js'; + +export function getHtml(this: DownloadsToolbarElement) { + return html`<!--_html_template_start_--> +<cr-toolbar id="toolbar" page-name="$i18n{title}" autofocus always-show-logo + search-prompt="$i18n{search}" clear-label="$i18n{clearSearch}" + .spinnerActive="${this.spinnerActive}" + @search-changed="${this.onSearchChanged_}"> + <cr-button id="clearAll" @click="${this.onClearAllClick_}"> + $i18n{clearAll} + </cr-button> +</cr-toolbar> +<!--_html_template_end_-->`; +}
diff --git a/chrome/browser/resources/downloads/toolbar.ts b/chrome/browser/resources/downloads/toolbar.ts index 588103a..f3d20d2e 100644 --- a/chrome/browser/resources/downloads/toolbar.ts +++ b/chrome/browser/resources/downloads/toolbar.ts
@@ -5,7 +5,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.js'; import 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.js'; import 'chrome://resources/cr_elements/cr_hidden_style.css.js'; -import 'chrome://resources/cr_elements/icons.html.js'; +import 'chrome://resources/cr_elements/icons_lit.html.js'; import 'chrome://resources/cr_elements/cr_shared_vars.css.js'; import 'chrome://resources/js/util.js'; import './strings.m.js'; @@ -14,55 +14,61 @@ import type {CrToolbarElement} from 'chrome://resources/cr_elements/cr_toolbar/cr_toolbar.js'; import {assert} from 'chrome://resources/js/assert.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; -import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {CrLitElement} from 'chrome://resources/lit/v3_0/lit.rollup.js'; +import type {PropertyValues} from 'chrome://resources/lit/v3_0/lit.rollup.js'; import {BrowserProxy} from './browser_proxy.js'; import type {MojomData} from './data.js'; import type {PageHandlerInterface} from './downloads.mojom-webui.js'; import {SearchService} from './search_service.js'; -import {getTemplate} from './toolbar.html.js'; +import {getCss} from './toolbar.css.js'; +import {getHtml} from './toolbar.html.js'; export interface DownloadsToolbarElement { $: { - 'toolbar': CrToolbarElement, + clearAll: HTMLElement, + toolbar: CrToolbarElement, }; } -export class DownloadsToolbarElement extends PolymerElement { +export class DownloadsToolbarElement extends CrLitElement { static get is() { return 'downloads-toolbar'; } - static get template() { - return getTemplate(); + static override get styles() { + return getCss(); } - static get properties() { + override render() { + return getHtml.bind(this)(); + } + + static override get properties() { return { - hasClearableDownloads: { - type: Boolean, - observer: 'updateClearAll_', - }, - - items: Array, - - spinnerActive: { - type: Boolean, - }, + hasClearableDownloads: {type: Boolean}, + items: {type: Array}, + spinnerActive: {type: Boolean}, }; } private mojoHandler_: PageHandlerInterface|null = null; hasClearableDownloads: boolean = false; - spinnerActive: boolean; + spinnerActive: boolean = false; items: MojomData[] = []; - /** @override */ - override ready() { - super.ready(); + override firstUpdated() { this.mojoHandler_ = BrowserProxy.getInstance().handler; } + override updated(changedProperties: PropertyValues<this>) { + super.updated(changedProperties); + + if (changedProperties.has('hasClearableDownloads')) { + this.updateClearAll_(); + } + } + /** @return Whether removal can be undone. */ canUndo(): boolean { return !this.isSearchFocused(); @@ -86,7 +92,7 @@ return this.$.toolbar.getSearchField().isSearchFocused(); } - private onClearAllClick_(e: Event) { + protected onClearAllClick_(e: Event) { assert(this.canClearAll()); this.mojoHandler_!.clearAll(); const canUndo = @@ -99,7 +105,7 @@ e.preventDefault(); } - private onSearchChanged_(event: CustomEvent<string>) { + protected onSearchChanged_(event: CustomEvent<string>) { const searchService = SearchService.getInstance(); if (searchService.search(event.detail)) { this.spinnerActive = searchService.isSearching(); @@ -113,8 +119,7 @@ } private updateClearAll_() { - this.shadowRoot!.querySelector<HTMLButtonElement>('#clear-all')!.hidden = - !this.canClearAll(); + this.$.clearAll.hidden = !this.canClearAll(); } }
diff --git a/chrome/browser/resources/new_tab_page/modules/v2/module_header.html b/chrome/browser/resources/new_tab_page/modules/v2/module_header.html index 7597d37..bd9f217 100644 --- a/chrome/browser/resources/new_tab_page/modules/v2/module_header.html +++ b/chrome/browser/resources/new_tab_page/modules/v2/module_header.html
@@ -7,7 +7,8 @@ </cr-icon-button> </div> -<cr-action-menu id="actionMenu"> +<cr-action-menu id="actionMenu" + role-description="$i18n{moduleHeaderMoreActionsMenu}"> ${this.menuItemGroups.map((group, index) => html` ${group.map(item => html` <button id="${item.action}" class="dropdown-item"
diff --git a/chrome/browser/resources/side_panel/customize_chrome/customize_toolbar/toolbar.css b/chrome/browser/resources/side_panel/customize_chrome/customize_toolbar/toolbar.css index fce9723..4f73819 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/customize_toolbar/toolbar.css +++ b/chrome/browser/resources/side_panel/customize_chrome/customize_toolbar/toolbar.css
@@ -38,6 +38,11 @@ margin: 16px 0; } +.category-title { + font-size: 12px; + font-weight: 500; +} + .sp-card > :first-child { margin-top: 0; }
diff --git a/chrome/browser/resources/side_panel/customize_chrome/customize_toolbar/toolbar.html.ts b/chrome/browser/resources/side_panel/customize_chrome/customize_toolbar/toolbar.html.ts index dcf4b45..404c013 100644 --- a/chrome/browser/resources/side_panel/customize_chrome/customize_toolbar/toolbar.html.ts +++ b/chrome/browser/resources/side_panel/customize_chrome/customize_toolbar/toolbar.html.ts
@@ -32,18 +32,20 @@ ${ this.categories_.map( (category, categoryIndex) => html` - <div class="choose-icons-row category-title">${category.displayName}</div> + <h3 class="choose-icons-row category-title">${category.displayName}</h3> ${ this.actions_.map( - (action) => action.category === category.id ? html` + (action) => action.category === category.id ? + html` <div class="toggle-container choose-icons-row"> <img class="toggle-icon" src="${action.iconUrl.url}"></img> <div class="toggle-title">${action.displayName}</div> <cr-toggle @change="${this.getActionToggleHandler_(action.id)}" - ?checked="${action.pinned}"></cr-toggle> + ?checked="${action.pinned}" aria-label="${ + action.displayName}"></cr-toggle> </div> ` : - '')} + '')} ${ categoryIndex !== this.categories_.length - 1 ? html`<hr class="sp-hr">` :
diff --git a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_browsertest.cc b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_browsertest.cc index 89b8cdd..1d96ff51 100644 --- a/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_browsertest.cc +++ b/chrome/browser/safe_browsing/extension_telemetry/extension_telemetry_service_browsertest.cc
@@ -93,17 +93,17 @@ extensions::ExtensionApiTest::SetUpOnMainThread(); host_resolver()->AddRule("*", "127.0.0.1"); - // Enable enterprise policy. Verify that enterprise reporting is enabled. + // Helper to set up enterprise reporting and enable by default. + event_report_validator_helper_ = std::make_unique< + enterprise_connectors::test::EventReportValidatorHelper>( + browser()->profile(), /*browser_test=*/true); + // Enable enterprise policy. enterprise_connectors::test::SetOnSecurityEventReporting( /*prefs=*/prefs(), /*enabled=*/true, /*enabled_event_names=*/{}, /*enabled_opt_in_events=*/ {{enterprise_connectors::kExtensionTelemetryEvent, {"*"}}}); - // Helper to set up enterprise reporting and enable by default. - event_report_validator_helper_ = std::make_unique< - enterprise_connectors::test::EventReportValidatorHelper>( - browser()->profile(), /*browser_test=*/true); } void TearDownOnMainThread() override {
diff --git a/chrome/browser/sessions/session_restore.cc b/chrome/browser/sessions/session_restore.cc index dfd3599..17dafb8 100644 --- a/chrome/browser/sessions/session_restore.cc +++ b/chrome/browser/sessions/session_restore.cc
@@ -27,7 +27,6 @@ #include "base/memory/weak_ptr.h" #include "base/metrics/field_trial.h" #include "base/metrics/histogram_macros.h" -#include "base/notimplemented.h" #include "base/observer_list.h" #include "base/ranges/algorithm.h" #include "base/run_loop.h" @@ -82,6 +81,7 @@ #include "components/keep_alive_registry/keep_alive_types.h" #include "components/keep_alive_registry/scoped_keep_alive.h" #include "components/saved_tab_groups/features.h" +#include "components/saved_tab_groups/saved_tab_group.h" #include "components/saved_tab_groups/tab_group_sync_service.h" #include "components/saved_tab_groups/types.h" #include "components/sessions/core/session_types.h" @@ -127,8 +127,9 @@ namespace { bool HasSingleNewTabPage(Browser* browser) { - if (browser->tab_strip_model()->count() != 1) + if (browser->tab_strip_model()->count() != 1) { return false; + } content::WebContents* active_tab = browser->tab_strip_model()->GetWebContentsAt(0); return active_tab->GetURL() == chrome::kChromeUINewTabURL || @@ -141,15 +142,17 @@ #if BUILDFLAG(IS_CHROMEOS_ASH) void ReportRestoredWindowCreated(aura::Window* window) { // Ash is not always initialized in unit tests. - if (!ash::Shell::HasInstance()) + if (!ash::Shell::HasInstance()) { return; + } const int32_t restore_window_id = window->GetProperty(app_restore::kRestoreWindowIdKey); // Restored window IDs are always non-zero. - if (restore_window_id == 0) + if (restore_window_id == 0) { return; + } ash::LoginUnlockThroughputRecorder* throughput_recorder = ash::Shell::Get()->login_unlock_throughput_recorder(); @@ -194,16 +197,18 @@ restore_started_(base::TimeTicks::Now()) { DCHECK(restore_browser_ || restore_apps_); - if (active_session_restorers == nullptr) + if (active_session_restorers == nullptr) { active_session_restorers = new std::set<SessionRestoreImpl*>(); + } // Only one SessionRestoreImpl should be operating on the profile at the // same time. std::set<SessionRestoreImpl*>::iterator it; for (it = active_session_restorers->begin(); it != active_session_restorers->end(); ++it) { - if ((*it)->profile_ == profile) + if ((*it)->profile_ == profile) { break; + } } DCHECK(it == active_session_restorers->end()); @@ -260,8 +265,9 @@ return browser; } - if (browser_) + if (browser_) { BrowserList::AddObserver(this); + } return browser_; } @@ -378,8 +384,9 @@ // BrowserListObserver: void OnBrowserRemoved(Browser* browser) override { if (browser == browser_) { - if (log_event_) + if (log_event_) { LogSessionServiceRestoreCanceledEvent(profile_); + } delete this; } } @@ -470,8 +477,9 @@ // AppSessionService. If one of them returns error, then |read_error_| is // true. So check whether |read_error_| has been set as true to prevent the // result is overwritten. - if (!read_error_) + if (!read_error_) { read_error_ = read_error; + } // Copy windows into windows_ so that we can combine both app and browser // windows together before doing a one-pass restore. @@ -490,8 +498,9 @@ // Don't let app restores set the active_window_id, or else it will // always bring the app to the forefront. - if (!for_apps) + if (!for_apps) { active_window_id_ = active_window_id; + } ProcessSessionWindowsIfReady(); } @@ -512,8 +521,9 @@ // For async restores, we need to early exit here if we aren't ready to // start restoring windows. - if (!got_all_sessions) + if (!got_all_sessions) { return; + } SortWindowsByWindowId(); @@ -534,11 +544,13 @@ // 2. we are restoring apps, we have both browser and app windows and // WebAppRegistryReady() has been called. bool IsReadyToProcessSessionWindows() const { - if (!restore_apps_) + if (!restore_apps_) { return got_browser_windows_; + } - if (!restore_browser_) + if (!restore_browser_) { return got_app_windows_ && web_app_registry_ready_; + } return (got_app_windows_ && got_browser_windows_ && web_app_registry_ready_); @@ -787,8 +799,9 @@ ash::BootTimesRecorder::Get()->AddLoginTimeMarker( "SessionRestore-CreatingTabs-End", false); #endif - if (browser_to_activate) + if (browser_to_activate) { browser_to_activate->window()->Activate(); + } // If last_normal_browser is NULL and startup_tabs_ is non-empty, // FinishedTabCreation will create a new TabbedBrowser and add the urls to @@ -905,8 +918,9 @@ // It's possible (particularly for foreign sessions) to receive a tab // without valid navigations. In that case, just skip it. // See crbug.com/154129. - if (tab.navigations.empty()) + if (tab.navigations.empty()) { return; + } SessionRestore::NotifySessionRestoreStartedLoadingTabs(); int selected_index = GetNavigationIndexToSelect(tab); @@ -949,11 +963,13 @@ restored_tabs.push_back(restored_tab); // If this isn't the selected tab, there's nothing else to do. - if (!is_selected_tab) + if (!is_selected_tab) { return; + } - if (browser != browser_) + if (browser != browser_) { did_show_browser = true; + } ShowBrowser(browser, browser->tab_strip_model()->GetIndexOfWebContents( web_contents)); } @@ -985,24 +1001,19 @@ void ProcessSavedGroup(Profile* profile, const tab_groups::LocalTabGroupID& local_id, std::optional<std::string> sync_id) { + tab_groups::TabGroupSyncService* service = + tab_groups::SavedTabGroupUtils::GetServiceForProfile(profile); + CHECK(service); + if (sync_id) { - tab_groups::TabGroupSyncService* service = - tab_groups::SavedTabGroupUtils::GetServiceForProfile(profile); - CHECK(service); const base::Uuid& sync_guid = base::Uuid::ParseLowercase(sync_id.value()); service->ConnectLocalTabGroup(sync_guid, local_id); } else if (tab_groups::IsTabGroupsSaveV2Enabled()) { - if (tab_groups::IsTabGroupSyncServiceDesktopMigrationEnabled()) { - NOTIMPLEMENTED(); - } else { - tab_groups::SavedTabGroupKeyedService* service = - tab_groups::SavedTabGroupServiceFactory::GetForProfile(profile); - CHECK(service); - - // Default save any groups that are not saved yet. This happens when - // a user goes from V1 of SavedTabGroups to V2 through an update. - service->SaveRestoredGroup(local_id); - } + // Default save any groups that are not saved yet. This happens when + // a user goes from V1 of SavedTabGroups to V2 through an update. + service->AddGroup( + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + local_id)); } } @@ -1052,8 +1063,9 @@ TabStripUserGestureDetails( TabStripUserGestureDetails::GestureType::kOther)); - if (browser_ == browser) + if (browser_ == browser) { return; + } browser->window()->Show(); browser->set_is_session_restore(false); @@ -1071,8 +1083,9 @@ } #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) int add_types = AddTabTypes::ADD_FORCE_INDEX; - if (is_first_tab) + if (is_first_tab) { add_types |= AddTabTypes::ADD_ACTIVE; + } NavigateParams params(browser, url, ui::PAGE_TRANSITION_AUTO_TOPLEVEL); params.disposition = is_first_tab ? WindowOpenDisposition::NEW_FOREGROUND_TAB @@ -1092,13 +1105,15 @@ Browser* browser_to_activate = last_normal_browser; StartupTabs normal_startup_tabs, startup_tabs_from_last_and_urls_pref; for (const StartupTab& startup_tab : startup_tabs) { - if (startup_tab.type == StartupTab::Type::kFromLastAndUrlsStartupPref) + if (startup_tab.type == StartupTab::Type::kFromLastAndUrlsStartupPref) { startup_tabs_from_last_and_urls_pref.push_back(startup_tab); - else + } else { normal_startup_tabs.push_back(startup_tab); + } } - if (last_normal_browser && !normal_startup_tabs.empty()) + if (last_normal_browser && !normal_startup_tabs.empty()) { AppendURLsToBrowser(last_normal_browser, normal_startup_tabs); + } if (!startup_tabs_from_last_and_urls_pref.empty()) { Browser::CreateParams params = Browser::CreateParams(profile_, /*user_gesture*/ false); @@ -1116,8 +1131,9 @@ void NotifySessionServiceOfRestoredTabs(Browser* browser, int initial_count) { SessionServiceBase* service = GetAppropriateSessionServiceForProfile(browser); - if (!service) + if (!service) { return; + } TabStripModel* tab_strip = browser->tab_strip_model(); for (int i = initial_count; i < tab_strip->count(); ++i) { service->TabRestored(tab_strip->GetWebContentsAt(i), @@ -1233,8 +1249,9 @@ profile->set_restored_last_session(true); #if BUILDFLAG(IS_CHROMEOS_LACROS) - if (!profile->IsMainProfile()) + if (!profile->IsMainProfile()) { behavior &= ~RESTORE_APPS; + } #endif // BUILDFLAG(IS_CHROMEOS_LACROS) LogSessionServiceRestoreInitiatedEvent(profile, (behavior & SYNCHRONOUS) != 0, @@ -1284,13 +1301,15 @@ // static void SessionRestore::OpenStartupPagesAfterCrash(Browser* browser) { WebContents* tab_to_clobber = nullptr; - if (HasSingleNewTabPage(browser)) + if (HasSingleNewTabPage(browser)) { tab_to_clobber = browser->tab_strip_model()->GetActiveWebContents(); + } StartupBrowserCreator::OpenStartupPages( browser, chrome::startup::IsProcessStartup::kYes); - if (tab_to_clobber && browser->tab_strip_model()->count() > 1) + if (tab_to_clobber && browser->tab_strip_model()->count() > 1) { chrome::CloseWebContents(browser, tab_to_clobber, true); + } } // static @@ -1324,8 +1343,9 @@ // static bool SessionRestore::IsRestoring(const Profile* profile) { - if (active_session_restorers == nullptr) + if (active_session_restorers == nullptr) { return false; + } for (SessionRestoreImpl* const active_session_restorer : *active_session_restorers) { if (active_session_restorer->profile() == profile) { @@ -1337,8 +1357,9 @@ // static bool SessionRestore::IsRestoringSynchronously() { - if (!active_session_restorers) + if (!active_session_restorers) { return false; + } for (const SessionRestoreImpl* const active_session_restorer : *active_session_restorers) { if (active_session_restorer->synchronous()) { @@ -1367,36 +1388,42 @@ // static void SessionRestore::OnTabLoaderFinishedLoadingTabs() { - if (!session_restore_started_) + if (!session_restore_started_) { return; + } session_restore_started_ = false; - for (auto& observer : *observers()) + for (auto& observer : *observers()) { observer.OnSessionRestoreFinishedLoadingTabs(); + } } // static void SessionRestore::NotifySessionRestoreStartedLoadingTabs() { - if (session_restore_started_) + if (session_restore_started_) { return; + } session_restore_started_ = true; - for (auto& observer : *observers()) + for (auto& observer : *observers()) { observer.OnSessionRestoreStartedLoadingTabs(); + } } // static void SessionRestore::OnWillRestoreTab(content::WebContents* web_contents) { - for (auto& observer : *observers()) + for (auto& observer : *observers()) { observer.OnWillRestoreTab(web_contents); + } } // static void SessionRestore::OnGotSession(Profile* profile, bool for_apps, int window_count) { - for (auto& observer : *observers()) + for (auto& observer : *observers()) { observer.OnGotSession(profile, for_apps, window_count); + } } // static
diff --git a/chrome/browser/supervised_user/supervised_user_browser_utils.cc b/chrome/browser/supervised_user/supervised_user_browser_utils.cc index 2fc15046..2e316d4 100644 --- a/chrome/browser/supervised_user/supervised_user_browser_utils.cc +++ b/chrome/browser/supervised_user/supervised_user_browser_utils.cc
@@ -163,21 +163,6 @@ #endif } -bool IsAuthenticatedSupervisedProfile(Profile* profile) { - signin::IdentityManager* identity_manager = - IdentityManagerFactory::GetForProfile(profile); - CHECK(identity_manager); - // Ignores unsupervised profiles. - if (IsPrimaryAccountSubjectToParentalControls(identity_manager) != - signin::Tribool::kTrue) { - return false; - } - supervised_user::ChildAccountService* child_account_service = - ChildAccountServiceFactory::GetForProfile(profile); - return child_account_service->GetGoogleAuthState() == - supervised_user::ChildAccountService::AuthState::AUTHENTICATED; -} - #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) std::string CreateReauthenticationInterstitial( content::NavigationHandle& navigation_handle, @@ -193,6 +178,7 @@ std::make_unique<SupervisedUserVerificationPage>( web_contents, profile->GetProfileUserName(), request_url, verification_purpose, child_account_service, + navigation_handle.GetNextPageUkmSourceId(), std::make_unique<SupervisedUserVerificationControllerClient>( web_contents, profile->GetPrefs(), g_browser_process->GetApplicationLocale(),
diff --git a/chrome/browser/supervised_user/supervised_user_browser_utils.h b/chrome/browser/supervised_user/supervised_user_browser_utils.h index ccc7ced..3d093ce 100644 --- a/chrome/browser/supervised_user/supervised_user_browser_utils.h +++ b/chrome/browser/supervised_user/supervised_user_browser_utils.h
@@ -55,10 +55,6 @@ // of the user. void AssertChildStatusOfTheUser(Profile* profile, bool is_child); -// Returns true if the profile has a supervised account authenticated in the -// content area. -bool IsAuthenticatedSupervisedProfile(Profile* profile); - #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) // Returns the html content of the reauthentication interstitial for blocked // sites. This interstitial is associated with the given NavigationHandle.
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc index 2bf583ce..1777a25 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle.cc
@@ -14,6 +14,7 @@ #include "base/task/single_thread_task_runner.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/signin/identity_manager_factory.h" #include "chrome/browser/supervised_user/supervised_user_browser_utils.h" #include "chrome/browser/supervised_user/supervised_user_navigation_observer.h" #include "chrome/browser/supervised_user/supervised_user_service_factory.h" @@ -198,6 +199,30 @@ } } +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) +// Whether to show a re-auth interstitial instead of the parent approval +// interstitial. +bool SupervisedUserNavigationThrottle::ShouldShowReauthInterstitial( + const Profile* profile) { + if (!base::FeatureList::IsEnabled( + supervised_user:: + kForceSupervisedUserReauthenticationForBlockedSites)) { + return false; + } + + signin::IdentityManager* identity_manager = + IdentityManagerFactory::GetForProfileIfExists(profile); + CHECK(identity_manager); + + // Show the re-auth interstitial if the account is in a persistent error + // state. If the error state is transient, show the approval interstitial + // instead (an approval request will either succeed, or display a "try again + // later" message). + return identity_manager->HasAccountWithRefreshTokenInPersistentErrorState( + identity_manager->GetPrimaryAccountId(signin::ConsentLevel::kSignin)); +} +#endif + void SupervisedUserNavigationThrottle::OnInterstitialResult( CallbackActions action, bool already_sent_request, @@ -213,10 +238,7 @@ navigation_handle()->GetWebContents()->GetBrowserContext()); #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) - if (base::FeatureList::IsEnabled( - supervised_user:: - kForceSupervisedUserReauthenticationForBlockedSites) && - !supervised_user::IsAuthenticatedSupervisedProfile(profile)) { + if (ShouldShowReauthInterstitial(profile)) { // Show the re-authentication interstitial if the user signed out of the // content area, as parent's approval requires authentication. This // interstitial is only available on Linux/Mac/Windows as ChromeOS and @@ -231,6 +253,7 @@ return; } #endif + std::string interstitial_html = supervised_user::SupervisedUserInterstitial::GetHTMLContents( SupervisedUserServiceFactory::GetForProfile(profile),
diff --git a/chrome/browser/supervised_user/supervised_user_navigation_throttle.h b/chrome/browser/supervised_user/supervised_user_navigation_throttle.h index d82f8c1..b7bb16f 100644 --- a/chrome/browser/supervised_user/supervised_user_navigation_throttle.h +++ b/chrome/browser/supervised_user/supervised_user_navigation_throttle.h
@@ -17,6 +17,8 @@ #include "components/supervised_user/core/common/supervised_users.h" #include "content/public/browser/navigation_throttle.h" +class Profile; + class SupervisedUserNavigationThrottle : public content::NavigationThrottle { public: enum CallbackActions { kCancelNavigation = 0, kCancelWithInterstitial }; @@ -61,6 +63,10 @@ supervised_user::FilteringBehaviorReason reason, bool uncertain); +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_WIN) + bool ShouldShowReauthInterstitial(const Profile* profile); +#endif + void OnInterstitialResult(CallbackActions continue_request, bool already_requested_permission, bool is_main_frame);
diff --git a/chrome/browser/supervised_user/supervised_user_verification_page.cc b/chrome/browser/supervised_user/supervised_user_verification_page.cc index c3a3d08..c901810 100644 --- a/chrome/browser/supervised_user/supervised_user_verification_page.cc +++ b/chrome/browser/supervised_user/supervised_user_verification_page.cc
@@ -13,6 +13,9 @@ #include "components/strings/grit/components_strings.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/web_contents.h" +#include "services/metrics/public/cpp/metrics_utils.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_recorder.h" #include "ui/base/l10n/l10n_util.h" using security_interstitials::MetricsHelper; @@ -28,6 +31,7 @@ const GURL& request_url, VerificationPurpose verification_purpose, supervised_user::ChildAccountService* child_account_service, + ukm::SourceId source_id, std::unique_ptr< security_interstitials::SecurityInterstitialControllerClient> controller_client) @@ -38,15 +42,16 @@ email_to_reauth_(email_to_reauth), request_url_(request_url), verification_purpose_(verification_purpose), - child_account_service_(child_account_service) { + child_account_service_(child_account_service), + source_id_(source_id) { if (child_account_service_) { // Reloads the interstitial to continue navigation once the supervised user // is authenticated. google_auth_state_subscription_ = child_account_service_->ObserveGoogleAuthState(base::BindRepeating( - &security_interstitials::SecurityInterstitialControllerClient:: - Reload, - base::Unretained(this->controller()))); + &SupervisedUserVerificationPage::OnReauthenticationCompleted, + base::Unretained(this))); + RecordYouTubeReauthStatusUkm(Status::SHOWN); } } @@ -57,6 +62,11 @@ return SupervisedUserVerificationPage::kTypeForTesting; } +void SupervisedUserVerificationPage::OnReauthenticationCompleted() { + RecordYouTubeReauthStatusUkm(Status::REAUTH_COMPLETED); + controller()->Reload(); +} + void SupervisedUserVerificationPage::PopulateInterstitialStrings( base::Value::Dict& load_time_data) { PopulateStringsForSharedHTML(load_time_data); @@ -118,6 +128,30 @@ load_time_data.Set("type", "SUPERVISED_USER_VERIFY"); } +void SupervisedUserVerificationPage::RecordYouTubeReauthStatusUkm( + Status status) { + if (verification_purpose_ != VerificationPurpose::REAUTH_REQUIRED_SITE) { + return; + } + + auto builder = + ukm::builders::FamilyLinkUser_ReauthenticationInterstitial(source_id_); + switch (status) { + case Status::SHOWN: + builder.SetInterstitialShown(true); + break; + case Status::REAUTH_STARTED: + builder.SetReauthenticationStarted(true); + break; + case Status::REAUTH_COMPLETED: + builder.SetReauthenticationCompleted(true); + break; + default: + NOTREACHED_NORETURN(); + } + builder.Record(ukm::UkmRecorder::Get()); +} + void SupervisedUserVerificationPage::CommandReceived( const std::string& command) { if (command == "\"pageLoadComplete\"") { @@ -131,6 +165,7 @@ switch (cmd) { case security_interstitials::CMD_OPEN_LOGIN: + RecordYouTubeReauthStatusUkm(Status::REAUTH_STARTED); controller()->OpenUrlInNewForegroundTab( signin::GetChromeReauthURL({.email = email_to_reauth_})); break;
diff --git a/chrome/browser/supervised_user/supervised_user_verification_page.h b/chrome/browser/supervised_user/supervised_user_verification_page.h index b83bc97..c093e261 100644 --- a/chrome/browser/supervised_user/supervised_user_verification_page.h +++ b/chrome/browser/supervised_user/supervised_user_verification_page.h
@@ -13,6 +13,7 @@ #include "components/security_interstitials/content/security_interstitial_page.h" #include "components/supervised_user/core/browser/child_account_service.h" #include "content/public/browser/web_contents.h" +#include "services/metrics/public/cpp/ukm_source_id.h" class GURL; @@ -30,6 +31,9 @@ // parent's approvals require re-authentication. }; + // The status of the interstitial used for metrics recording purposes. + enum class Status { SHOWN, REAUTH_STARTED, REAUTH_COMPLETED }; + // Interstitial type, used in tests. static const security_interstitials::SecurityInterstitialPage::TypeID kTypeForTesting; @@ -44,6 +48,7 @@ const GURL& request_url, VerificationPurpose verification_purpose, supervised_user::ChildAccountService* child_account_service, + ukm::SourceId source_id, std::unique_ptr< security_interstitials::SecurityInterstitialControllerClient> controller_client); @@ -59,6 +64,9 @@ security_interstitials::SecurityInterstitialPage::TypeID GetTypeForTesting() override; + // Reloads the interstitial page and records metrics if necessary. + void OnReauthenticationCompleted(); + protected: void CommandReceived(const std::string& command) override; void PopulateInterstitialStrings(base::Value::Dict& load_time_data) override; @@ -67,11 +75,13 @@ private: void PopulateStringsForSharedHTML(base::Value::Dict& load_time_data); + void RecordYouTubeReauthStatusUkm(Status status); base::CallbackListSubscription google_auth_state_subscription_; const std::string email_to_reauth_; const GURL request_url_; const VerificationPurpose verification_purpose_; raw_ptr<supervised_user::ChildAccountService> child_account_service_; + ukm::SourceId source_id_; }; #endif // CHROME_BROWSER_SUPERVISED_USER_SUPERVISED_USER_VERIFICATION_PAGE_H_
diff --git a/chrome/browser/supervised_user/supervised_user_verification_page_browsertest.cc b/chrome/browser/supervised_user/supervised_user_verification_page_browsertest.cc new file mode 100644 index 0000000..9221da7 --- /dev/null +++ b/chrome/browser/supervised_user/supervised_user_verification_page_browsertest.cc
@@ -0,0 +1,191 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/supervised_user/supervised_user_verification_page.h" + +#include "base/test/metrics/histogram_tester.h" +#include "base/test/run_until.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/supervised_user/child_accounts/child_account_service_factory.h" +#include "chrome/browser/supervised_user/supervised_user_browser_utils.h" +#include "chrome/browser/supervised_user/supervised_user_verification_controller_client.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "chrome/test/base/mixin_based_in_process_browser_test.h" +#include "chrome/test/base/testing_browser_process.h" +#include "chrome/test/base/testing_profile.h" +#include "chrome/test/base/testing_profile_manager.h" +#include "chrome/test/base/ui_test_utils.h" +#include "chrome/test/supervised_user/supervision_mixin.h" +#include "components/google/core/common/google_util.h" +#include "components/supervised_user/core/browser/child_account_service.h" +#include "components/ukm/test_ukm_recorder.h" +#include "content/public/browser/web_contents.h" +#include "content/public/test/browser_test.h" +#include "content/public/test/browser_test_utils.h" +#include "content/public/test/mock_navigation_handle.h" +#include "content/public/test/test_navigation_observer.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_source_id.h" + +namespace { + +using VerificationPurpose = SupervisedUserVerificationPage::VerificationPurpose; + +// A NavigationThrottle that shows the verification interstitial. +class SupervisedUserVerificationPageTestingNavigationThrottle + : public content::NavigationThrottle { + public: + explicit SupervisedUserVerificationPageTestingNavigationThrottle( + content::NavigationHandle* handle) + : content::NavigationThrottle(handle) {} + + // content::NavigationThrottle: + const char* GetNameForLogging() override { + return "SupervisedUserVerificationPageTestingNavigationThrottle"; + } + + private: + // content::NavigationThrottle: + content::NavigationThrottle::ThrottleCheckResult WillFailRequest() override { + CHECK(navigation_handle()->IsInPrimaryMainFrame()); + + content::WebContents* web_contents = navigation_handle()->GetWebContents(); + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + supervised_user::ChildAccountService* child_account_service = + ChildAccountServiceFactory::GetForProfile(profile); + CHECK(child_account_service); + // Do not show the interstitial for authenticated supervised users. + // TODO(362132528): We are only testing AuthState::AUTHENTICATED and + // AuthState::NOT_AUTHENTICATED. We will show the interstitial exclusively + // for AuthState::PENDING once it is set up. + if (child_account_service->GetGoogleAuthState() == + supervised_user::ChildAccountService::AuthState::AUTHENTICATED) { + return content::NavigationThrottle::PROCEED; + } + + VerificationPurpose verification_purpose = + VerificationPurpose::BLOCKED_SITE; + + // Show the appropriate re-auth interstitial for YouTube navigation. + if (google_util::IsYoutubeDomainUrl( + navigation_handle()->GetURL(), google_util::ALLOW_SUBDOMAIN, + google_util::ALLOW_NON_STANDARD_PORTS)) { + verification_purpose = VerificationPurpose::REAUTH_REQUIRED_SITE; + } + + std::string interstitial_html = + supervised_user::CreateReauthenticationInterstitial( + *navigation_handle(), verification_purpose); + return {CANCEL, net::ERR_CERT_COMMON_NAME_INVALID, interstitial_html}; + } +}; + +// A WebContentsObserver which installs a navigation throttle that creates +// SupervisedUserVerificationPage. +class TestingThrottleInstaller : public content::WebContentsObserver { + public: + explicit TestingThrottleInstaller(content::WebContents* web_contents) + : content::WebContentsObserver(web_contents) {} + + // content::WebContentsObserver: + void DidStartNavigation( + content::NavigationHandle* navigation_handle) override { + navigation_handle->RegisterThrottleForTesting( + std::make_unique< + SupervisedUserVerificationPageTestingNavigationThrottle>( + navigation_handle)); + } +}; + +class SupervisedUserVerificationPageTest + : public MixinBasedInProcessBrowserTest { + protected: + void TestInterstitial(const GURL& request_url, bool should_record_ukm); + + void PreRunTestOnMainThread() override { + InProcessBrowserTest::PreRunTestOnMainThread(); + ukm_recorder_ = std::make_unique<ukm::TestAutoSetUkmRecorder>(); + } + + supervised_user::SupervisionMixin supervision_mixin_{ + mixin_host_, + this, + {.sign_in_mode = + supervised_user::SupervisionMixin::SignInMode::kSignedOut}}; + + int GetReauthInterstitialUKMCount(const std::string& metric_name) { + int count = 0; + auto entries = ukm_recorder_->GetEntriesByName( + ukm::builders::FamilyLinkUser_ReauthenticationInterstitial::kEntryName); + for (const ukm::mojom::UkmEntry* const entry : entries) { + if (ukm_recorder_->GetEntryMetric(entry, metric_name)) { + ++count; + } + } + return count; + } + + supervised_user::KidsManagementApiServerMock& kids_management_api_mock() { + return supervision_mixin_.api_mock_setup_mixin().api_mock(); + } + + private: + std::unique_ptr<TestingThrottleInstaller> testing_throttle_installer_; + std::unique_ptr<ukm::TestAutoSetUkmRecorder> ukm_recorder_; +}; + +void SupervisedUserVerificationPageTest::TestInterstitial( + const GURL& request_url, + bool should_record_ukm) { + int expected_individual_count = int(should_record_ukm); + content::WebContents* contents = + browser()->tab_strip_model()->GetActiveWebContents(); + CHECK(contents); + testing_throttle_installer_ = + std::make_unique<TestingThrottleInstaller>(contents); + + // Navigate to the requested URL and wait for the interstitial. + ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), request_url)); + content::RenderFrameHost* frame = contents->GetPrimaryMainFrame(); + ASSERT_TRUE(WaitForRenderFrameReady(frame)); + EXPECT_EQ(GetReauthInterstitialUKMCount("InterstitialShown"), + expected_individual_count); + + // Interact with the "Next" button, starting re-authentication. + ASSERT_TRUE(content::ExecJs( + contents, "window.certificateErrorPageController.openLogin();")); + EXPECT_EQ(GetReauthInterstitialUKMCount("ReauthenticationStarted"), + expected_individual_count); + + // Sign in a supervised user, which completes re-authentication. + content::TestNavigationObserver observer(contents, 1); + kids_management_api_mock().AllowSubsequentClassifyUrl(); + supervision_mixin_.SignIn( + supervised_user::SupervisionMixin::SignInMode::kSupervised); + // Wait for the re-auth page to be asynchronously reloaded. + observer.WaitForNavigationFinished(); + EXPECT_EQ(GetReauthInterstitialUKMCount("ReauthenticationCompleted"), + expected_individual_count); +} + +// Tests that UKMs are recorded for the YouTube main frame re-authentication +// interstitial. +IN_PROC_BROWSER_TEST_F(SupervisedUserVerificationPageTest, + UkmRecordedForYouTubeReauthInterstitial) { + TestInterstitial(GURL("https://youtube.com/"), /*should_record_ukm=*/true); +} + +// Tests that UKMs are not recorded for the blocked sites main frame +// re-authentication interstitial. +IN_PROC_BROWSER_TEST_F(SupervisedUserVerificationPageTest, + UkmNotRecordedForBlockingInterstitial) { + TestInterstitial(GURL("https://example.com/"), + /*should_record_ukm=*/false); +} + +} // namespace
diff --git a/chrome/browser/sync/chrome_sync_client.cc b/chrome/browser/sync/chrome_sync_client.cc index e0169e4f..f0f7f03 100644 --- a/chrome/browser/sync/chrome_sync_client.cc +++ b/chrome/browser/sync/chrome_sync_client.cc
@@ -366,19 +366,25 @@ scoped_refptr<autofill::AutofillWebDataService> account_web_data_service = WebDataServiceFactory::GetAutofillWebDataForAccount( profile_, ServiceAccessType::IMPLICIT_ACCESS); - scoped_refptr<base::SequencedTaskRunner> web_data_service_thread = - profile_web_data_service ? profile_web_data_service->GetDBTaskRunner() - : nullptr; - // This class assumes that the database thread is the same across the profile - // and account storage. This DCHECK makes that assumption explicit. - DCHECK(!account_web_data_service || - web_data_service_thread == - account_web_data_service->GetDBTaskRunner()); + + // This class assumes that the tasks posted by the profile and account storage + // services will execute, in order, on the same sequence. + // This DCHECK makes that assumption explicit. +#if DCHECK_IS_ON() + if (account_web_data_service && profile_web_data_service) { + profile_web_data_service->GetDBTaskRunner()->PostTask( + FROM_HERE, base::BindOnce( + [](scoped_refptr<base::SequencedTaskRunner> ac_tr) { + CHECK(ac_tr->RunsTasksInCurrentSequence()); + }, + account_web_data_service->GetDBTaskRunner())); + } +#endif // DCHECK_IS_ON() browser_sync::CommonControllerBuilder builder; - builder.SetAutofillWebDataService( - content::GetUIThreadTaskRunner({}), web_data_service_thread, - profile_web_data_service, account_web_data_service); + builder.SetAutofillWebDataService(content::GetUIThreadTaskRunner({}), + profile_web_data_service, + account_web_data_service); builder.SetBookmarkModel( BookmarkModelFactory::GetForBrowserContext(profile_)); builder.SetBookmarkSyncService(
diff --git a/chrome/browser/sync/test/integration/autofill_helper.cc b/chrome/browser/sync/test/integration/autofill_helper.cc index e35c045..e234a3fbe7 100644 --- a/chrome/browser/sync/test/integration/autofill_helper.cc +++ b/chrome/browser/sync/test/integration/autofill_helper.cc
@@ -68,7 +68,8 @@ test()->GetProfile(index), ServiceAccessType::EXPLICIT_ACCESS); } -void WaitForCurrentTasksToComplete(base::SequencedTaskRunner* task_runner) { +void WaitForCurrentTasksToComplete( + scoped_refptr<base::SequencedTaskRunner> task_runner) { base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, base::WaitableEvent::InitialState::NOT_SIGNALED); task_runner->PostTask(FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal,
diff --git a/chrome/browser/sync/test/integration/wallet_helper.cc b/chrome/browser/sync/test/integration/wallet_helper.cc index e86f6c8c4..07fa2e8 100644 --- a/chrome/browser/sync/test/integration/wallet_helper.cc +++ b/chrome/browser/sync/test/integration/wallet_helper.cc
@@ -179,7 +179,8 @@ return true; } -void WaitForCurrentTasksToComplete(base::SequencedTaskRunner* task_runner) { +void WaitForCurrentTasksToComplete( + scoped_refptr<base::SequencedTaskRunner> task_runner) { // We are fine with the UI thread getting blocked. If using RunLoop here, in // some uses of this functions, we would get nested RunLoops that tend to // cause troubles. This is a more robust solution.
diff --git a/chrome/browser/sync/test/integration/web_apps_sync_test_base.cc b/chrome/browser/sync/test/integration/web_apps_sync_test_base.cc index a11d6e4..e5fd519c 100644 --- a/chrome/browser/sync/test/integration/web_apps_sync_test_base.cc +++ b/chrome/browser/sync/test/integration/web_apps_sync_test_base.cc
@@ -5,7 +5,7 @@ #include "chrome/browser/sync/test/integration/web_apps_sync_test_base.h" #include "base/containers/extend.h" -#include "chrome/common/chrome_features.h" +#include "content/public/common/content_features.h" #if BUILDFLAG(IS_CHROMEOS) #include "chrome/browser/apps/link_capturing/link_capturing_features.h" @@ -33,7 +33,7 @@ enabled_features.push_back(apps::features::kLinkCapturingUiUpdate); #else // TOOD(b/313492499): Update test driver to work with new intent picker UI. - enabled_features.push_back(features::kDesktopPWAsLinkCapturing); + enabled_features.push_back(features::kPwaNavigationCapturing); #endif #if BUILDFLAG(IS_CHROMEOS_ASH)
diff --git a/chrome/browser/tab_group_sync/BUILD.gn b/chrome/browser/tab_group_sync/BUILD.gn index f9187ef..c2608f2e 100644 --- a/chrome/browser/tab_group_sync/BUILD.gn +++ b/chrome/browser/tab_group_sync/BUILD.gn
@@ -36,6 +36,7 @@ deps = [ "//base:base_java", "//build/android:build_java", + "//chrome/browser/flags:java", "//chrome/browser/profiles/android:java", "//chrome/browser/tab:java", "//chrome/browser/tab_group:java",
diff --git a/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncServiceFactory.java b/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncServiceFactory.java index a137639..4da5247 100644 --- a/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncServiceFactory.java +++ b/chrome/browser/tab_group_sync/android/java/src/org/chromium/chrome/browser/tab_group_sync/TabGroupSyncServiceFactory.java
@@ -10,6 +10,7 @@ import org.jni_zero.NativeMethods; import org.chromium.base.ResettersForTesting; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.profiles.Profile; import org.chromium.components.tab_group_sync.TabGroupSyncService; @@ -29,6 +30,11 @@ } assert !profile.isOffTheRecord(); + + if (!ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_GROUP_SYNC_ANDROID)) { + return null; + } + return TabGroupSyncServiceFactoryJni.get().getForProfile(profile); }
diff --git a/chrome/browser/tab_group_sync/tab_group_sync_service_factory.cc b/chrome/browser/tab_group_sync/tab_group_sync_service_factory.cc index badab33f..68655273 100644 --- a/chrome/browser/tab_group_sync/tab_group_sync_service_factory.cc +++ b/chrome/browser/tab_group_sync/tab_group_sync_service_factory.cc
@@ -72,7 +72,6 @@ TabGroupSyncService* TabGroupSyncServiceFactory::GetForProfile( Profile* profile) { CHECK(profile); - CHECK(!profile->IsOffTheRecord()); return static_cast<TabGroupSyncService*>( GetInstance()->GetServiceForBrowserContext(profile, /*create=*/true)); }
diff --git a/chrome/browser/tab_group_sync/tab_group_sync_service_factory_unittest.cc b/chrome/browser/tab_group_sync/tab_group_sync_service_factory_unittest.cc index 4c59cc4..528bed0 100644 --- a/chrome/browser/tab_group_sync/tab_group_sync_service_factory_unittest.cc +++ b/chrome/browser/tab_group_sync/tab_group_sync_service_factory_unittest.cc
@@ -35,7 +35,7 @@ TEST_F(TabGroupSyncServiceFactoryTest, ServiceNotCreatedInIncognito) { Profile* otr_profile = profile_.get()->GetOffTheRecordProfile( Profile::OTRProfileID::PrimaryID(), /*create_if_needed=*/true); - EXPECT_DEATH(TabGroupSyncServiceFactory::GetForProfile(otr_profile), ""); + EXPECT_FALSE(TabGroupSyncServiceFactory::GetForProfile(otr_profile)); } } // namespace
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index ce1a4fc..6e514d7 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -4377,6 +4377,8 @@ "views/controls/text_with_controls_view.h", "views/data_sharing/data_sharing_bubble_controller.cc", "views/data_sharing/data_sharing_bubble_controller.h", + "views/data_sharing/data_sharing_utils.cc", + "views/data_sharing/data_sharing_utils.h", "views/desktop_capture/desktop_media_content_pane_view.cc", "views/desktop_capture/desktop_media_content_pane_view.h", "views/desktop_capture/desktop_media_delegated_source_list_view.cc",
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 2f70213..c185823 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -978,6 +978,15 @@ <message name="IDS_ACCESS_LOSS_EXPORT_DIALOG_POSITIVE_BUTTON_TEXT" desc="The text on the button, confirming the user's agreement to export passwords and remove them from Chrome's database."> Export and delete </message> + <message name="IDS_ACCESS_LOSS_IMPORT_DIALOG_TITLE" desc="The title of the dialog instructing the user to import passwords into Google Password Manager."> + Next, import the passwords + </message> + <message name="IDS_ACCESS_LOSS_IMPORT_DIALOG_DESC" desc="The message of the dialog instructing the user to import passwords into Google Password Manager."> + Open Google Password Manager and go to settings. Select “Import“ and add the CSV file that contains your exported passwords. + </message> + <message name="IDS_ACCESS_LOSS_IMPORT_DIALOG_POSITIVE_BUTTON_TEXT" desc="The positive button text in the dialog instructing the user to import passwords into Google Password Manager."> + Take me there + </message> <message name="IDS_ACCESS_LOSS_PREF_DESC" desc="The subtitle of the Google Password Manager item in Chrome main settings. Displayed only if the UPM is not functioning properly."> Some passwords will stop working soon </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESS_LOSS_IMPORT_DIALOG_DESC.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESS_LOSS_IMPORT_DIALOG_DESC.png.sha1 new file mode 100644 index 0000000..54f3ce4d --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESS_LOSS_IMPORT_DIALOG_DESC.png.sha1
@@ -0,0 +1 @@ +d8d78033d06543c2b58af593efb1d45ca829b24e \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESS_LOSS_IMPORT_DIALOG_POSITIVE_BUTTON_TEXT.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESS_LOSS_IMPORT_DIALOG_POSITIVE_BUTTON_TEXT.png.sha1 new file mode 100644 index 0000000..54f3ce4d --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESS_LOSS_IMPORT_DIALOG_POSITIVE_BUTTON_TEXT.png.sha1
@@ -0,0 +1 @@ +d8d78033d06543c2b58af593efb1d45ca829b24e \ No newline at end of file
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESS_LOSS_IMPORT_DIALOG_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESS_LOSS_IMPORT_DIALOG_TITLE.png.sha1 new file mode 100644 index 0000000..54f3ce4d --- /dev/null +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_ACCESS_LOSS_IMPORT_DIALOG_TITLE.png.sha1
@@ -0,0 +1 @@ +d8d78033d06543c2b58af593efb1d45ca829b24e \ No newline at end of file
diff --git a/chrome/browser/ui/ash/desks/desks_interactive_uitest.cc b/chrome/browser/ui/ash/desks/desks_interactive_uitest.cc index 4c3f861a..b366ffa 100644 --- a/chrome/browser/ui/ash/desks/desks_interactive_uitest.cc +++ b/chrome/browser/ui/ash/desks/desks_interactive_uitest.cc
@@ -134,8 +134,6 @@ /*alt=*/false, /*command=*/false); }), - // Note: FlushEvents is needed here. Without it, the desk - // name text field does not gain focus Log("Wait for the overview desk bar to show"), AfterShow(kOverviewDeskBarElementId, [&desk_bar_view](ui::TrackedElement* el) {
diff --git a/chrome/browser/ui/ash/privacy_hub/geolocation_switch_interactive_uitest.cc b/chrome/browser/ui/ash/privacy_hub/geolocation_switch_interactive_uitest.cc index 8044a10c..93c4fd01 100644 --- a/chrome/browser/ui/ash/privacy_hub/geolocation_switch_interactive_uitest.cc +++ b/chrome/browser/ui/ash/privacy_hub/geolocation_switch_interactive_uitest.cc
@@ -84,11 +84,7 @@ CheckJsResult(kWebContentsElementId, "geoStartWithSyncResponse", "requested"), WaitForShow(PermissionPromptBubbleBaseView::kMainViewId), - WaitForShow(PermissionPromptBubbleBaseView::kAllowButtonElementId) - // We need to call `FlushEvents` here before `PressButton` because a - // `view_` variable in PermissionRequestManager is not yet - // initialized. - , + WaitForShow(PermissionPromptBubbleBaseView::kAllowButtonElementId), PressButton(PermissionPromptBubbleBaseView::kAllowButtonElementId), WaitForHide(PermissionPromptBubbleBaseView::kMainViewId));
diff --git a/chrome/browser/ui/browser_element_identifiers.cc b/chrome/browser/ui/browser_element_identifiers.cc index 2b4a766..da40fdf2 100644 --- a/chrome/browser/ui/browser_element_identifiers.cc +++ b/chrome/browser/ui/browser_element_identifiers.cc
@@ -85,6 +85,8 @@ DEFINE_ELEMENT_IDENTIFIER_VALUE(kTabIconElementId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kTabElementId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kTabGroupEditorBubbleCloseGroupButtonId); +DEFINE_ELEMENT_IDENTIFIER_VALUE(kTabGroupEditorBubbleManageSharedGroupButtonId); +DEFINE_ELEMENT_IDENTIFIER_VALUE(kTabGroupEditorBubbleShareGroupButtonId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kTabGroupEditorBubbleId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kTabGroupEditorBubbleSaveToggleId); DEFINE_ELEMENT_IDENTIFIER_VALUE(kTabGroupHeaderElementId);
diff --git a/chrome/browser/ui/browser_element_identifiers.h b/chrome/browser/ui/browser_element_identifiers.h index 33cbcde..c6cd94f 100644 --- a/chrome/browser/ui/browser_element_identifiers.h +++ b/chrome/browser/ui/browser_element_identifiers.h
@@ -96,6 +96,9 @@ DECLARE_ELEMENT_IDENTIFIER_VALUE(kTabIconElementId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kTabElementId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kTabGroupEditorBubbleCloseGroupButtonId); +DECLARE_ELEMENT_IDENTIFIER_VALUE( + kTabGroupEditorBubbleManageSharedGroupButtonId); +DECLARE_ELEMENT_IDENTIFIER_VALUE(kTabGroupEditorBubbleShareGroupButtonId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kTabGroupEditorBubbleId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kTabGroupEditorBubbleSaveToggleId); DECLARE_ELEMENT_IDENTIFIER_VALUE(kTabGroupHeaderElementId);
diff --git a/chrome/browser/ui/browser_live_tab_context.cc b/chrome/browser/ui/browser_live_tab_context.cc index e7f905e..d40d3aa 100644 --- a/chrome/browser/ui/browser_live_tab_context.cc +++ b/chrome/browser/ui/browser_live_tab_context.cc
@@ -243,18 +243,9 @@ // Save the group if it was not saved. if (!tab_group_service->GetGroup(group_id.value()).has_value() && tab_groups::IsTabGroupsSaveV2Enabled()) { - tab_groups::SavedTabGroup saved_tab_group( - tab.group_visual_data->title(), tab.group_visual_data->color(), {}, - std::nullopt, std::nullopt, tab.group.value()); - saved_tab_group.AddTabLocally( - tab_groups::SavedTabGroupUtils:: - CreateSavedTabGroupTabFromWebContents( - web_contents, saved_tab_group.saved_guid())); - - const base::Uuid saved_group_guid = saved_tab_group.saved_guid(); - tab_group_service->AddGroup(std::move(saved_tab_group)); - tab_group_service->ConnectLocalTabGroup(saved_group_guid, - tab.group.value()); + tab_group_service->AddGroup( + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + tab.group.value())); } } } else {
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.cc b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.cc index 96ec612d..6239bf3 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.cc
@@ -186,14 +186,17 @@ } } -void SavedTabGroupKeyedService::SaveRestoredGroup( - const TabGroupId& local_group_id) { +void SavedTabGroupKeyedService::SaveRestoredGroup(SavedTabGroup group) { if (model()->is_loaded()) { - CHECK(!model()->Contains(local_group_id)) + CHECK(!model()->Contains(group.saved_guid())) << "This group is somehow saved already when it shouldn't be."; - SaveGroup(local_group_id); + + const LocalTabGroupID local_id = group.local_group_id().value(); + const base::Uuid sync_id = group.saved_guid(); + model_->Add(std::move(group)); + ConnectLocalTabGroup(local_id, sync_id); } else { - restored_groups_to_save_on_load_.emplace_back(local_group_id); + restored_groups_to_save_on_load_.emplace_back(group); } } @@ -272,22 +275,10 @@ return std::nullopt; } - std::map<content::WebContents*, base::Uuid> contents_guid_mapping; - std::transform( - tab_guid_mapping.begin(), tab_guid_mapping.end(), - std::inserter(contents_guid_mapping, contents_guid_mapping.end()), - [](const std::pair<tabs::TabModel*, base::Uuid>& pair) { - // Transform the TabModel* to WebContents* - content::WebContents* web_contents = pair.first->contents(); - - // Return a pair with the transformed key and the same UUID value - return std::make_pair(web_contents, pair.second); - }); - // Take the opened tabs and move them into a TabGroup in the TabStrip. Link // the `tab_group_id` to `saved_group_guid` to stay up-to-date. TabGroupId tab_group_id = AddOpenedTabsToGroup( - browser->tab_strip_model(), contents_guid_mapping, *saved_group); + browser->tab_strip_model(), tab_guid_mapping, *saved_group); EventDetails event_details(TabGroupEvent::kTabGroupOpened); event_details.local_tab_group_id = tab_group_id; @@ -302,15 +293,12 @@ TabGroupId SavedTabGroupKeyedService::AddOpenedTabsToGroup( TabStripModel* const tab_strip_model_for_creation, - const std::map<content::WebContents*, base::Uuid>& - opened_web_contents_to_uuid, + const std::map<tabs::TabModel*, base::Uuid>& tab_guid_mapping, const SavedTabGroup& saved_group) { - // Figure out which tabs we actually opened in this browser that aren't - // already in groups. std::vector<int> tab_indices; for (int i = 0; i < tab_strip_model_for_creation->count(); ++i) { - if (base::Contains(opened_web_contents_to_uuid, - tab_strip_model_for_creation->GetWebContentsAt(i)) && + if (base::Contains(tab_guid_mapping, + tab_strip_model_for_creation->GetTabAtIndex(i)) && !tab_strip_model_for_creation->GetTabGroupForTab(i).has_value()) { tab_indices.push_back(i); LogEvent(TabGroupEvent::kTabAdded, saved_group.saved_guid()); @@ -337,7 +325,20 @@ UpdateGroupVisualData(saved_group.saved_guid(), saved_group.local_group_id().value()); - listener_->ConnectToLocalTabGroup(saved_group, opened_web_contents_to_uuid); + std::map<content::WebContents*, base::Uuid> contents_guid_mapping; + + std::transform( + tab_guid_mapping.begin(), tab_guid_mapping.end(), + std::inserter(contents_guid_mapping, contents_guid_mapping.end()), + [](const std::pair<tabs::TabModel*, base::Uuid>& pair) { + // Transform the TabModel* to WebContents* + content::WebContents* web_contents = pair.first->contents(); + + // Return a pair with the transformed key and the same UUID value + return std::make_pair(web_contents, pair.second); + }); + + listener_->ConnectToLocalTabGroup(saved_group, contents_guid_mapping); return tab_group_id; } @@ -470,9 +471,23 @@ model_->OnGroupOpenedInTabStrip(saved_guid, local_group_id); UpdateGroupVisualData(saved_guid, local_group_id); - listener_->ConnectToLocalTabGroup( - *model_->Get(saved_guid), GetWebContentsToTabGuidMappingForSavedGroup( - tab_strip_model, saved_group, tab_range)); + auto tab_guid_mapping = + GetTabToGuidMappingForSavedGroup(tab_strip_model, saved_group, tab_range); + + std::map<content::WebContents*, base::Uuid> contents_guid_mapping; + std::transform( + tab_guid_mapping.begin(), tab_guid_mapping.end(), + std::inserter(contents_guid_mapping, contents_guid_mapping.end()), + [](const std::pair<tabs::TabModel*, base::Uuid>& pair) { + // Transform the TabModel* to WebContents* + content::WebContents* web_contents = pair.first->contents(); + + // Return a pair with the transformed key and the same UUID value + return std::make_pair(web_contents, pair.second); + }); + + listener_->ConnectToLocalTabGroup(*model_->Get(saved_guid), + contents_guid_mapping); } void SavedTabGroupKeyedService::SavedTabGroupModelLoaded() { @@ -494,8 +509,8 @@ ConnectLocalTabGroup(local_group_id, saved_guid); } - for (const auto& local_group_id : restored_groups_to_save_on_load_) { - SaveGroup(local_group_id); + for (SavedTabGroup group : restored_groups_to_save_on_load_) { + SaveRestoredGroup(std::move(group)); } // Clear restored groups to connect and save now that we have processed them. @@ -596,27 +611,24 @@ } } -std::map<content::WebContents*, base::Uuid> -SavedTabGroupKeyedService::GetWebContentsToTabGuidMappingForSavedGroup( +std::map<tabs::TabModel*, base::Uuid> +SavedTabGroupKeyedService::GetTabToGuidMappingForSavedGroup( const TabStripModel* const tab_strip_model, const SavedTabGroup* const saved_group, const gfx::Range& tab_range) { - std::map<content::WebContents*, base::Uuid> web_contents_map; + std::map<tabs::TabModel*, base::Uuid> tab_guid_mapping; - for (size_t index_in_tabstrip = tab_range.start(); - index_in_tabstrip < tab_range.end(); ++index_in_tabstrip) { - content::WebContents* const web_contents = - tab_strip_model->GetWebContentsAt(index_in_tabstrip); - CHECK(web_contents); + for (size_t i = tab_range.start(); i < tab_range.end(); ++i) { + tabs::TabModel* const tab = tab_strip_model->GetTabAtIndex(i); + CHECK(tab); - const int saved_tab_index = index_in_tabstrip - tab_range.start(); const SavedTabGroupTab& saved_tab = - saved_group->saved_tabs()[saved_tab_index]; + saved_group->saved_tabs()[i - tab_range.start()]; - web_contents_map.emplace(web_contents, saved_tab.saved_tab_guid()); + tab_guid_mapping.emplace(tab, saved_tab.saved_tab_guid()); } - return web_contents_map; + return tab_guid_mapping; } std::map<tabs::TabModel*, base::Uuid>
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h index 81ce4fa6..3380a4e 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h
@@ -93,7 +93,7 @@ // Saves a restored group. This can be called prior to the saved tab // group model is loaded. These groups are saved when the model is loaded. - void SaveRestoredGroup(const tab_groups::TabGroupId& group_id); + void SaveRestoredGroup(SavedTabGroup group); void UpdateAttributions( const LocalTabGroupID& group_id, @@ -143,15 +143,16 @@ const SavedTabGroup* const saved_group, const gfx::Range& tab_range); - // Connects all SavedTabGroupTabs from a SavedTabGroup to their respective - // WebContents in the local TabGroup. - std::map<content::WebContents*, base::Uuid> - GetWebContentsToTabGuidMappingForSavedGroup( + // Given a `tab_range` which is indexes of tabs in the `tab_strip_model` that + // should be part of `saved_group` outputs a mapping of tab to guid. This + // method performs no checks to make sure that the tabs are the correct ones + // that should be connected. + std::map<tabs::TabModel*, base::Uuid> GetTabToGuidMappingForSavedGroup( const TabStripModel* const tab_strip_model, const SavedTabGroup* const saved_group, const gfx::Range& tab_range); - // Opens a saved tab group into the tabstrip of the |browser| and returns a + // Opens a saved tab group into the tabstrip of the `browser` and returns a // mapping of the tabs to the SavedTabGroupTab. This method does not check // that the browser is accepting of groups so this must be done by callers. // This method does not check that the saved group is already open so that @@ -161,13 +162,11 @@ Browser* browser, const SavedTabGroup* const saved_group); - // Helper function that adds the opened tabs obtained from calling - // `GetWebContentsToTabGuidMappingForOpening` into a new tab group in the - // TabStrip. + // Helper method that takes the list of tabs that were created specifically + // for the saved group, and then groups them in the tabstrip model. tab_groups::TabGroupId AddOpenedTabsToGroup( TabStripModel* const tab_strip_model_for_creation, - const std::map<content::WebContents*, base::Uuid>& - opened_web_contents_to_uuid, + const std::map<tabs::TabModel*, base::Uuid>& tab_guid_mapping, const SavedTabGroup& saved_group); // Returns a pointer to the TabStripModel which contains `local_group_id`. @@ -223,7 +222,7 @@ restored_groups_to_connect_on_load_; // Keeps track of the groups to save on model load. - std::vector<tab_groups::TabGroupId> restored_groups_to_save_on_load_; + std::vector<SavedTabGroup> restored_groups_to_save_on_load_; }; } // namespace tab_groups
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.cc b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.cc index 3f56df67..efed03ce 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_model_listener.cc
@@ -55,6 +55,10 @@ return; } + if (!tab_groups::IsTabGroupsSaveV2Enabled()) { + return; + } + if (local_tab_group_listeners_.contains(group_id)) { return; } @@ -77,6 +81,10 @@ return; } + if (!tab_groups::IsTabGroupsSaveV2Enabled()) { + return; + } + DisconnectLocalTabGroup(group_id); }
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc index 31801f17f..d8f22728 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.cc
@@ -493,6 +493,32 @@ return contentses; } +SavedTabGroup SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + const tab_groups::LocalTabGroupID& local_id) { + Browser* browser = GetBrowserWithTabGroupId(local_id); + CHECK(browser); + + const TabGroup* local_group = + browser->tab_strip_model()->group_model()->GetTabGroup(local_id); + tab_groups::SavedTabGroup saved_tab_group( + local_group->visual_data()->title(), local_group->visual_data()->color(), + {}, std::nullopt, std::nullopt, local_id); + saved_tab_group.SetPinned( + tab_groups::SavedTabGroupUtils::ShouldAutoPinNewTabGroups( + browser->profile())); + + const std::vector<content::WebContents*>& web_contentses = + tab_groups::SavedTabGroupUtils::GetWebContentsesInGroup(local_id); + for (content::WebContents* web_contents : web_contentses) { + tab_groups::SavedTabGroupTab saved_tab_group_tab = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupTabFromWebContents( + web_contents, saved_tab_group.saved_guid()); + saved_tab_group.AddTabLocally(std::move(saved_tab_group_tab)); + } + + return saved_tab_group; +} + std::unordered_set<std::string> SavedTabGroupUtils::GetURLsInSavedTabGroup( Profile* profile, const base::Uuid& saved_id) {
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h index fff5b29..df7ee43 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h +++ b/chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/tabs/tab_group.h" #include "chrome/browser/ui/tabs/tab_group_deletion_dialog_controller.h" #include "components/saved_tab_groups/saved_tab_group.h" +#include "components/saved_tab_groups/types.h" #include "ui/base/interaction/element_identifier.h" #include "ui/base/interaction/element_tracker.h" #include "ui/base/models/dialog_model.h" @@ -92,6 +93,10 @@ content::WebContents* contents, base::Uuid saved_tab_group_id); + // Creates a SavedTabGroup group for the provided local tab group. + static SavedTabGroup CreateSavedTabGroupFromLocalId( + const tab_groups::LocalTabGroupID& local_id); + static content::NavigationHandle* OpenTabInBrowser( const GURL& url, Browser* browser,
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.cc b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.cc index d027f28..9024168a 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.cc
@@ -43,11 +43,11 @@ TabGroupSyncServiceProxy::~TabGroupSyncServiceProxy() = default; void TabGroupSyncServiceProxy::AddGroup(SavedTabGroup group) { - service_->model()->Add(std::move(group)); + service_->SaveRestoredGroup(std::move(group)); } void TabGroupSyncServiceProxy::RemoveGroup(const LocalTabGroupID& local_id) { - service_->model()->Remove(local_id); + service_->UnsaveGroup(local_id, ClosingSource::kDeletedByUser); } void TabGroupSyncServiceProxy::RemoveGroup(const base::Uuid& sync_id) { @@ -263,6 +263,10 @@ void TabGroupSyncServiceProxy::RemoveObserver(Observer* observer) {} +void TabGroupSyncServiceProxy::SetIsInitializedForTesting(bool initialized) { + service_->model()->LoadStoredEntries({}, {}); +} + void TabGroupSyncServiceProxy::AddSavedTabGroupModelObserver( SavedTabGroupModelObserver* saved_tab_group_model_observer) {
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.h b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.h index 64ecd7a..4d6fdb8 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.h +++ b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy.h
@@ -92,6 +92,8 @@ void AddObserver(Observer* observer) override; void RemoveObserver(Observer* observer) override; + void SetIsInitializedForTesting(bool initialized) override; + void AddSavedTabGroupModelObserver( SavedTabGroupModelObserver* saved_tab_group_model_observer); void RemoveSavedTabGroupModelObserver(
diff --git a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy_unittest.cc b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy_unittest.cc index 8abe31a..28a9a57b 100644 --- a/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy_unittest.cc +++ b/chrome/browser/ui/tabs/saved_tab_groups/tab_group_sync_service_proxy_unittest.cc
@@ -137,108 +137,96 @@ // Verify we can add a group to both services correctly. TEST_P(TabGroupSyncServiceProxyUnitTest, AddGroup) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); + AddTabToBrowser(browser, 0); + AddTabToBrowser(browser, 0); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0, 1, 2}); const std::optional<SavedTabGroup> retrieved_group = - service()->GetGroup(kGroupId); - EXPECT_TRUE(retrieved_group.has_value()); + service()->GetGroup(local_id); + ASSERT_TRUE(retrieved_group.has_value()); EXPECT_EQ(local_id, retrieved_group->local_group_id()); - EXPECT_EQ(kGroupId, retrieved_group->saved_guid()); EXPECT_EQ(3u, retrieved_group->saved_tabs().size()); - EXPECT_TRUE(retrieved_group->ContainsTab(kFirstTabId)); - EXPECT_TRUE(retrieved_group->ContainsTab(kSecondTabId)); - EXPECT_TRUE(retrieved_group->ContainsTab(kThirdTabId)); } // Verify we can remove a group from the services using the local id correctly. TEST_P(TabGroupSyncServiceProxyUnitTest, RemoveGroupUsingLocalId) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); + const base::Uuid sync_id = retrieved_group->saved_guid(); service()->RemoveGroup(local_id); EXPECT_FALSE(service()->GetGroup(local_id).has_value()); - EXPECT_FALSE(service()->GetGroup(kGroupId).has_value()); + EXPECT_FALSE(service()->GetGroup(sync_id).has_value()); } // Verify we can remove a group from the services using the sync id correctly. TEST_P(TabGroupSyncServiceProxyUnitTest, RemoveGroupUsingSyncId) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); - service()->RemoveGroup(kGroupId); + const base::Uuid sync_id = retrieved_group->saved_guid(); + service()->RemoveGroup(sync_id); EXPECT_FALSE(service()->GetGroup(local_id).has_value()); - EXPECT_FALSE(service()->GetGroup(kGroupId).has_value()); + EXPECT_FALSE(service()->GetGroup(sync_id).has_value()); } // Verify we can update a groups visual data from the services correctly. TEST_P(TabGroupSyncServiceProxyUnitTest, UpdateVisualData) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); - EXPECT_EQ(kGroupTitle, retrieved_group->title()); - EXPECT_EQ(kGroupColor, retrieved_group->color()); const std::u16string new_title = u"New Title"; const TabGroupColorId new_color = TabGroupColorId::kCyan; TabGroupVisualData new_visual_data(new_title, new_color); service()->UpdateVisualData(local_id, &new_visual_data); - retrieved_group = service()->GetGroup(kGroupId); + retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); EXPECT_EQ(new_title, retrieved_group->title()); EXPECT_EQ(new_color, retrieved_group->color()); } TEST_P(TabGroupSyncServiceProxyUnitTest, UpdateGroupPositionPinnedState) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); + AddTabToBrowser(browser, 0); + TabGroupId local_id = browser->tab_strip_model()->AddToNewGroup({0}); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); - - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + // Ensure the group was saved. + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); const bool pinned_state = retrieved_group->is_pinned(); service()->UpdateGroupPosition(retrieved_group->saved_guid(), !pinned_state, std::nullopt); - retrieved_group = service()->GetGroup(kGroupId); + retrieved_group = service()->GetGroup(local_id); EXPECT_NE(retrieved_group->is_pinned(), pinned_state); service()->UpdateGroupPosition(retrieved_group->saved_guid(), pinned_state, std::nullopt); - retrieved_group = service()->GetGroup(kGroupId); + retrieved_group = service()->GetGroup(local_id); EXPECT_EQ(retrieved_group->is_pinned(), pinned_state); } @@ -256,25 +244,18 @@ return std::distance(groups.begin(), it); }; - LocalTabGroupID local_id_1 = tab_groups::TabGroupId::GenerateNew(); - LocalTabGroupID local_id_2 = tab_groups::TabGroupId::GenerateNew(); - LocalTabGroupID local_id_3 = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); + AddTabToBrowser(browser, 0); + AddTabToBrowser(browser, 0); + TabGroupId local_id_1 = browser->tab_strip_model()->AddToNewGroup({0}); + TabGroupId local_id_2 = browser->tab_strip_model()->AddToNewGroup({1}); + TabGroupId local_id_3 = browser->tab_strip_model()->AddToNewGroup({2}); - SavedTabGroup group_1( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id_1); - SavedTabGroup group_2( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - base::Uuid::GenerateRandomV4(), local_id_2); - SavedTabGroup group_3( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - base::Uuid::GenerateRandomV4(), local_id_3); - service()->AddGroup(std::move(group_1)); - service()->AddGroup(std::move(group_2)); - service()->AddGroup(std::move(group_3)); + // Ensure the group was saved. + std::optional<SavedTabGroup> retrieved_group = + service()->GetGroup(local_id_1); + const base::Uuid& sync_id = retrieved_group->saved_guid(); std::vector<SavedTabGroup> all_groups = service()->GetAllGroups(); ASSERT_EQ(3u, all_groups.size()); @@ -282,17 +263,17 @@ EXPECT_EQ(1, get_index(local_id_2)); EXPECT_EQ(2, get_index(local_id_1)); - service()->UpdateGroupPosition(kGroupId, std::nullopt, 0); + service()->UpdateGroupPosition(sync_id, std::nullopt, 0); EXPECT_EQ(0, get_index(local_id_1)); EXPECT_EQ(1, get_index(local_id_3)); EXPECT_EQ(2, get_index(local_id_2)); - service()->UpdateGroupPosition(kGroupId, std::nullopt, 1); + service()->UpdateGroupPosition(sync_id, std::nullopt, 1); EXPECT_EQ(0, get_index(local_id_3)); EXPECT_EQ(1, get_index(local_id_1)); EXPECT_EQ(2, get_index(local_id_2)); - service()->UpdateGroupPosition(kGroupId, std::nullopt, 2); + service()->UpdateGroupPosition(sync_id, std::nullopt, 2); EXPECT_EQ(0, get_index(local_id_3)); EXPECT_EQ(1, get_index(local_id_2)); EXPECT_EQ(2, get_index(local_id_1)); @@ -300,20 +281,19 @@ // Verifies that we add tabs to a group at the correct position. TEST_P(TabGroupSyncServiceProxyUnitTest, AddTab) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); - SavedTabGroup group(kGroupTitle, kGroupColor, {FirstTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); EXPECT_EQ(1u, retrieved_group->saved_tabs().size()); - EXPECT_TRUE(retrieved_group->ContainsTab(kFirstTabId)); - SavedTabGroupTab second_tab = SecondTab(kGroupId); - SavedTabGroupTab third_tab = ThirdTab(kGroupId); - + const base::Uuid sync_id = retrieved_group->saved_guid(); + SavedTabGroupTab second_tab = SecondTab(sync_id); + SavedTabGroupTab third_tab = ThirdTab(sync_id); service()->AddTab(local_id, kSecondTabToken, second_tab.title(), second_tab.url(), 0); service()->AddTab(local_id, kThirdTabToken, third_tab.title(), @@ -322,29 +302,32 @@ retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); EXPECT_EQ(3u, retrieved_group->saved_tabs().size()); - EXPECT_TRUE(retrieved_group->ContainsTab(kFirstTabToken)); EXPECT_TRUE(retrieved_group->ContainsTab(kSecondTabToken)); EXPECT_TRUE(retrieved_group->ContainsTab(kThirdTabToken)); // Get the order of tabs. const std::vector<SavedTabGroupTab> tabs = retrieved_group->saved_tabs(); EXPECT_EQ(kSecondTabToken, tabs[0].local_tab_id()); - EXPECT_EQ(kFirstTabToken, tabs[1].local_tab_id()); EXPECT_EQ(kThirdTabToken, tabs[2].local_tab_id()); } // Verifies that we can update the title and url of a tab in a saved group. TEST_P(TabGroupSyncServiceProxyUnitTest, UpdateTab) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); - SavedTabGroup group(kGroupTitle, kGroupColor, {FirstTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); EXPECT_EQ(1u, retrieved_group->saved_tabs().size()); - EXPECT_TRUE(retrieved_group->ContainsTab(kFirstTabId)); + EXPECT_TRUE(retrieved_group->saved_tabs()[0].local_tab_id().has_value()); + + const LocalTabID tab_id = + retrieved_group->saved_tabs()[0].local_tab_id().value(); + const base::Uuid sync_tab_id = + retrieved_group->saved_tabs()[0].saved_tab_guid(); const std::u16string new_title = u"This is the new title"; GURL new_url = GURL("https://not_first_tab.com"); @@ -352,12 +335,12 @@ SavedTabGroupTabBuilder tab_builder; tab_builder.SetTitle(new_title); tab_builder.SetURL(new_url); - service()->UpdateTab(local_id, kFirstTabToken, std::move(tab_builder)); - retrieved_group = service()->GetGroup(kGroupId); + service()->UpdateTab(local_id, tab_id, std::move(tab_builder)); + retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); - EXPECT_TRUE(retrieved_group->ContainsTab(kFirstTabId)); + EXPECT_TRUE(retrieved_group->ContainsTab(sync_tab_id)); - const SavedTabGroupTab* retrieved_tab = retrieved_group->GetTab(kFirstTabId); + const SavedTabGroupTab* retrieved_tab = retrieved_group->GetTab(sync_tab_id); EXPECT_EQ(new_title, retrieved_tab->title()); EXPECT_EQ(new_url, retrieved_tab->url()); } @@ -365,116 +348,134 @@ // Verifies that we can remove a tab in a group and that after removing all of // the tabs, the group is deleted. TEST_P(TabGroupSyncServiceProxyUnitTest, RemoveTab) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); + AddTabToBrowser(browser, 0); + AddTabToBrowser(browser, 0); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0, 1, 2}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); + EXPECT_EQ(3u, retrieved_group->saved_tabs().size()); + + const LocalTabID tab_1_id = + retrieved_group->saved_tabs()[0].local_tab_id().value(); + const LocalTabID tab_2_id = + retrieved_group->saved_tabs()[1].local_tab_id().value(); + const LocalTabID tab_3_id = + retrieved_group->saved_tabs()[2].local_tab_id().value(); // Remove the first tab: [ Tab 1, Tab 2, Tab 3 ] -> [ Tab 2, Tab 3] - service()->RemoveTab(local_id, kFirstTabToken); + service()->RemoveTab(local_id, tab_1_id); - retrieved_group = service()->GetGroup(kGroupId); + retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); EXPECT_EQ(2u, retrieved_group->saved_tabs().size()); - EXPECT_FALSE(retrieved_group->ContainsTab(kFirstTabToken)); - EXPECT_TRUE(retrieved_group->ContainsTab(kSecondTabToken)); - EXPECT_TRUE(retrieved_group->ContainsTab(kThirdTabToken)); + EXPECT_FALSE(retrieved_group->ContainsTab(tab_1_id)); + EXPECT_TRUE(retrieved_group->ContainsTab(tab_2_id)); + EXPECT_TRUE(retrieved_group->ContainsTab(tab_3_id)); // Remove the third tab: [ Tab 2, Tab 3 ] -> [ Tab 2 ] - service()->RemoveTab(local_id, kThirdTabToken); + service()->RemoveTab(local_id, tab_3_id); - retrieved_group = service()->GetGroup(kGroupId); + retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); EXPECT_EQ(1u, retrieved_group->saved_tabs().size()); - EXPECT_FALSE(retrieved_group->ContainsTab(kFirstTabToken)); - EXPECT_TRUE(retrieved_group->ContainsTab(kSecondTabToken)); - EXPECT_FALSE(retrieved_group->ContainsTab(kThirdTabToken)); + EXPECT_FALSE(retrieved_group->ContainsTab(tab_1_id)); + EXPECT_TRUE(retrieved_group->ContainsTab(tab_2_id)); + EXPECT_FALSE(retrieved_group->ContainsTab(tab_3_id)); // Remove the second tab. This should delete the group. - service()->RemoveTab(local_id, kSecondTabToken); + const base::Uuid sync_id = retrieved_group->saved_guid(); + service()->RemoveTab(local_id, tab_2_id); - retrieved_group = service()->GetGroup(kGroupId); + retrieved_group = service()->GetGroup(sync_id); EXPECT_FALSE(retrieved_group.has_value()); } // Verifies that we can move the tabs in a saved group correctly. TEST_P(TabGroupSyncServiceProxyUnitTest, MoveTab) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); + AddTabToBrowser(browser, 0); + AddTabToBrowser(browser, 0); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0, 1, 2}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); + EXPECT_EQ(3u, retrieved_group->saved_tabs().size()); + + const LocalTabID tab_1_id = + retrieved_group->saved_tabs()[0].local_tab_id().value(); + const LocalTabID tab_2_id = + retrieved_group->saved_tabs()[1].local_tab_id().value(); + const LocalTabID tab_3_id = + retrieved_group->saved_tabs()[2].local_tab_id().value(); // Move tab 3 to the front: [ Tab 1, Tab 2, Tab 3 ] -> [ Tab 3, Tab 1, Tab 2] - service()->MoveTab(local_id, kThirdTabToken, 0); - retrieved_group = service()->GetGroup(kGroupId); + service()->MoveTab(local_id, tab_3_id, 0); + retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); std::vector<SavedTabGroupTab> tabs = retrieved_group->saved_tabs(); - EXPECT_EQ(kThirdTabToken, tabs[0].local_tab_id()); - EXPECT_EQ(kFirstTabToken, tabs[1].local_tab_id()); - EXPECT_EQ(kSecondTabToken, tabs[2].local_tab_id()); + EXPECT_EQ(tab_3_id, tabs[0].local_tab_id()); + EXPECT_EQ(tab_1_id, tabs[1].local_tab_id()); + EXPECT_EQ(tab_2_id, tabs[2].local_tab_id()); // Move tab 2 to the middle: [ Tab 3, Tab 1, Tab 2 ] -> [ Tab 3, Tab 2, Tab 1] - service()->MoveTab(local_id, kSecondTabToken, 1); - retrieved_group = service()->GetGroup(kGroupId); + service()->MoveTab(local_id, tab_2_id, 1); + retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); tabs = retrieved_group->saved_tabs(); - EXPECT_EQ(kThirdTabToken, tabs[0].local_tab_id()); - EXPECT_EQ(kSecondTabToken, tabs[1].local_tab_id()); - EXPECT_EQ(kFirstTabToken, tabs[2].local_tab_id()); + EXPECT_EQ(tab_3_id, tabs[0].local_tab_id()); + EXPECT_EQ(tab_2_id, tabs[1].local_tab_id()); + EXPECT_EQ(tab_1_id, tabs[2].local_tab_id()); // Move tab 1 to the front: [ Tab 3, Tab 2, Tab 1 ] -> [ Tab 1, Tab 3, Tab 2] - service()->MoveTab(local_id, kFirstTabToken, 0); - retrieved_group = service()->GetGroup(kGroupId); + service()->MoveTab(local_id, tab_1_id, 0); + retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); tabs = retrieved_group->saved_tabs(); - EXPECT_EQ(kFirstTabToken, tabs[0].local_tab_id()); - EXPECT_EQ(kThirdTabToken, tabs[1].local_tab_id()); - EXPECT_EQ(kSecondTabToken, tabs[2].local_tab_id()); + EXPECT_EQ(tab_1_id, tabs[0].local_tab_id()); + EXPECT_EQ(tab_3_id, tabs[1].local_tab_id()); + EXPECT_EQ(tab_2_id, tabs[2].local_tab_id()); // Move tab 3 to the end: [ Tab 1, Tab 3, Tab 2 ] -> [ Tab 1, Tab 2, Tab 3] - service()->MoveTab(local_id, kThirdTabToken, 2); - retrieved_group = service()->GetGroup(kGroupId); + service()->MoveTab(local_id, tab_3_id, 2); + retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); tabs = retrieved_group->saved_tabs(); - EXPECT_EQ(kFirstTabToken, tabs[0].local_tab_id()); - EXPECT_EQ(kSecondTabToken, tabs[1].local_tab_id()); - EXPECT_EQ(kThirdTabToken, tabs[2].local_tab_id()); + EXPECT_EQ(tab_1_id, tabs[0].local_tab_id()); + EXPECT_EQ(tab_2_id, tabs[1].local_tab_id()); + EXPECT_EQ(tab_3_id, tabs[2].local_tab_id()); } // Verifies that we can update the local tab group mapping of a saved group // after it is added to the service. TEST_P(TabGroupSyncServiceProxyUnitTest, UpdateLocalTabGroupMapping) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); + EXPECT_EQ(1u, retrieved_group->saved_tabs().size()); + + const base::Uuid sync_id = retrieved_group->saved_guid(); tab_groups::TabGroupId new_local_id = tab_groups::TabGroupId::GenerateNew(); - service()->UpdateLocalTabGroupMapping(kGroupId, new_local_id); + service()->UpdateLocalTabGroupMapping(sync_id, new_local_id); - retrieved_group = service()->GetGroup(kGroupId); + retrieved_group = service()->GetGroup(sync_id); EXPECT_TRUE(retrieved_group.has_value()); EXPECT_EQ(new_local_id, retrieved_group->local_group_id()); } @@ -482,20 +483,20 @@ // Verifies that we can remove the local tab group mapping of a saved group // after it is added to the service. TEST_P(TabGroupSyncServiceProxyUnitTest, RemoveLocalTabGroupMapping) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); + EXPECT_EQ(1u, retrieved_group->saved_tabs().size()); + const base::Uuid sync_id = retrieved_group->saved_guid(); service()->RemoveLocalTabGroupMapping(local_id); - retrieved_group = service()->GetGroup(kGroupId); + retrieved_group = service()->GetGroup(sync_id); EXPECT_TRUE(retrieved_group.has_value()); EXPECT_EQ(std::nullopt, retrieved_group->local_group_id()); } @@ -503,24 +504,28 @@ // Verifies that we can update the local tab id mapping for a tab in a saved // group after it is added to the service. TEST_P(TabGroupSyncServiceProxyUnitTest, UpdateLocalTabId) { - tab_groups::TabGroupId local_id = tab_groups::TabGroupId::GenerateNew(); + Browser* browser = AddBrowser(); + AddTabToBrowser(browser, 0); - SavedTabGroup group( - kGroupTitle, kGroupColor, - {FirstTab(kGroupId), SecondTab(kGroupId), ThirdTab(kGroupId)}, 0, - kGroupId, local_id); - service()->AddGroup(std::move(group)); + tab_groups::TabGroupId local_id = + browser->tab_strip_model()->AddToNewGroup({0}); - std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(kGroupId); + std::optional<SavedTabGroup> retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); + EXPECT_EQ(1u, retrieved_group->saved_tabs().size()); + + const LocalTabID tab_1_id = + retrieved_group->saved_tabs()[0].local_tab_id().value(); + const base::Uuid tab_1_guid = + retrieved_group->saved_tabs()[0].saved_tab_guid(); LocalTabID new_local_tab_id = base::Token::CreateRandom(); - service()->UpdateLocalTabId(local_id, kFirstTabId, new_local_tab_id); + service()->UpdateLocalTabId(local_id, tab_1_guid, new_local_tab_id); - retrieved_group = service()->GetGroup(kGroupId); + retrieved_group = service()->GetGroup(local_id); EXPECT_TRUE(retrieved_group.has_value()); EXPECT_TRUE(retrieved_group->ContainsTab(new_local_tab_id)); - EXPECT_FALSE(retrieved_group->ContainsTab(kFirstTabToken)); + EXPECT_FALSE(retrieved_group->ContainsTab(tab_1_id)); } // Verifies that when a new tab group is created in the browser it is saved by
diff --git a/chrome/browser/ui/toasts/BUILD.gn b/chrome/browser/ui/toasts/BUILD.gn index ea609f07..4d6d9b3aa 100644 --- a/chrome/browser/ui/toasts/BUILD.gn +++ b/chrome/browser/ui/toasts/BUILD.gn
@@ -67,3 +67,16 @@ "//ui/views", ] } + +source_set("unit_tests") { + testonly = true + sources = [ "toast_controller_unittest.cc" ] + deps = [ + ":toasts", + "//base", + "//base/test:test_support", + "//chrome/test:test_support", + "//testing/gtest", + "//ui/gfx", + ] +}
diff --git a/chrome/browser/ui/toasts/toast_controller.cc b/chrome/browser/ui/toasts/toast_controller.cc index dcfaa00..ec7d0f85 100644 --- a/chrome/browser/ui/toasts/toast_controller.cc +++ b/chrome/browser/ui/toasts/toast_controller.cc
@@ -4,11 +4,23 @@ #include "chrome/browser/ui/toasts/toast_controller.h" +#include <optional> +#include <utility> + +#include "base/check.h" +#include "base/check_op.h" +#include "base/feature_list.h" +#include "base/functional/bind.h" +#include "base/location.h" #include "chrome/browser/ui/browser_window/public/browser_window_interface.h" #include "chrome/browser/ui/toasts/api/toast_id.h" #include "chrome/browser/ui/toasts/api/toast_registry.h" +#include "chrome/browser/ui/toasts/api/toast_specification.h" +#include "chrome/browser/ui/toasts/toast_features.h" ToastParams::ToastParams(ToastId id) : toast_id_(id) {} +ToastParams::ToastParams(ToastParams&& other) noexcept = default; +ToastParams& ToastParams::operator=(ToastParams&& other) noexcept = default; ToastParams::~ToastParams() = default; ToastController::ToastController( @@ -16,27 +28,67 @@ const ToastRegistry* toast_registry) : browser_window_interface_(browser_window_interface), toast_registry_(toast_registry) {} + +// TODO(crbug.com/358610787): ensure that no toast is showing when the +// destructor is called. ToastController::~ToastController() = default; -bool ToastController::CanShowToast(ToastId id) { - // TODO(crbug.com/358609791): Implement controller to work with the toast - // service. - return false; +bool ToastController::IsShowingToast() const { + return current_toast_params_.has_value(); } -void ToastController::ShowToast(ToastParams params) { - is_showing_toast_ = true; - // TODO(crbug.com/358609791): Implement controller to work with the toast - // service. +bool ToastController::CanShowToast(ToastId id) const { + if (!base::FeatureList::IsEnabled(toast_features::kToastFramework)) { + return false; + } + + if (!IsShowingToast()) { + return true; + } + + const ToastSpecification* current_toast_spec = + toast_registry_->GetToastSpecification( + current_toast_params_.value().toast_id_); + const ToastSpecification* potential_toast_spec = + toast_registry_->GetToastSpecification(id); + + return !(current_toast_spec->is_persistent_toast() && + potential_toast_spec->is_persistent_toast()); +} + +bool ToastController::MaybeShowToast(ToastParams params) { + if (!CanShowToast(params.toast_id_)) { + return false; + } + + CloseToast(); + current_toast_params_ = std::move(params); + + const ToastSpecification* current_toast_spec = + toast_registry_->GetToastSpecification( + current_toast_params_.value().toast_id_); + + CHECK(current_toast_spec); + if (!current_toast_spec->is_persistent_toast()) { + toast_close_timer_.Start( + FROM_HERE, toast_features::kToastTimeout.Get(), + base::BindOnce(&ToastController::CloseToast, base::Unretained(this))); + } + + // TODO(crbug.com/358610190): show the toast and manage resetting/stopping the + // timer when a toast is shown or closed. + return true; } void ToastController::ClosePersistentToast(ToastId id) { - // TODO(crbug.com/358609791): Implement controller to work with the toast - // service. + CHECK(current_toast_params_.has_value()); + CHECK_EQ(current_toast_params_.value().toast_id_, id); + // TODO(crbug.com/358610787): close the persistent toast and have internal + // state reflect that. + CloseToast(); } -bool ToastController::IsShowingToast() const { - // TODO(crbug.com/358609791): Implement controller to work with the toast - // service. - return is_showing_toast_; +void ToastController::CloseToast() { + current_toast_params_ = std::nullopt; + // TODO(crbug.com/358610190): close the currently showing toast. }
diff --git a/chrome/browser/ui/toasts/toast_controller.h b/chrome/browser/ui/toasts/toast_controller.h index a2bfb60..71042b2 100644 --- a/chrome/browser/ui/toasts/toast_controller.h +++ b/chrome/browser/ui/toasts/toast_controller.h
@@ -5,10 +5,12 @@ #ifndef CHROME_BROWSER_UI_TOASTS_TOAST_CONTROLLER_H_ #define CHROME_BROWSER_UI_TOASTS_TOAST_CONTROLLER_H_ +#include <optional> #include <string> #include <vector> #include "base/memory/raw_ptr.h" +#include "base/timer/timer.h" class BrowserWindowInterface; class ToastRegistry; @@ -16,6 +18,8 @@ struct ToastParams { explicit ToastParams(ToastId id); + ToastParams(ToastParams&& other) noexcept; + ToastParams& operator=(ToastParams&& other) noexcept; ~ToastParams(); ToastId toast_id_; @@ -29,16 +33,24 @@ const ToastRegistry* toast_registry); ~ToastController(); - bool CanShowToast(ToastId id); - void ShowToast(ToastParams params); - void ClosePersistentToast(ToastId id); bool IsShowingToast() const; + bool CanShowToast(ToastId id) const; + + // Attempts to show the toast and returns true if the toast was successfully + // shown, otherwise return false. Callers that show a persistent toast must + // eventually call ClosePersistentToast() to ensure their toast closes. + bool MaybeShowToast(ToastParams params); + + // Closes the currently showing persistent toast that must correspond to `id`. + void ClosePersistentToast(ToastId id); private: - bool is_showing_toast_ = false; + void CloseToast(); const raw_ptr<BrowserWindowInterface> browser_window_interface_; const raw_ptr<const ToastRegistry> toast_registry_; + std::optional<ToastParams> current_toast_params_; + base::OneShotTimer toast_close_timer_; }; #endif // CHROME_BROWSER_UI_TOASTS_TOAST_CONTROLLER_H_
diff --git a/chrome/browser/ui/toasts/toast_controller_unittest.cc b/chrome/browser/ui/toasts/toast_controller_unittest.cc new file mode 100644 index 0000000..097ba9f --- /dev/null +++ b/chrome/browser/ui/toasts/toast_controller_unittest.cc
@@ -0,0 +1,139 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/toasts/toast_controller.h" + +#include <memory> + +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" +#include "chrome/browser/ui/toasts/api/toast_id.h" +#include "chrome/browser/ui/toasts/api/toast_registry.h" +#include "chrome/browser/ui/toasts/api/toast_specification.h" +#include "chrome/browser/ui/toasts/toast_features.h" +#include "components/vector_icons/vector_icons.h" +#include "testing/gtest/include/gtest/gtest.h" + +class ToastControllerUnitTest : public testing::Test { + public: + void SetUp() override { + feature_list_.InitAndEnableFeature(toast_features::kToastFramework); + toast_registry_ = std::make_unique<ToastRegistry>(); + } + + base::test::SingleThreadTaskEnvironment& task_environment() { + return task_environment_; + } + + ToastRegistry* toast_registry() { return toast_registry_.get(); } + + private: + base::test::ScopedFeatureList feature_list_; + base::test::SingleThreadTaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; + std::unique_ptr<ToastRegistry> toast_registry_; +}; + +TEST_F(ToastControllerUnitTest, ShowEphemeralToast) { + ToastRegistry* const registry = toast_registry(); + registry->RegisterToast( + ToastId::kLinkCopied, + ToastSpecification::Builder(vector_icons::kEmailIcon, 0).Build()); + + auto controller = std::make_unique<ToastController>(nullptr, registry); + + // We should be able to show the toast because there is no toast showing. + EXPECT_FALSE(controller->IsShowingToast()); + EXPECT_TRUE(controller->CanShowToast(ToastId::kLinkCopied)); + + // We can show the toast again because it is an ephemeral toast. + EXPECT_TRUE(controller->MaybeShowToast(ToastParams(ToastId::kLinkCopied))); + EXPECT_TRUE(controller->IsShowingToast()); + EXPECT_TRUE(controller->CanShowToast(ToastId::kLinkCopied)); +} + +TEST_F(ToastControllerUnitTest, ShowPersistentToast) { + ToastRegistry* const registry = toast_registry(); + registry->RegisterToast(ToastId::kLinkCopied, ToastSpecification::Builder( + vector_icons::kEmailIcon, 0) + .AddPersistance() + .Build()); + + registry->RegisterToast( + ToastId::kImageCopied, + ToastSpecification::Builder(vector_icons::kEmailIcon, 0) + .AddPersistance() + .Build()); + + auto controller = std::make_unique<ToastController>(nullptr, registry); + + // We should be able to show the toast because there is no toast showing. + EXPECT_TRUE(controller->CanShowToast(ToastId::kLinkCopied)); + EXPECT_TRUE(controller->MaybeShowToast(ToastParams(ToastId::kLinkCopied))); + EXPECT_TRUE(controller->IsShowingToast()); + + // We should not be able to trigger the same same toast to show or another + // persistent toast because we are already showing a persistent toast. + EXPECT_FALSE(controller->CanShowToast(ToastId::kLinkCopied)); + EXPECT_FALSE(controller->CanShowToast(ToastId::kImageCopied)); +} + +TEST_F(ToastControllerUnitTest, PreemptPersistentToast) { + ToastRegistry* const registry = toast_registry(); + registry->RegisterToast( + ToastId::kLinkCopied, + ToastSpecification::Builder(vector_icons::kEmailIcon, 0).Build()); + registry->RegisterToast( + ToastId::kImageCopied, + ToastSpecification::Builder(vector_icons::kEmailIcon, 0) + .AddPersistance() + .Build()); + + auto controller = std::make_unique<ToastController>(nullptr, registry); + EXPECT_TRUE(controller->MaybeShowToast(ToastParams(ToastId::kImageCopied))); + EXPECT_TRUE(controller->IsShowingToast()); + + // The ephemeral toast can show but the persistent toast cannot show while we + // are currently showing a persistent toast. + EXPECT_TRUE(controller->CanShowToast(ToastId::kLinkCopied)); + EXPECT_FALSE(controller->CanShowToast(ToastId::kImageCopied)); +} + +TEST_F(ToastControllerUnitTest, EphemeralToastAutomaticallyCloses) { + ToastRegistry* const registry = toast_registry(); + registry->RegisterToast( + ToastId::kLinkCopied, + ToastSpecification::Builder(vector_icons::kEmailIcon, 0).Build()); + + auto controller = std::make_unique<ToastController>(nullptr, registry); + + // We can show the toast again because it is an ephemeral toast. + EXPECT_TRUE(controller->MaybeShowToast(ToastParams(ToastId::kLinkCopied))); + EXPECT_TRUE(controller->IsShowingToast()); + + // The toast should stop showing after reaching toast timeout time. + task_environment().FastForwardBy(toast_features::kToastTimeout.Get()); + EXPECT_FALSE(controller->IsShowingToast()); +} + +TEST_F(ToastControllerUnitTest, PersistentToastStaysOpen) { + ToastRegistry* const registry = toast_registry(); + registry->RegisterToast(ToastId::kLinkCopied, ToastSpecification::Builder( + vector_icons::kEmailIcon, 0) + .AddPersistance() + .Build()); + + auto controller = std::make_unique<ToastController>(nullptr, registry); + + EXPECT_TRUE(controller->MaybeShowToast(ToastParams(ToastId::kLinkCopied))); + EXPECT_TRUE(controller->IsShowingToast()); + + // The toast should remain showing even after past the toast timeout time. + task_environment().FastForwardBy(toast_features::kToastTimeout.Get()); + EXPECT_TRUE(controller->IsShowingToast()); + + // Persistent toasts should close when explicitly called to close. + controller->ClosePersistentToast(ToastId::kLinkCopied); + EXPECT_FALSE(controller->IsShowingToast()); +}
diff --git a/chrome/browser/ui/toasts/toast_features.cc b/chrome/browser/ui/toasts/toast_features.cc index fc51157..fe8fb336 100644 --- a/chrome/browser/ui/toasts/toast_features.cc +++ b/chrome/browser/ui/toasts/toast_features.cc
@@ -6,6 +6,7 @@ #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" +#include "base/time/time.h" namespace toast_features { @@ -18,6 +19,9 @@ const base::FeatureParam<bool> kToastDemoMode{&kToastFramework, "toast_demo_mode", false}; +const base::FeatureParam<base::TimeDelta> kToastTimeout{ + &kToastFramework, "toast_timeout", base::Seconds(10)}; + // Enables the link copied confirmation toast. BASE_FEATURE(kLinkCopiedToast, "LinkCopiedToast",
diff --git a/chrome/browser/ui/toasts/toast_features.h b/chrome/browser/ui/toasts/toast_features.h index bcab1f4..18e74f19 100644 --- a/chrome/browser/ui/toasts/toast_features.h +++ b/chrome/browser/ui/toasts/toast_features.h
@@ -7,6 +7,7 @@ #include "base/feature_list.h" #include "base/metrics/field_trial_params.h" +#include "base/time/time.h" namespace toast_features { @@ -17,6 +18,10 @@ // is used for demo mode. extern const base::FeatureParam<bool> kToastDemoMode; +// The amount of time an ephemeral toast should show before automatically +// closing. +extern const base::FeatureParam<base::TimeDelta> kToastTimeout; + // Individual toasts BASE_DECLARE_FEATURE(kLinkCopiedToast); BASE_DECLARE_FEATURE(kImageCopiedToast);
diff --git a/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc b/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc index 6485c05..85d96aa 100644 --- a/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc +++ b/chrome/browser/ui/toolbar/app_menu_fullscreen_interactive_uitest.cc
@@ -203,9 +203,6 @@ MoveMouseTo(kBrowserViewElementId), ClickMouse(ui_controls::RIGHT), // 5. Make sure context menu is displayed correctly at the expected // location when chrome is in full screen mode. - // WaitForShow and FlushEvents is required to prevent re-enter - // views::MenuController::OpenMenu from the same call stack during the - // NotifyElementShown. InAnyContext(WaitForShow(RenderViewContextMenu::kExitFullscreenMenuItem)), CreateFullscreenWaiter(waiter2, false), InAnyContext(
diff --git a/chrome/browser/ui/unload_controller.cc b/chrome/browser/ui/unload_controller.cc index 2029364e..1fe075f 100644 --- a/chrome/browser/ui/unload_controller.cc +++ b/chrome/browser/ui/unload_controller.cc
@@ -57,6 +57,14 @@ return false; } +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Tabs cannot be closed when the app is locked for OnTask. Only relevant for + // non-web browser scenarios. + if (browser_->IsLockedForOnTask()) { + return false; + } +#endif + return !is_attempting_to_close_browser_ || is_calling_before_unload_handlers(); }
diff --git a/chrome/browser/ui/unload_controller_browsertest.cc b/chrome/browser/ui/unload_controller_browsertest.cc index 4669f4ee..777d96e 100644 --- a/chrome/browser/ui/unload_controller_browsertest.cc +++ b/chrome/browser/ui/unload_controller_browsertest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chrome/browser/ui/tabs/tab_strip_model.h" +#include "chrome/browser/ui/unload_controller.h" #include "base/json/json_reader.h" #include "base/test/scoped_feature_list.h" @@ -12,19 +12,21 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_window.h" -#include "chrome/browser/ui/unload_controller.h" +#include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" #include "chrome/browser/web_applications/test/prevent_close_test_base.h" #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" #include "chrome/browser/web_applications/web_app_id_constants.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/common/chrome_features.h" +#include "chrome/test/base/in_process_browser_test.h" #include "components/policy/core/browser/browser_policy_connector.h" #include "components/policy/core/browser/browser_policy_connector_base.h" #include "components/policy/core/common/mock_configuration_policy_provider.h" #include "components/policy/core/common/policy_map.h" #include "components/policy/policy_constants.h" #include "components/webapps/common/web_app_id.h" +#include "content/public/browser/web_contents.h" #include "content/public/test/browser_test.h" #include "third_party/abseil-cpp/absl/cleanup/cleanup.h" #include "ui/base/window_open_disposition.h" @@ -98,3 +100,48 @@ EXPECT_EQ(BrowserClosingStatus::kPermitted, unload_controller.GetBrowserClosingStatus()); } + +#if BUILDFLAG(IS_CHROMEOS_ASH) + +// Browser tests for verifying `UnloadController` behavior for apps when locked +// (and not locked) for OnTask. Only relevant for non-web browser scenarios. +class UnloadControllerWithOnTaskTest : public InProcessBrowserTest { + protected: + webapps::AppId InstallMockApp() { + return web_app::test::InstallDummyWebApp( + browser()->profile(), /*app_name=*/"Mock app", + /*app_url=*/GURL("https://www.example.com/")); + } +}; + +IN_PROC_BROWSER_TEST_F(UnloadControllerWithOnTaskTest, + PreventCloseWhenLockedForOnTask) { + // Install and launch app. + webapps::AppId app_id = InstallMockApp(); + Browser* const app_browser = + web_app::LaunchWebAppBrowser(browser()->profile(), app_id); + app_browser->SetLockedForOnTask(true); + + // Verify tab cannot be closed. + content::WebContents* const active_web_contents = + app_browser->tab_strip_model()->GetWebContentsAt(0); + UnloadController unload_controller(app_browser); + EXPECT_FALSE(unload_controller.CanCloseContents(active_web_contents)); +} + +IN_PROC_BROWSER_TEST_F(UnloadControllerWithOnTaskTest, + AllowCloseWhenNotLockedForOnTask) { + // Install and launch app. + webapps::AppId app_id = InstallMockApp(); + Browser* const app_browser = + web_app::LaunchWebAppBrowser(browser()->profile(), app_id); + app_browser->SetLockedForOnTask(false); + + // Verify tab can be closed. + content::WebContents* const active_web_contents = + app_browser->tab_strip_model()->GetWebContentsAt(0); + UnloadController unload_controller(app_browser); + EXPECT_TRUE(unload_controller.CanCloseContents(active_web_contents)); +} + +#endif
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar_unittest.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar_unittest.cc index d86747f..fa4e1ee 100644 --- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar_unittest.cc +++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_bar_unittest.cc
@@ -9,14 +9,14 @@ #include "base/test/scoped_feature_list.h" #include "base/uuid.h" +#include "chrome/browser/tab_group_sync/tab_group_sync_service_factory.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/layout_constants.h" -#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h" -#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.h" #include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_button.h" #include "chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_overflow_button.h" +#include "chrome/browser/ui/views/frame/test_with_browser_view.h" #include "chrome/grit/generated_resources.h" #include "chrome/test/base/test_browser_window.h" #include "chrome/test/base/testing_profile.h" @@ -25,52 +25,22 @@ #include "components/saved_tab_groups/saved_tab_group_test_utils.h" #include "components/saved_tab_groups/tab_group_sync_service.h" #include "components/saved_tab_groups/types.h" +#include "components/tab_groups/tab_group_id.h" #include "components/tab_groups/tab_group_visual_data.h" +#include "content/public/test/test_renderer_host.h" +#include "content/public/test/web_contents_tester.h" #include "testing/gmock/include/gmock/gmock.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/view_utils.h" namespace tab_groups { namespace { - -const LocalTabGroupID kLocalTabGroupID1 = test::GenerateRandomTabGroupID(); -const LocalTabGroupID kLocalTabGroupID2 = test::GenerateRandomTabGroupID(); -const LocalTabGroupID kLocalTabGroupID3 = test::GenerateRandomTabGroupID(); -const LocalTabGroupID kLocalTabGroupID4 = test::GenerateRandomTabGroupID(); -const LocalTabGroupID kLocalTabGroupID5 = test::GenerateRandomTabGroupID(); - -SavedTabGroup kSavedTabGroup1(std::u16string(u"test_title_1"), - tab_groups::TabGroupColorId::kGrey, - {}, - std::nullopt); - -SavedTabGroup kSavedTabGroup2(std::u16string(u"test_title_2"), - tab_groups::TabGroupColorId::kGrey, - {}, - std::nullopt); - -SavedTabGroup kSavedTabGroup3(std::u16string(u"test_title_3"), - tab_groups::TabGroupColorId::kGrey, - {}, - std::nullopt); - -SavedTabGroup kSavedTabGroup4(std::u16string(u"test_title_4"), - tab_groups::TabGroupColorId::kGrey, - {}, - std::nullopt); - -SavedTabGroup kSavedTabGroup5(std::u16string(u"test_title_5"), - tab_groups::TabGroupColorId::kGrey, - {}, - std::nullopt); - const std::u16string kNewTitle(u"kNewTitle"); const tab_groups::TabGroupColorId kNewColor = tab_groups::TabGroupColorId::kRed; - } // anonymous namespace -class SavedTabGroupBarUnitTest : public ChromeViewsTestBase, +class SavedTabGroupBarUnitTest : public TestWithBrowserView, public ::testing::WithParamInterface<bool> { public: SavedTabGroupBarUnitTest() { @@ -87,13 +57,16 @@ return tab_groups::SavedTabGroupUtils::GetServiceForProfile( browser()->profile()); } - TestingProfile* profile() { return profile_.get(); } int button_padding() { return button_padding_; } void SetUp() override { - ChromeViewsTestBase::SetUp(); - CreateBrowser(); + TestWithBrowserView::SetUp(); + + TabGroupSyncService* service = + tab_groups::SavedTabGroupUtils::GetServiceForProfile( + browser()->profile()); + service->SetIsInitializedForTesting(true); saved_tab_group_bar_ = std::make_unique<SavedTabGroupBar>(browser(), false); saved_tab_group_bar_->SetPageNavigator(nullptr); @@ -101,18 +74,14 @@ void TearDown() override { saved_tab_group_bar_.reset(); - browser_window_.reset(); - browser_.reset(); - profile_.reset(); - - ChromeViewsTestBase::TearDown(); + TestWithBrowserView::TearDown(); } void Add4Groups() { - service()->AddGroup(kSavedTabGroup1); - service()->AddGroup(kSavedTabGroup2); - service()->AddGroup(kSavedTabGroup3); - service()->AddGroup(kSavedTabGroup4); + SaveGroup(CreateNewGroupInBrowser()); + SaveGroup(CreateNewGroupInBrowser()); + SaveGroup(CreateNewGroupInBrowser()); + SaveGroup(CreateNewGroupInBrowser()); } int GetWidthOfButtonsAndPadding() { @@ -129,16 +98,6 @@ return size; } - void CreateBrowser() { - TestingProfile::Builder profile_builder; - profile_ = profile_builder.Build(); - browser_window_ = std::make_unique<TestBrowserWindow>(); - Browser::CreateParams params(profile_.get(), /*user_gesture*/ true); - params.type = Browser::TYPE_NORMAL; - params.window = browser_window_.get(); - browser_.reset(Browser::Create(params)); - } - std::vector<base::Uuid> GetButtonGUIDs() { std::vector<base::Uuid> guids; for (views::View* view : saved_tab_group_bar()->children()) { @@ -162,13 +121,34 @@ return guids; } - Browser* browser() { return browser_.get(); } + tab_groups::TabGroupId CreateNewGroupInBrowser() { + AddTabToBrowser(browser(), 0); + tab_groups::TabGroupId local_id = + browser()->tab_strip_model()->AddToNewGroup({0}); + return local_id; + } + + base::Uuid SaveGroup(const tab_groups::TabGroupId& local_id) { + SavedTabGroup group = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + local_id); + const base::Uuid sync_id = group.saved_guid(); + service()->AddGroup(std::move(group)); + return sync_id; + } + + void AddTabToBrowser(Browser* browser, int index) { + std::unique_ptr<content::WebContents> web_contents = + content::WebContentsTester::CreateTestWebContents(browser->profile(), + nullptr); + + browser->tab_strip_model()->AddWebContents( + std::move(web_contents), index, + ui::PageTransition::PAGE_TRANSITION_TYPED, AddTabTypes::ADD_ACTIVE); + } private: base::test::ScopedFeatureList feature_list_; - std::unique_ptr<TestingProfile> profile_; - std::unique_ptr<TestBrowserWindow> browser_window_; - std::unique_ptr<Browser> browser_; std::unique_ptr<SavedTabGroupBar> saved_tab_group_bar_; static constexpr int button_padding_ = 8; @@ -207,22 +187,27 @@ EXPECT_EQ(menu_model()->GetItemCount(), 1u); // Add three test groups. - const SavedTabGroup saved_tab_group1(std::u16string(u"test_title_1"), - tab_groups::TabGroupColorId::kGrey, {}, - std::nullopt); - service()->AddGroup(saved_tab_group1); + const std::u16string title_1 = u"test_title_1"; + const std::u16string title_2 = u"test_title_2"; + const std::u16string title_3 = u"test_title_3"; - task_environment()->FastForwardBy(interval_); - const SavedTabGroup saved_tab_group2(std::u16string(u"test_title_2"), - tab_groups::TabGroupColorId::kGrey, {}, - std::nullopt); - service()->AddGroup(saved_tab_group2); + SavedTabGroup group_1 = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + CreateNewGroupInBrowser()); + SavedTabGroup group_2 = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + CreateNewGroupInBrowser()); + SavedTabGroup group_3 = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + CreateNewGroupInBrowser()); - task_environment()->FastForwardBy(interval_); - const SavedTabGroup saved_tab_group3(std::u16string(u"test_title_3"), - tab_groups::TabGroupColorId::kGrey, {}, - std::nullopt); - service()->AddGroup(saved_tab_group3); + group_1.SetTitle(title_1); + group_2.SetTitle(title_2); + group_3.SetTitle(title_3); + + service()->AddGroup(std::move(group_1)); + service()->AddGroup(std::move(group_2)); + service()->AddGroup(std::move(group_3)); // A separator is also added. auto model = menu_model(); @@ -230,9 +215,9 @@ // The three added tab group items starts from model index 2. They are sorted // by most recent created first. - EXPECT_EQ(model->GetLabelAt(2), u"test_title_3"); - EXPECT_EQ(model->GetLabelAt(3), u"test_title_2"); - EXPECT_EQ(model->GetLabelAt(4), u"test_title_1"); + EXPECT_EQ(model->GetLabelAt(2), title_3); + EXPECT_EQ(model->GetLabelAt(3), title_2); + EXPECT_EQ(model->GetLabelAt(4), title_1); } TEST_P(SavedTabGroupBarUnitTest, AddsButtonFromModelAdd) { @@ -241,13 +226,18 @@ // that is invisible. EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); - service()->AddGroup(kSavedTabGroup1); - EXPECT_EQ(IsV2UIEnabled() ? 1u : 2u, - saved_tab_group_bar()->children().size()); + const tab_groups::TabGroupId& local_id = CreateNewGroupInBrowser(); + SaveGroup(local_id); - SavedTabGroup group_2_with_position = kSavedTabGroup2; - group_2_with_position.SetPosition(1); - service()->AddGroup(group_2_with_position); + EXPECT_EQ(2u, saved_tab_group_bar()->children().size()); + + const tab_groups::TabGroupId& local_id_2 = CreateNewGroupInBrowser(); + SavedTabGroup group = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + local_id_2); + group.SetPinned(false); + service()->AddGroup(std::move(group)); + EXPECT_EQ(IsV2UIEnabled() ? 2u : 3u, saved_tab_group_bar()->children().size()); } @@ -265,14 +255,15 @@ EXPECT_TRUE(overflow_button->GetVisible()); // Add a tab group button; the Everything button is still there. - service()->AddGroup(kSavedTabGroup1); + const base::Uuid& sync_id = SaveGroup(CreateNewGroupInBrowser()); + saved_tab_group_bar()->SetBounds( 0, 2, saved_tab_group_bar()->CalculatePreferredWidthRestrictedBy(400), 2); EXPECT_TRUE(overflow_button->GetVisible()); // Remove the last tab group button; the Everything button is still there. - service()->RemoveGroup(kSavedTabGroup1.saved_guid()); + service()->RemoveGroup(sync_id); saved_tab_group_bar()->SetBounds( 0, 2, saved_tab_group_bar()->CalculatePreferredWidthRestrictedBy(400), 2); @@ -303,7 +294,7 @@ // Verify that the overflow button is visible when a 5th button is added and // that the 5th button is not visible. - service()->AddGroup(kSavedTabGroup5); + SaveGroup(CreateNewGroupInBrowser()); // Layout the buttons. saved_tab_group_bar()->SetBounds( @@ -330,7 +321,8 @@ // Verify that the overflow button is visible when a 5th button is added and // that the 5th button is not visible. Add4Groups(); - service()->AddGroup(kSavedTabGroup5); + + const base::Uuid& sync_id = SaveGroup(CreateNewGroupInBrowser()); // Layout the buttons. saved_tab_group_bar()->SetBounds( @@ -340,7 +332,7 @@ EXPECT_FALSE(saved_tab_group_bar()->children()[4]->GetVisible()); EXPECT_EQ(6u, saved_tab_group_bar()->children().size()); - service()->RemoveGroup(kSavedTabGroup5.saved_guid()); + service()->RemoveGroup(sync_id); // Layout the buttons. saved_tab_group_bar()->SetBounds( @@ -366,7 +358,8 @@ // Verify that the overflow button is visible when a 5th button is added and // that the 5th button is not visible. Add4Groups(); - service()->AddGroup(kSavedTabGroup5); + + const base::Uuid& sync_id = SaveGroup(CreateNewGroupInBrowser()); // Layout the buttons. saved_tab_group_bar()->SetBounds( @@ -376,7 +369,7 @@ EXPECT_FALSE(saved_tab_group_bar()->children()[4]->GetVisible()); EXPECT_EQ(6u, saved_tab_group_bar()->children().size()); - service()->RemoveGroup(kSavedTabGroup5.saved_guid()); + service()->RemoveGroup(sync_id); // Layout the buttons. saved_tab_group_bar()->SetBounds( @@ -388,7 +381,7 @@ } TEST_P(SavedTabGroupBarUnitTest, BarsWithSameModelsHaveSameButtons) { - service()->AddGroup(kSavedTabGroup1); + SaveGroup(CreateNewGroupInBrowser()); SavedTabGroupBar another_tab_group_bar_on_same_model( browser(), @@ -399,45 +392,42 @@ } TEST_P(SavedTabGroupBarUnitTest, RemoveButtonFromModelRemove) { - service()->AddGroup(kSavedTabGroup1); - // Remove the group and expect no buttons except the overflow menu. - service()->RemoveGroup(kSavedTabGroup1.saved_guid()); + const base::Uuid& sync_id = SaveGroup(CreateNewGroupInBrowser()); + service()->RemoveGroup(sync_id); EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); EXPECT_TRUE(views::IsViewClass<SavedTabGroupOverflowButton>( saved_tab_group_bar()->children()[0])); - SavedTabGroup group_1_with_position = kSavedTabGroup1; - group_1_with_position.SetPosition(1); - service()->AddGroup(group_1_with_position); - // Remove the group and expect no buttons. - service()->RemoveGroup(kSavedTabGroup1.saved_guid()); + const base::Uuid& sync_id_2 = SaveGroup(CreateNewGroupInBrowser()); + service()->RemoveGroup(sync_id_2); EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); EXPECT_TRUE(views::IsViewClass<SavedTabGroupOverflowButton>( saved_tab_group_bar()->children()[0])); } TEST_P(SavedTabGroupBarUnitTest, UpdatedVisualDataMakesChangeToSpecificView) { - service()->AddGroup(kSavedTabGroup1); - SavedTabGroup group_2_with_position = kSavedTabGroup2; - group_2_with_position.SetPosition(1); - service()->AddGroup(group_2_with_position); + const tab_groups::TabGroupId& local_id_1 = CreateNewGroupInBrowser(); + SavedTabGroup group = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + local_id_1); + service()->AddGroup(std::move(group)); - const LocalTabGroupID local_group_id_1 = test::GenerateRandomTabGroupID(); - const LocalTabGroupID local_group_id_2 = test::GenerateRandomTabGroupID(); - service()->UpdateLocalTabGroupMapping(kSavedTabGroup1.saved_guid(), - local_group_id_1); - service()->UpdateLocalTabGroupMapping(kSavedTabGroup2.saved_guid(), - local_group_id_2); + const tab_groups::TabGroupId& local_id_2 = CreateNewGroupInBrowser(); + SavedTabGroup group_2 = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + local_id_2); + group_2.SetPinned(false); + service()->AddGroup(std::move(group_2)); tab_groups::TabGroupVisualData saved_tab_group_visual_data(kNewTitle, kNewColor); // Update the visual_data and expect the first button to be updated and the // second button to stay the same. - service()->UpdateVisualData(local_group_id_1, &saved_tab_group_visual_data); - service()->UpdateVisualData(local_group_id_2, &saved_tab_group_visual_data); + service()->UpdateVisualData(local_id_1, &saved_tab_group_visual_data); + service()->UpdateVisualData(local_id_2, &saved_tab_group_visual_data); SavedTabGroupButton* new_button_1 = views::AsViewClass<SavedTabGroupButton>( saved_tab_group_bar()->children()[0]); @@ -462,53 +452,41 @@ } TEST_P(SavedTabGroupBarUnitTest, MoveButtonFromModelMove) { - const base::Uuid guid_1 = kSavedTabGroup1.saved_guid(); - const base::Uuid guid_2 = kSavedTabGroup2.saved_guid(); - const base::Uuid guid_3 = kSavedTabGroup3.saved_guid(); + const base::Uuid sync_id_1 = SaveGroup(CreateNewGroupInBrowser()); + const base::Uuid sync_id_2 = SaveGroup(CreateNewGroupInBrowser()); + const base::Uuid sync_id_3 = SaveGroup(CreateNewGroupInBrowser()); if (IsV2UIEnabled()) { - SavedTabGroup group1 = kSavedTabGroup1; - group1.SetPinned(true); - SavedTabGroup group2 = kSavedTabGroup2; - group2.SetPinned(true); - SavedTabGroup group3 = kSavedTabGroup3; - group3.SetPinned(true); - service()->AddGroup(group1); - service()->AddGroup(group2); - service()->AddGroup(group3); - - ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_3, guid_2, guid_1)); - service()->UpdateGroupPosition(kSavedTabGroup2.saved_guid(), std::nullopt, - 2); - EXPECT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_3, guid_1, guid_2)); - service()->UpdateGroupPosition(kSavedTabGroup2.saved_guid(), std::nullopt, - 0); - EXPECT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_2, guid_3, guid_1)); - service()->UpdateGroupPosition(kSavedTabGroup2.saved_guid(), std::nullopt, - 1); - EXPECT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_3, guid_2, guid_1)); + ASSERT_THAT(GetButtonGUIDs(), + testing::ElementsAre(sync_id_3, sync_id_2, sync_id_1)); + service()->UpdateGroupPosition(sync_id_2, std::nullopt, 2); + EXPECT_THAT(GetButtonGUIDs(), + testing::ElementsAre(sync_id_3, sync_id_1, sync_id_2)); + service()->UpdateGroupPosition(sync_id_2, std::nullopt, 0); + EXPECT_THAT(GetButtonGUIDs(), + testing::ElementsAre(sync_id_2, sync_id_3, sync_id_1)); + service()->UpdateGroupPosition(sync_id_2, std::nullopt, 1); + EXPECT_THAT(GetButtonGUIDs(), + testing::ElementsAre(sync_id_3, sync_id_2, sync_id_1)); } else { - service()->AddGroup(kSavedTabGroup1); - service()->AddGroup(kSavedTabGroup2); - service()->AddGroup(kSavedTabGroup3); - - ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_1, guid_2, guid_3)); - service()->UpdateGroupPosition(kSavedTabGroup2.saved_guid(), std::nullopt, - 2); - EXPECT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_1, guid_3, guid_2)); - service()->UpdateGroupPosition(kSavedTabGroup2.saved_guid(), std::nullopt, - 0); - EXPECT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_2, guid_1, guid_3)); - service()->UpdateGroupPosition(kSavedTabGroup2.saved_guid(), std::nullopt, - 1); - EXPECT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_1, guid_2, guid_3)); + ASSERT_THAT(GetButtonGUIDs(), + testing::ElementsAre(sync_id_1, sync_id_2, sync_id_3)); + service()->UpdateGroupPosition(sync_id_2, std::nullopt, 2); + EXPECT_THAT(GetButtonGUIDs(), + testing::ElementsAre(sync_id_1, sync_id_3, sync_id_2)); + service()->UpdateGroupPosition(sync_id_2, std::nullopt, 0); + EXPECT_THAT(GetButtonGUIDs(), + testing::ElementsAre(sync_id_2, sync_id_1, sync_id_3)); + service()->UpdateGroupPosition(sync_id_2, std::nullopt, 1); + EXPECT_THAT(GetButtonGUIDs(), + testing::ElementsAre(sync_id_1, sync_id_2, sync_id_3)); } } // If the restriction is exactly the expected size all should be visible TEST_P(SavedTabGroupBarUnitTest, CalculatePreferredWidthRestrictedByExactSize) { if (IsV2UIEnabled()) { - GTEST_SKIP() << "N/A for V2"; + GTEST_SKIP() << "N/A for V1"; } Add4Groups(); @@ -521,7 +499,7 @@ // After 4 buttons have been added (excluding the invisible overflow), all // subsequent buttons will be hidden. Instead an overflow menu will appear // which will house the hidden buttons. - service()->AddGroup(kSavedTabGroup5); + SaveGroup(CreateNewGroupInBrowser()); // Layout the buttons. saved_tab_group_bar()->SetBounds( @@ -540,7 +518,7 @@ TEST_P(SavedTabGroupBarUnitTest, CalculatePreferredWidthRestrictedByLargerSize) { if (IsV2UIEnabled()) { - GTEST_SKIP() << "N/A for V2"; + GTEST_SKIP() << "N/A for V1"; } Add4Groups(); @@ -553,7 +531,7 @@ // After 4 buttons have been added (excluding the invisible overflow), all // subsequent buttons will be hidden. Instead an overflow menu will appear // which will house the hidden buttons. - service()->AddGroup(kSavedTabGroup5); + SaveGroup(CreateNewGroupInBrowser()); // Layout the buttons. saved_tab_group_bar()->SetBounds( @@ -571,7 +549,7 @@ TEST_P(SavedTabGroupBarUnitTest, CalculatePreferredWidthRestrictedBySmallerSize) { if (IsV2UIEnabled()) { - GTEST_SKIP() << "N/A for V2"; + GTEST_SKIP() << "N/A for V1"; } Add4Groups(); @@ -584,7 +562,7 @@ // After 4 buttons have been added (excluding the invisible overflow), all // subsequent buttons will be hidden. Instead an overflow menu will appear // which will house the hidden buttons. - service()->AddGroup(kSavedTabGroup5); + SaveGroup(CreateNewGroupInBrowser()); // Layout the buttons. saved_tab_group_bar()->SetBounds( @@ -600,15 +578,13 @@ // Verify add pinned tab group will add a button. TEST_P(SavedTabGroupBarUnitTest, AddPinnedTabGroupButton) { if (!IsV2UIEnabled()) { - GTEST_SKIP() << "N/A for V2"; + GTEST_SKIP() << "N/A for V1"; } EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); - SavedTabGroup group1 = kSavedTabGroup1; - group1.SetPinned(true); + SaveGroup(CreateNewGroupInBrowser()); - service()->AddGroup(group1); EXPECT_EQ(2u, saved_tab_group_bar()->children().size()); EXPECT_TRUE(!!views::AsViewClass<SavedTabGroupButton>( saved_tab_group_bar()->children()[0])); @@ -617,16 +593,22 @@ // Verify pin an existing tab group will add a button. TEST_P(SavedTabGroupBarUnitTest, PinTabGroupAddButton) { if (!IsV2UIEnabled()) { - GTEST_SKIP() << "N/A for V2"; + GTEST_SKIP() << "N/A for V1"; } EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); - service()->AddGroup(kSavedTabGroup1); + const tab_groups::TabGroupId& local_id_2 = CreateNewGroupInBrowser(); + SavedTabGroup group = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + local_id_2); + const base::Uuid sync_id = group.saved_guid(); + group.SetPinned(false); + service()->AddGroup(std::move(group)); + EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); - service()->UpdateGroupPosition(kSavedTabGroup1.saved_guid(), - !kSavedTabGroup1.is_pinned(), std::nullopt); + service()->UpdateGroupPosition(sync_id, true, std::nullopt); EXPECT_EQ(2u, saved_tab_group_bar()->children().size()); EXPECT_TRUE(!!views::AsViewClass<SavedTabGroupButton>( saved_tab_group_bar()->children()[0])); @@ -635,85 +617,103 @@ // Verify unpin an existing tab group will remove a button. TEST_P(SavedTabGroupBarUnitTest, UnpinTabGroupRemoveButton) { if (!IsV2UIEnabled()) { - GTEST_SKIP() << "N/A for V2"; - } - - EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); - - SavedTabGroup group1 = kSavedTabGroup1; - group1.SetPinned(true); - - service()->AddGroup(group1); - EXPECT_EQ(2u, saved_tab_group_bar()->children().size()); - - service()->UpdateGroupPosition(kSavedTabGroup1.saved_guid(), false, - std::nullopt); - EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); -} - -TEST_P(SavedTabGroupBarUnitTest, PinAndUnpinMultipleTabGroups) { - if (!IsV2UIEnabled()) { - GTEST_SKIP() << "N/A for V2"; - } - - const base::Uuid guid_1 = kSavedTabGroup1.saved_guid(); - const base::Uuid guid_2 = kSavedTabGroup2.saved_guid(); - const base::Uuid guid_3 = kSavedTabGroup3.saved_guid(); - - EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); - - service()->AddGroup(kSavedTabGroup1); - service()->AddGroup(kSavedTabGroup2); - service()->AddGroup(kSavedTabGroup3); - EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); - - service()->UpdateGroupPosition(guid_1, true, std::nullopt); - EXPECT_EQ(2u, saved_tab_group_bar()->children().size()); - ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_1)); - - service()->UpdateGroupPosition(guid_2, true, std::nullopt); - EXPECT_EQ(3u, saved_tab_group_bar()->children().size()); - ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_2, guid_1)); - - service()->UpdateGroupPosition(guid_3, true, std::nullopt); - EXPECT_EQ(4u, saved_tab_group_bar()->children().size()); - ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_3, guid_2, guid_1)); - - std::optional<SavedTabGroup> retrieved_group_1 = service()->GetGroup(guid_1); - std::optional<SavedTabGroup> retrieved_group_2 = service()->GetGroup(guid_2); - std::optional<SavedTabGroup> retrieved_group_3 = service()->GetGroup(guid_3); - - service()->UpdateGroupPosition(guid_1, false, std::nullopt); - EXPECT_EQ(3u, saved_tab_group_bar()->children().size()); - ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_3, guid_2)); - - service()->UpdateGroupPosition(guid_2, false, std::nullopt); - EXPECT_EQ(2u, saved_tab_group_bar()->children().size()); - ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(guid_3)); - - service()->UpdateGroupPosition(guid_3, false, std::nullopt); - EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); -} - -TEST_P(SavedTabGroupBarUnitTest, OnlyShowEverthingButtonForV2) { - if (IsV2UIEnabled()) { GTEST_SKIP() << "N/A for V1"; } EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); - service()->AddGroup(kSavedTabGroup1); + const base::Uuid& sync_id = SaveGroup(CreateNewGroupInBrowser()); EXPECT_EQ(2u, saved_tab_group_bar()->children().size()); + service()->UpdateGroupPosition(sync_id, false, std::nullopt); + EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); +} + +TEST_P(SavedTabGroupBarUnitTest, PinAndUnpinMultipleTabGroups) { + if (!IsV2UIEnabled()) { + GTEST_SKIP() << "N/A for V1"; + } + + EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); + + SavedTabGroup group_1 = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + CreateNewGroupInBrowser()); + SavedTabGroup group_2 = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + CreateNewGroupInBrowser()); + SavedTabGroup group_3 = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + CreateNewGroupInBrowser()); + + group_1.SetPinned(false); + group_2.SetPinned(false); + group_3.SetPinned(false); + + const base::Uuid sync_id_1 = group_1.saved_guid(); + const base::Uuid sync_id_2 = group_2.saved_guid(); + const base::Uuid sync_id_3 = group_3.saved_guid(); + + service()->AddGroup(std::move(group_1)); + service()->AddGroup(std::move(group_2)); + service()->AddGroup(std::move(group_3)); + + EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); + + service()->UpdateGroupPosition(sync_id_1, true, std::nullopt); + EXPECT_EQ(2u, saved_tab_group_bar()->children().size()); + ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(sync_id_1)); + + service()->UpdateGroupPosition(sync_id_2, true, std::nullopt); + EXPECT_EQ(3u, saved_tab_group_bar()->children().size()); + ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(sync_id_2, sync_id_1)); + + service()->UpdateGroupPosition(sync_id_3, true, std::nullopt); + EXPECT_EQ(4u, saved_tab_group_bar()->children().size()); + ASSERT_THAT(GetButtonGUIDs(), + testing::ElementsAre(sync_id_3, sync_id_2, sync_id_1)); + + std::optional<SavedTabGroup> retrieved_group_1 = + service()->GetGroup(sync_id_1); + std::optional<SavedTabGroup> retrieved_group_2 = + service()->GetGroup(sync_id_2); + std::optional<SavedTabGroup> retrieved_group_3 = + service()->GetGroup(sync_id_3); + + service()->UpdateGroupPosition(sync_id_1, false, std::nullopt); + EXPECT_EQ(3u, saved_tab_group_bar()->children().size()); + ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(sync_id_3, sync_id_2)); + + service()->UpdateGroupPosition(sync_id_2, false, std::nullopt); + EXPECT_EQ(2u, saved_tab_group_bar()->children().size()); + ASSERT_THAT(GetButtonGUIDs(), testing::ElementsAre(sync_id_3)); + + service()->UpdateGroupPosition(sync_id_3, false, std::nullopt); + EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); +} + +TEST_P(SavedTabGroupBarUnitTest, OnlyShowEverthingButtonForV2) { + if (!IsV2UIEnabled()) { + GTEST_SKIP() << "N/A for V1"; + } + + EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); + + SavedTabGroup group = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId( + CreateNewGroupInBrowser()); + group.SetPinned(false); + service()->AddGroup(std::move(group)); + + EXPECT_EQ(1u, saved_tab_group_bar()->children().size()); + saved_tab_group_bar()->SetBounds( 0, 2, saved_tab_group_bar()->CalculatePreferredWidthRestrictedBy(40), 2); // Saved tab group button is not visible because there's not enough space. - EXPECT_FALSE(saved_tab_group_bar()->children()[0]->GetVisible()); - // Everything button is visible. - EXPECT_TRUE(saved_tab_group_bar()->children()[1]->GetVisible()); + EXPECT_TRUE(saved_tab_group_bar()->children()[0]->GetVisible()); } TEST_P(SavedTabGroupBarUnitTest, AccessibleProperties) {
diff --git a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_interactive_uitest.cc b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_interactive_uitest.cc index f2ac09b..ea5f9e3 100644 --- a/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_interactive_uitest.cc +++ b/chrome/browser/ui/views/bookmarks/saved_tab_groups/saved_tab_group_interactive_uitest.cc
@@ -34,6 +34,7 @@ #include "components/prefs/pref_service.h" #include "components/saved_tab_groups/features.h" #include "components/saved_tab_groups/saved_tab_group_model.h" +#include "components/saved_tab_groups/tab_group_sync_service.h" #include "components/tab_groups/tab_group_color.h" #include "components/tab_groups/tab_group_id.h" #include "content/public/test/browser_test.h" @@ -176,21 +177,20 @@ StepBuilder SaveGroupViaModel(const tab_groups::TabGroupId local_group) { return Do([=, this]() { - SavedTabGroupKeyedService* const service = - SavedTabGroupServiceFactory::GetForProfile(browser()->profile()); - - service->SaveGroup(local_group); - ASSERT_NE(nullptr, service->model()->Get(local_group)); + TabGroupSyncService* service = + SavedTabGroupUtils::GetServiceForProfile(browser()->profile()); + service->AddGroup( + SavedTabGroupUtils::CreateSavedTabGroupFromLocalId(local_group)); + ASSERT_TRUE(service->GetGroup(local_group).has_value()); }); } StepBuilder UnsaveGroupViaModel(const tab_groups::TabGroupId local_group) { return Do([=, this]() { - SavedTabGroupKeyedService* const service = - SavedTabGroupServiceFactory::GetForProfile(browser()->profile()); - - service->model()->Remove(local_group); - ASSERT_EQ(nullptr, service->model()->Get(local_group)); + TabGroupSyncService* service = + SavedTabGroupUtils::GetServiceForProfile(browser()->profile()); + service->RemoveGroup(local_group); + ASSERT_FALSE(service->GetGroup(local_group).has_value()); }); } @@ -1091,110 +1091,6 @@ EXPECT_EQ(1, model->GetIndexOf(group_id_1).value()); } -// TODO(crbug.com/41494455): Deflake this test before enabling -#if BUILDFLAG(IS_MAC) -#define MAYBE_OverflowMenuUpdatesWhileOpen DISABLED_OverflowMenuUpdatesWhileOpen -#else -#define MAYBE_OverflowMenuUpdatesWhileOpen OverflowMenuUpdatesWhileOpen -#endif // BUILDFLAG(IS_MAC) -IN_PROC_BROWSER_TEST_P(SavedTabGroupInteractiveTest, - MAYBE_OverflowMenuUpdatesWhileOpen) { - if (IsV2UIEnabled()) { - GTEST_SKIP() << "N/A for V2"; - } - - // Add 5 additional tabs to the browser. - ASSERT_TRUE( - AddTabAtIndex(0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED)); - ASSERT_TRUE( - AddTabAtIndex(0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED)); - ASSERT_TRUE( - AddTabAtIndex(0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED)); - ASSERT_TRUE( - AddTabAtIndex(0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED)); - ASSERT_TRUE( - AddTabAtIndex(0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED)); - ASSERT_EQ(6, browser()->tab_strip_model()->count()); - - // Add each tab to a separate group. - const tab_groups::TabGroupId group_1 = - browser()->tab_strip_model()->AddToNewGroup({0}); - const tab_groups::TabGroupId group_2 = - browser()->tab_strip_model()->AddToNewGroup({1}); - const tab_groups::TabGroupId group_3 = - browser()->tab_strip_model()->AddToNewGroup({2}); - const tab_groups::TabGroupId group_4 = - browser()->tab_strip_model()->AddToNewGroup({3}); - const tab_groups::TabGroupId group_5 = - browser()->tab_strip_model()->AddToNewGroup({4}); - const tab_groups::TabGroupId group_6 = - browser()->tab_strip_model()->AddToNewGroup({5}); - - int menu_widget_height; - - RunTestSequence( - // Show the bookmarks bar where the buttons will be displayed. - FinishTabstripAnimations(), ShowBookmarksBar(), - // Ensure no saved group buttons in the bookmarks bar are present. - EnsureNotPresent(kSavedTabGroupButtonElementId), - - // Add views until we get an overflow button. - SaveGroupAndCloseEditorBubble(group_1), FinishTabstripAnimations(), - SaveGroupAndCloseEditorBubble(group_2), FinishTabstripAnimations(), - SaveGroupAndCloseEditorBubble(group_3), FinishTabstripAnimations(), - SaveGroupAndCloseEditorBubble(group_4), FinishTabstripAnimations(), - SaveGroupAndCloseEditorBubble(group_5), FinishTabstripAnimations(), - WaitForShow(kSavedTabGroupOverflowButtonElementId), - - // Show the overflow menu. - PressButton(kSavedTabGroupOverflowButtonElementId), - WaitForShow(kSavedTabGroupOverflowMenuId, true), Do([=, this]() { - BrowserView::GetBrowserViewForBrowser(browser()) - ->GetWidget() - ->LayoutRootViewIfNecessary(); - }), - - CheckView(kSavedTabGroupOverflowMenuId, - [&menu_widget_height](views::View* el) { - menu_widget_height = el->bounds().height(); - return true; - }), - - // Verify the overflow menu expands if another group is added. - SaveGroupViaModel(group_6), Do([=, this]() { - BrowserView::GetBrowserViewForBrowser(browser()) - ->GetWidget() - ->LayoutRootViewIfNecessary(); - }), - - CheckView(kSavedTabGroupOverflowMenuId, - [&menu_widget_height](views::View* el) { - const int old_height = menu_widget_height; - menu_widget_height = el->bounds().height(); - return menu_widget_height > old_height; - }), - - // Verify the overflow menu shrinks if a group is removed. - UnsaveGroupViaModel(group_6), Do([=, this]() { - BrowserView::GetBrowserViewForBrowser(browser()) - ->GetWidget() - ->LayoutRootViewIfNecessary(); - }), - - CheckView(kSavedTabGroupOverflowMenuId, - [&menu_widget_height](views::View* el) { - const int old_height = menu_widget_height; - menu_widget_height = el->bounds().height(); - return menu_widget_height < old_height; - }), - // Hide the overflow menu. - - SendAccelerator( - kSavedTabGroupOverflowMenuId, - ui::Accelerator(ui::KeyboardCode::VKEY_ESCAPE, ui::EF_NONE)), - WaitForHide(kSavedTabGroupOverflowMenuId)); -} - IN_PROC_BROWSER_TEST_P(SavedTabGroupInteractiveTest, OverflowMenuClosesWhenNoMoreButtons) { if (IsV2UIEnabled()) {
diff --git a/chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.cc b/chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.cc index d58e6b05..2929510d 100644 --- a/chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.cc +++ b/chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.cc
@@ -7,6 +7,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_element_identifiers.h" +#include "chrome/browser/ui/views/data_sharing/data_sharing_utils.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/top_container_view.h" #include "chrome/browser/ui/webui/data_sharing/data_sharing_ui.h" @@ -36,15 +37,22 @@ DataSharingBubbleController::~DataSharingBubbleController() = default; -void DataSharingBubbleController::Show() { +void DataSharingBubbleController::Show( + std::variant<tab_groups::LocalTabGroupID, data_sharing::GroupToken> + request_info) { if (bubble_view_) { return; } + auto url = + data_sharing::GenerateWebUIUrl(request_info, GetBrowser().profile()); + if (!url) { + return; + } auto contents_wrapper = std::make_unique<WebUIContentsWrapperT<DataSharingUI>>( - GURL(chrome::kChromeUIUntrustedDataSharingURL), - GetBrowser().profile(), IDS_DATA_SHARING_BUBBLE_DIALOG_TITLE, + url.value(), GetBrowser().profile(), + IDS_DATA_SHARING_BUBBLE_DIALOG_TITLE, /*esc_closes_ui=*/true, /*supports_draggable_regions=*/false);
diff --git a/chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.h b/chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.h index ebf3335..37b22d6 100644 --- a/chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.h +++ b/chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.h
@@ -7,6 +7,8 @@ #include "chrome/browser/ui/browser_user_data.h" #include "chrome/browser/ui/views/bubble/webui_bubble_manager.h" +#include "components/data_sharing/public/group_data.h" +#include "components/saved_tab_groups/types.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/base/metadata/metadata_impl_macros.h" @@ -19,8 +21,10 @@ delete; ~DataSharingBubbleController() override; - // Shows an instance of the data sharing bubble for this browser. - void Show(); + // `request_info` contains the values we want to pass into the loaded WebUI in + // this bubble. + void Show(std::variant<tab_groups::LocalTabGroupID, data_sharing::GroupToken> + request_info); // Closes the instance of the data sharing bubble. void Close();
diff --git a/chrome/browser/ui/views/data_sharing/data_sharing_bubble_interactive_test.cc b/chrome/browser/ui/views/data_sharing/data_sharing_bubble_interactive_test.cc index 0736101f..185cac1 100644 --- a/chrome/browser/ui/views/data_sharing/data_sharing_bubble_interactive_test.cc +++ b/chrome/browser/ui/views/data_sharing/data_sharing_bubble_interactive_test.cc
@@ -2,71 +2,181 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "build/chromeos_buildflags.h" +#include <optional> +#include <string> + +#include "base/check.h" +#include "build/build_config.h" +#include "chrome/browser/data_sharing/data_sharing_service_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_element_identifiers.h" -#include "chrome/browser/ui/views/data_sharing/data_sharing_bubble_controller.h" +#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_keyed_service.h" +#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_service_factory.h" +#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h" +#include "chrome/browser/ui/tabs/tab_group.h" +#include "chrome/browser/ui/ui_features.h" +#include "chrome/browser/ui/views/data_sharing/data_sharing_utils.h" +#include "chrome/browser/ui/views/tabs/tab_group_header.h" +#include "chrome/browser/ui/views/tabs/tab_strip.h" +#include "chrome/common/webui_url_constants.h" +#include "chrome/test/interaction/interaction_test_util_browser.h" #include "chrome/test/interaction/interactive_browser_test.h" +#include "components/data_sharing/public/data_sharing_service.h" #include "components/data_sharing/public/features.h" +#include "components/data_sharing/public/group_data.h" +#include "components/saved_tab_groups/features.h" +#include "components/saved_tab_groups/saved_tab_group.h" +#include "components/saved_tab_groups/saved_tab_group_model.h" +#include "components/saved_tab_groups/types.h" +#include "components/tab_groups/tab_group_id.h" #include "content/public/test/browser_test.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "ui/views/widget/any_widget_observer.h" +#include "ui/base/interaction/element_identifier.h" +#include "url/url_constants.h" -namespace { -class DataSharingBubbleInteractiveUiTest : public InteractiveBrowserTest { - public: - DataSharingBubbleInteractiveUiTest() = default; - ~DataSharingBubbleInteractiveUiTest() override = default; - DataSharingBubbleInteractiveUiTest( - const DataSharingBubbleInteractiveUiTest&) = delete; - void operator=(const DataSharingBubbleInteractiveUiTest&) = delete; +class DataSharingChromeNativeUiTest : public InteractiveBrowserTest { + protected: + DataSharingChromeNativeUiTest() = default; + ~DataSharingChromeNativeUiTest() override = default; - auto ShowBubble() { - return Do(base::BindLambdaForTesting([&]() { - base::RunLoop run_loop; - views::AnyWidgetObserver observer(views::test::AnyWidgetTestPasskey{}); - observer.set_initialized_callback( - base::BindLambdaForTesting([&](views::Widget* w) { - if (w->GetName() == "DataSharingBubbleDialogView") { - run_loop.Quit(); - } - })); - auto* controller = - DataSharingBubbleController::GetOrCreateForBrowser(browser()); - controller->Show(); - run_loop.Run(); - })); + void SetUp() override { + scoped_feature_list_.InitWithFeatures( + {data_sharing::features::kDataSharingFeature, + tab_groups::kTabGroupsSaveUIUpdate, tab_groups::kTabGroupsSaveV2}, + {}); + ASSERT_TRUE(embedded_test_server()->InitializeAndListen()); + InProcessBrowserTest::SetUp(); } - auto CloseBubble() { - return Do(base::BindLambdaForTesting([&]() { - base::RunLoop run_loop; - views::AnyWidgetObserver observer(views::test::AnyWidgetTestPasskey{}); - observer.set_closing_callback( - base::BindLambdaForTesting([&](views::Widget* w) { - if (w->GetName() == "DataSharingBubbleDialogView") { - run_loop.Quit(); - } - })); - auto* controller = DataSharingBubbleController::FromBrowser(browser()); - controller->Close(); - run_loop.Run(); - })); + MultiStep FinishTabstripAnimations() { + return Steps( + WaitForShow(kTabStripElementId), + std::move(WithView(kTabStripElementId, [](TabStrip* tab_strip) { + tab_strip->StopAnimating(true); + }).SetDescription("FinishTabstripAnimation"))); + } + + MultiStep HoverTabGroupHeader(tab_groups::TabGroupId group_id) { + const char kTabGroupHeaderToHover[] = "Tab group header to hover"; + return Steps( + FinishTabstripAnimations(), + NameDescendantView( + kBrowserViewElementId, kTabGroupHeaderToHover, + base::BindRepeating( + [](tab_groups::TabGroupId group_id, const views::View* view) { + const TabGroupHeader* header = + views::AsViewClass<TabGroupHeader>(view); + if (!header) { + return false; + } + return header->group().value() == group_id; + }, + group_id)), + MoveMouseTo(kTabGroupHeaderToHover)); + } + + MultiStep SaveGroupLeaveEditorBubbleOpen(tab_groups::TabGroupId group_id) { + return Steps(EnsureNotPresent(kTabGroupEditorBubbleId), + // Right click on the header to open the editor bubble. + HoverTabGroupHeader(group_id), ClickMouse(ui_controls::RIGHT), + // Wait for the tab group editor bubble to appear. + WaitForShow(kTabGroupEditorBubbleId)); + } + + tab_groups::TabGroupId InstrumentATabGroup() { + // Add 1 tab into the browser. And verify there are 2 tabs (The tab when you + // open the browser and the added one). + EXPECT_TRUE( + AddTabAtIndex(0, GURL(url::kAboutBlankURL), ui::PAGE_TRANSITION_TYPED)); + EXPECT_EQ(2, browser()->tab_strip_model()->count()); + return browser()->tab_strip_model()->AddToNewGroup({0, 1}); } private: - base::test::ScopedFeatureList feature_list_{ - data_sharing::features::kDataSharingFeature}; + base::test::ScopedFeatureList scoped_feature_list_; }; -#if BUILDFLAG(IS_CHROMEOS_LACROS) -#define MAYBE_BubbleCanShowAndClose DISABLED_BubbleCanShowAndClose -#else -#define MAYBE_BubbleCanShowAndClose BubbleCanShowAndClose -#endif -IN_PROC_BROWSER_TEST_F(DataSharingBubbleInteractiveUiTest, - MAYBE_BubbleCanShowAndClose) { - RunTestSequence(EnsureNotPresent(kDataSharingBubbleElementId), ShowBubble(), - WaitForShow(kDataSharingBubbleElementId), CloseBubble(), - WaitForHide(kDataSharingBubbleElementId)); +IN_PROC_BROWSER_TEST_F(DataSharingChromeNativeUiTest, ShowShareBubble) { + tab_groups::LocalTabGroupID group_id = InstrumentATabGroup(); + RunTestSequence(FinishTabstripAnimations(), + SaveGroupLeaveEditorBubbleOpen(group_id), + WaitForShow(kTabGroupEditorBubbleShareGroupButtonId), + PressButton(kTabGroupEditorBubbleShareGroupButtonId), + WaitForShow(kDataSharingBubbleElementId)); } -} // namespace + +IN_PROC_BROWSER_TEST_F(DataSharingChromeNativeUiTest, ShowManageBubble) { + // TODO(crbug.com/350514491): Use STGUtils::GetServiceForProfile instead. + auto* tab_group_service = + tab_groups::SavedTabGroupServiceFactory::GetForProfile( + browser()->profile()); + tab_groups::LocalTabGroupID group_id = InstrumentATabGroup(); + auto* group = const_cast<tab_groups::SavedTabGroup*>( + tab_group_service->model()->Get(group_id)); + std::string fake_collaboration_id = "fake_collab_id"; + group->SetCollaborationId(fake_collaboration_id); + + RunTestSequence(FinishTabstripAnimations(), + SaveGroupLeaveEditorBubbleOpen(group_id), + WaitForShow(kTabGroupEditorBubbleManageSharedGroupButtonId), + PressButton(kTabGroupEditorBubbleManageSharedGroupButtonId), + WaitForShow(kDataSharingBubbleElementId)); +} + +IN_PROC_BROWSER_TEST_F(DataSharingChromeNativeUiTest, ShowJoinBubble) { + std::string fake_collaboration_id = "fake_collab_id"; + std::string fake_access_token = "fake_access_token"; + + RunTestSequence( + Do([=]() { + auto share_link = data_sharing::GetShareLink( + fake_collaboration_id, fake_access_token, browser()->profile()); + auto* data_sharing_service = + data_sharing::DataSharingServiceFactory::GetForProfile( + browser()->profile()); + data_sharing_service->HandleShareURLNavigationIntercepted(share_link); + }), + WaitForShow(kDataSharingBubbleElementId)); +} + +IN_PROC_BROWSER_TEST_F(DataSharingChromeNativeUiTest, GenerateWebUIUrl) { + tab_groups::LocalTabGroupID group_id = InstrumentATabGroup(); + std::string fake_collab_id = "fake_collab_id"; + std::string fake_access_token = "fake_access_token"; + auto expected_share_flow_url = + GURL(std::string(chrome::kChromeUIUntrustedDataSharingURL) + "?" + + std::string(data_sharing::kQueryParamFlow) + "=" + + std::string(data_sharing::kFlowShare) + "&" + + std::string(data_sharing::kQueryParamTabGroupId) + "=" + + group_id.ToString()); + auto expected_manage_flow_url = GURL( + std::string(chrome::kChromeUIUntrustedDataSharingURL) + "?" + + std::string(data_sharing::kQueryParamFlow) + "=" + + std::string(data_sharing::kFlowManage) + "&" + + std::string(data_sharing::kQueryParamGroupId) + "=" + fake_collab_id); + auto expected_join_flow_url = GURL( + std::string(chrome::kChromeUIUntrustedDataSharingURL) + "?" + + std::string(data_sharing::kQueryParamFlow) + "=" + + std::string(data_sharing::kFlowJoin) + "&" + + std::string(data_sharing::kQueryParamGroupId) + "=" + fake_collab_id + + "&" + std::string(data_sharing::kQueryParamTokenSecret) + "=" + + fake_access_token); + + auto url = data_sharing::GenerateWebUIUrl(group_id, browser()->profile()); + EXPECT_EQ(url.value().spec(), expected_share_flow_url); + + // TODO(crbug.com/350514491): Use STGUtils::GetServiceForProfile instead. + auto* tab_group_service = + tab_groups::SavedTabGroupServiceFactory::GetForProfile( + browser()->profile()); + tab_groups::SavedTabGroup* group = const_cast<tab_groups::SavedTabGroup*>( + tab_group_service->model()->Get(group_id)); + group->SetCollaborationId(fake_collab_id); + url = data_sharing::GenerateWebUIUrl(group_id, browser()->profile()); + EXPECT_EQ(url.value().spec(), expected_manage_flow_url); + + data_sharing::GroupToken token = data_sharing::GroupToken( + data_sharing::GroupId(fake_collab_id), fake_access_token); + url = data_sharing::GenerateWebUIUrl(token, browser()->profile()); + EXPECT_EQ(url.value().spec(), expected_join_flow_url); +}
diff --git a/chrome/browser/ui/views/data_sharing/data_sharing_utils.cc b/chrome/browser/ui/views/data_sharing/data_sharing_utils.cc new file mode 100644 index 0000000..945d568 --- /dev/null +++ b/chrome/browser/ui/views/data_sharing/data_sharing_utils.cc
@@ -0,0 +1,97 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/ui/views/data_sharing/data_sharing_utils.h" + +#include "base/token.h" +#include "chrome/browser/data_sharing/data_sharing_service_factory.h" +#include "chrome/browser/ui/tabs/saved_tab_groups/saved_tab_group_utils.h" +#include "chrome/common/webui_url_constants.h" +#include "components/data_sharing/public/data_sharing_service.h" +#include "components/data_sharing/public/group_data.h" +#include "components/saved_tab_groups/saved_tab_group_tab.h" +#include "components/saved_tab_groups/tab_group_sync_service.h" +#include "components/tab_groups/tab_group_id.h" +#include "net/base/url_util.h" + +std::optional<GURL> data_sharing::GenerateWebUIUrl( + std::variant<tab_groups::LocalTabGroupID, data_sharing::GroupToken> + request_info, + Profile* profile) { + GURL url = GURL(chrome::kChromeUIUntrustedDataSharingURL); + if (std::holds_alternative<tab_groups::LocalTabGroupID>(request_info)) { + tab_groups::TabGroupId local_group_id = std::get<0>(request_info); + if (local_group_id.is_empty()) { + return std::nullopt; + } + tab_groups::TabGroupSyncService* const tab_group_service = + tab_groups::SavedTabGroupUtils::GetServiceForProfile(profile); + if (!tab_group_service) { + return std::nullopt; + } + std::optional<tab_groups::SavedTabGroup> saved_group = + tab_group_service->GetGroup(local_group_id); + if (!saved_group) { + return std::nullopt; + } + if (saved_group->is_shared_tab_group()) { + // Return manage flow url which requires a group_id for webui to fetch + // people info. + url = net::AppendQueryParameter(url, kQueryParamFlow, kFlowManage); + url = net::AppendQueryParameter(url, kQueryParamGroupId, + saved_group->collaboration_id().value()); + } else { + // Return share flow url which requires a local group id to later + // associate with the collaboration_id returned by WebUI. + url = net::AppendQueryParameter(url, kQueryParamFlow, kFlowShare); + url = net::AppendQueryParameter(url, kQueryParamTabGroupId, + local_group_id.ToString()); + } + } else { + // Return join flow url which requires both collaboration_id and + // access_token for WebUI to fetch people info. + GroupToken group_token = std::get<1>(request_info); + CHECK(group_token.IsValid()); + url = net::AppendQueryParameter(url, kQueryParamFlow, kFlowJoin); + url = net::AppendQueryParameter(url, kQueryParamGroupId, + group_token.group_id.value()); + url = net::AppendQueryParameter(url, kQueryParamTokenSecret, + group_token.access_token); + } + return std::make_optional(url); +} + +void data_sharing::AssociateTabGroupWithGroupId(const std::string& tab_group_id, + const std::string& group_id, + Profile* profile) { + tab_groups::TabGroupSyncService* service = + tab_groups::SavedTabGroupUtils::GetServiceForProfile(profile); + // `tab_group_id` is served by webui and should never be null when it gets + // here. + std::optional<base::Token> token = base::Token::FromString(tab_group_id); + CHECK(token); + tab_groups::TabGroupId local_tab_group_id( + tab_groups::TabGroupId::FromRawToken(token.value())); + std::optional<tab_groups::SavedTabGroup> group = + service->GetGroup(local_tab_group_id); + if (group && !group->is_shared_tab_group()) { + service->MakeTabGroupShared(local_tab_group_id, group_id); + } +} + +GURL data_sharing::GetShareLink(const std::string& group_id, + const std::string& access_token, + Profile* profile) { + data_sharing::GroupData group_data; + group_data.group_token = + data_sharing::GroupToken(data_sharing::GroupId(group_id), access_token); + auto* data_sharing_service = + data_sharing::DataSharingServiceFactory::GetForProfile(profile); + // `group_id` and `access_token` are served by webui and should never be null + // when they get here. So the sharing url must be valid. + std::unique_ptr<GURL> url_ptr = + data_sharing_service->GetDataSharingURL(group_data); + CHECK(url_ptr); + return *url_ptr; +}
diff --git a/chrome/browser/ui/views/data_sharing/data_sharing_utils.h b/chrome/browser/ui/views/data_sharing/data_sharing_utils.h new file mode 100644 index 0000000..fca566a9 --- /dev/null +++ b/chrome/browser/ui/views/data_sharing/data_sharing_utils.h
@@ -0,0 +1,45 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_UI_VIEWS_DATA_SHARING_DATA_SHARING_UTILS_H_ +#define CHROME_BROWSER_UI_VIEWS_DATA_SHARING_DATA_SHARING_UTILS_H_ + +#include "base/uuid.h" +#include "chrome/browser/profiles/profile.h" +#include "components/data_sharing/public/group_data.h" +#include "components/saved_tab_groups/types.h" + +namespace data_sharing { + +// The query params of the urls to internally load webui. +inline std::string_view kQueryParamFlow = "flow"; +inline std::string_view kQueryParamGroupId = "group_id"; +inline std::string_view kQueryParamTokenSecret = "token_secret"; +inline std::string_view kQueryParamTabGroupId = "tab_group_id"; + +// Possible values of kQueryParamFlow in url. +inline std::string_view kFlowShare = "share"; +inline std::string_view kFlowJoin = "join"; +inline std::string_view kFlowManage = "manage"; + +// `request_info` contains the info we want to pass into the loaded WebUI. +std::optional<GURL> GenerateWebUIUrl( + std::variant<tab_groups::LocalTabGroupID, data_sharing::GroupToken> + request_info, + Profile* profile); + +// Associate tab group with `group_id` returned by the Share flow WebUI, i.e. +// make the tab group shared. +void AssociateTabGroupWithGroupId(const std::string& tab_group_id, + const std::string& group_id, + Profile* profile); + +// Get share link from data sharing service. +GURL GetShareLink(const std::string& group_id, + const std::string& access_token, + Profile* profile); + +} // namespace data_sharing + +#endif // CHROME_BROWSER_UI_VIEWS_DATA_SHARING_DATA_SHARING_UTILS_H_
diff --git a/chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.cc b/chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.cc index d6f8abf7..75035829 100644 --- a/chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.cc +++ b/chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.cc
@@ -7,47 +7,32 @@ #include <memory> #include "base/functional/callback_forward.h" -#include "chrome/browser/digital_credentials/digital_identity_bluetooth_adapter_status_change_observer.h" -#include "chrome/browser/digital_credentials/digital_identity_fido_handler_observer.h" #include "chrome/browser/ui/views/digital_credentials/digital_identity_multi_step_dialog.h" +#include "chrome/browser/ui/views/digital_credentials/digital_identity_safety_interstitial_controller_desktop.h" #include "chrome/grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/models/dialog_model.h" -using BleStatus = device::FidoRequestHandlerBase::BleStatus; - DigitalIdentityBluetoothManualDialogController:: DigitalIdentityBluetoothManualDialogController( - DigitalIdentityMultiStepDialog* dialog, - DigitalIdentityFidoHandlerObserver* observer_registrar) - : dialog_(dialog), observer_registrar_(observer_registrar) { - observer_registrar_->AddBluetoothAdapterStatusChangeObserver(this); -} + DigitalIdentityMultiStepDialog* dialog) + : dialog_(dialog) {} DigitalIdentityBluetoothManualDialogController:: - ~DigitalIdentityBluetoothManualDialogController() { - observer_registrar_->RemoveBluetoothAdapterStatusChangeObserver(this); -} + ~DigitalIdentityBluetoothManualDialogController() = default; void DigitalIdentityBluetoothManualDialogController::Show( - base::RepeatingClosure accept_bluetooth_powered_on_callback, - base::RepeatingClosure cancel_callback) { - accept_bluetooth_powered_on_callback_ = - std::move(accept_bluetooth_powered_on_callback); + base::OnceClosure user_requested_bluetooth_power_on_callback, + base::OnceClosure cancel_callback) { + user_requested_blueooth_power_on_callback_ = + std::move(user_requested_bluetooth_power_on_callback); cancel_callback_ = std::move(cancel_callback); - UpdateDialog(); + + UpdateDialog(/*enabled=*/true); } -void DigitalIdentityBluetoothManualDialogController:: - OnBluetoothAdapterStatusChanged(BleStatus ble_status) { - is_ble_powered_ = (ble_status == BleStatus::kOn); - UpdateDialog(); -} - -void DigitalIdentityBluetoothManualDialogController::UpdateDialog() { - CHECK(accept_bluetooth_powered_on_callback_); - CHECK(cancel_callback_); - +void DigitalIdentityBluetoothManualDialogController::UpdateDialog( + bool is_ok_button_enabled) { std::u16string dialog_title = l10n_util::GetStringUTF16( IDS_WEB_DIGITAL_CREDENTIALS_BLUETOOTH_POWER_ON_MANUAL_TITLE); std::u16string dialog_body = l10n_util::GetStringUTF16( @@ -57,10 +42,31 @@ std::optional<ui::DialogModel::Button::Params> ok_button_params = std::make_optional<ui::DialogModel::Button::Params>(); ok_button_params->SetLabel(ok_button_text); - ok_button_params->SetEnabled(is_ble_powered_); + ok_button_params->SetEnabled(is_ok_button_enabled); - dialog_->TryShow(ok_button_params, accept_bluetooth_powered_on_callback_, - ui::DialogModel::Button::Params(), cancel_callback_, - dialog_title, dialog_body, - /*custom_body_field=*/nullptr); + dialog_->TryShow( + ok_button_params, + base::BindOnce(&DigitalIdentityBluetoothManualDialogController::OnAccept, + weak_factory_.GetWeakPtr()), + ui::DialogModel::Button::Params(), + base::BindOnce(&DigitalIdentityBluetoothManualDialogController::OnCancel, + weak_factory_.GetWeakPtr()), + dialog_title, dialog_body, + /*custom_body_field=*/nullptr); +} + +void DigitalIdentityBluetoothManualDialogController::OnAccept() { + CHECK(user_requested_blueooth_power_on_callback_); + + // Disable the dialog so that the user can't click the button twice. + UpdateDialog(/*enabled=*/false); + + std::move(user_requested_blueooth_power_on_callback_).Run(); +} + +void DigitalIdentityBluetoothManualDialogController::OnCancel() { + // The owner of this object should ensure that the user can't click other + // buttons after the cancel callback, e.g. by destroying the dialog. + CHECK(cancel_callback_); + std::move(cancel_callback_).Run(); }
diff --git a/chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.h b/chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.h index c0c9b78..750f561 100644 --- a/chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.h +++ b/chrome/browser/ui/views/digital_credentials/digital_identity_bluetooth_manual_dialog_controller.h
@@ -5,45 +5,35 @@ #ifndef CHROME_BROWSER_UI_VIEWS_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_BLUETOOTH_MANUAL_DIALOG_CONTROLLER_H_ #define CHROME_BROWSER_UI_VIEWS_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_BLUETOOTH_MANUAL_DIALOG_CONTROLLER_H_ -#include "base/functional/callback_forward.h" +#include "base/functional/callback.h" #include "base/memory/raw_ptr.h" -#include "chrome/browser/digital_credentials/digital_identity_bluetooth_adapter_status_change_observer.h" -#include "device/fido/digital_identity_request_handler.h" -#include "device/fido/fido_request_handler_base.h" +#include "base/memory/weak_ptr.h" class DigitalIdentityMultiStepDialog; -class DigitalIdentityFidoHandlerObserver; // Displays step asking user to manually turn on bluetooth. -class DigitalIdentityBluetoothManualDialogController - : public DigitalIdentityBluetoothAdapterStatusChangeObserver { +class DigitalIdentityBluetoothManualDialogController { public: - DigitalIdentityBluetoothManualDialogController( - DigitalIdentityMultiStepDialog* dialog, - DigitalIdentityFidoHandlerObserver* observer_registrar); - ~DigitalIdentityBluetoothManualDialogController() override; + explicit DigitalIdentityBluetoothManualDialogController( + DigitalIdentityMultiStepDialog* dialog); + ~DigitalIdentityBluetoothManualDialogController(); - void Show(base::RepeatingClosure accept_bluetooth_powered_on_callback, - base::RepeatingClosure cancel_callback); - - // DigitalIdentityBluetoothAdapterPowerChangedObserver: - void OnBluetoothAdapterStatusChanged( - device::FidoRequestHandlerBase::BleStatus ble_status) override; + void Show(base::OnceClosure user_requested_bluetooth_power_on_callback, + base::OnceClosure cancel_callback); private: - void UpdateDialog(); - - // Whether bluetooth is powered. - bool is_ble_powered_ = false; - - base::RepeatingClosure accept_bluetooth_powered_on_callback_; - base::RepeatingClosure cancel_callback_; + void UpdateDialog(bool enabled); + void OnAccept(); + void OnCancel(); // Owned by DigitalIdentityProviderDesktop. - raw_ptr<DigitalIdentityMultiStepDialog> dialog_; + const raw_ptr<DigitalIdentityMultiStepDialog> dialog_; - // Owned by DigitalIdentityProviderDesktop. - raw_ptr<DigitalIdentityFidoHandlerObserver> observer_registrar_; + base::OnceClosure user_requested_blueooth_power_on_callback_; + base::OnceClosure cancel_callback_; + + base::WeakPtrFactory<DigitalIdentityBluetoothManualDialogController> + weak_factory_{this}; }; #endif // CHROME_BROWSER_UI_VIEWS_DIGITAL_CREDENTIALS_DIGITAL_IDENTITY_BLUETOOTH_MANUAL_DIALOG_CONTROLLER_H_
diff --git a/chrome/browser/ui/views/digital_credentials/digital_identity_safety_interstitial_integration_test.cc b/chrome/browser/ui/views/digital_credentials/digital_identity_safety_interstitial_integration_test.cc index 7cee971..25a5f88 100644 --- a/chrome/browser/ui/views/digital_credentials/digital_identity_safety_interstitial_integration_test.cc +++ b/chrome/browser/ui/views/digital_credentials/digital_identity_safety_interstitial_integration_test.cc
@@ -54,7 +54,7 @@ void Request(content::WebContents* web_contents, const url::Origin& origin, - const std::string& request, + base::Value request, DigitalIdentityCallback callback) override { did_request_credential_ = true;
diff --git a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc index 497f9439..bd2bc447 100644 --- a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc +++ b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.cc
@@ -818,18 +818,25 @@ return GetColorProvider()->GetColor(id); } -int WebUITabStripContainerView::GetHeightForWidth(int w) const { +gfx::Size WebUITabStripContainerView::CalculatePreferredSize( + const views::SizeBounds& available_size) const { DCHECK(!(animation_.is_animating() && current_drag_height_)); + gfx::Size preferred_size = + GetLayoutManager()->GetPreferredSize(this, available_size); // Note that preferred size is automatically calculated by the layout. if (animation_.is_animating()) { - return gfx::Tween::LinearIntValueBetween(animation_.GetCurrentValue(), 0, - GetPreferredSize().height()); + preferred_size.set_height(gfx::Tween::LinearIntValueBetween( + animation_.GetCurrentValue(), 0, preferred_size.height())); + return preferred_size; } - if (current_drag_height_) - return std::round(*current_drag_height_); - return GetVisible() ? GetPreferredSize().height() : 0; + if (current_drag_height_) { + preferred_size.set_height(std::round(*current_drag_height_)); + return preferred_size; + } + + return GetVisible() ? preferred_size : gfx::Size(); } gfx::Size WebUITabStripContainerView::FlexRule(
diff --git a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h index a893d80..c1303ec 100644 --- a/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h +++ b/chrome/browser/ui/views/frame/webui_tab_strip_container_view.h
@@ -136,7 +136,8 @@ SkColor GetColorProviderColor(ui::ColorId id) const override; // views::View: - int GetHeightForWidth(int w) const override; + gfx::Size CalculatePreferredSize( + const views::SizeBounds& available_size) const override; gfx::Size FlexRule(const views::View* view, const views::SizeBounds& bounds) const;
diff --git a/chrome/browser/ui/views/permissions/permission_rhs_indicators_interactive_uitest.cc b/chrome/browser/ui/views/permissions/permission_rhs_indicators_interactive_uitest.cc index 89628e0..e44a689 100644 --- a/chrome/browser/ui/views/permissions/permission_rhs_indicators_interactive_uitest.cc +++ b/chrome/browser/ui/views/permissions/permission_rhs_indicators_interactive_uitest.cc
@@ -172,8 +172,6 @@ ExecuteJs(kWebContentsElementId, "requestNotification"), WaitForShow(PermissionPromptBubbleBaseView::kMainViewId), WaitForShow(PermissionPromptBubbleBaseView::kAllowButtonElementId), - // We need to call `FlushEvents` here before `PressButton` because a - // `view_` variable in PermissionRequestManager is not yet initialized. // Permission prompt bubble is shown, click on the Allow button. PressButton(PermissionPromptBubbleBaseView::kAllowButtonElementId), @@ -198,8 +196,6 @@ ExecuteJs(kWebContentsElementId, "requestCamera"), WaitForShow(PermissionPromptBubbleBaseView::kMainViewId), WaitForShow(PermissionPromptBubbleBaseView::kAllowButtonElementId), - // We need to call `FlushEvents` here before `PressButton` because a - // `view_` variable in PermissionRequestManager is not yet initialized. // Permission prompt bubble is shown, click on the Allow button. PressButton(PermissionPromptBubbleBaseView::kAllowButtonElementId), @@ -224,8 +220,6 @@ ExecuteJs(kWebContentsElementId, "requestCamera"), WaitForShow(PermissionPromptBubbleBaseView::kMainViewId), WaitForShow(PermissionPromptBubbleBaseView::kAllowButtonElementId), - // We need to call `FlushEvents` here before `PressButton` because a - // `view_` variable in PermissionRequestManager is not yet initialized. // Permission prompt bubble is shown, click on the Allow button. PressButton(PermissionPromptBubbleBaseView::kAllowButtonElementId), @@ -246,8 +240,6 @@ ExecuteJs(kWebContentsElementId, "requestMicrophone"), WaitForShow(PermissionPromptBubbleBaseView::kMainViewId), WaitForShow(PermissionPromptBubbleBaseView::kAllowButtonElementId), - // We need to call `FlushEvents` here before `PressButton` because a - // `view_` variable in PermissionRequestManager is not yet initialized. // Permission prompt bubble is shown, click on the Allow button. PressButton(PermissionPromptBubbleBaseView::kAllowButtonElementId), @@ -268,8 +260,6 @@ ExecuteJs(kWebContentsElementId, "requestCameraAndMicrophone"), WaitForShow(PermissionPromptBubbleBaseView::kMainViewId), WaitForShow(PermissionPromptBubbleBaseView::kAllowButtonElementId), - // We need to call `FlushEvents` here before `PressButton` because a - // `view_` variable in PermissionRequestManager is not yet initialized. // Permission prompt bubble is shown, click on the Allow button. PressButton(PermissionPromptBubbleBaseView::kAllowButtonElementId),
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 1b458f29..212b3047 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -333,6 +333,14 @@ return; } +#if BUILDFLAG(IS_CHROMEOS_ASH) + // Tabs cannot be closed when the app is locked for OnTask. Only relevant for + // non-web browser scenarios. + if (browser_view_->browser()->IsLockedForOnTask()) { + return; + } +#endif + // Only consider pausing the close operation if this is the last remaining // tab (since otherwise closing it won't close the browser window). if (GetCount() <= 1) {
diff --git a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc index a3d354a..54a2f5b 100644 --- a/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc +++ b/chrome/browser/ui/views/tabs/tab_group_editor_bubble_view.cc
@@ -501,22 +501,28 @@ std::unique_ptr<views::LabelButton> TabGroupEditorBubbleView::BuildManageSharedGroupButton() { - return CreateMenuItem( + auto menu_item = CreateMenuItem( TAB_GROUP_HEADER_CXMENU_MANAGE_SHARING, l10n_util::GetStringUTF16(IDS_TAB_GROUP_HEADER_CXMENU_MANAGE_GROUP), base::BindRepeating(&TabGroupEditorBubbleView::ShareOrManagePressed, base::Unretained(this)), ui::ImageModel::FromVectorIcon(kTabGroupSharingIcon)); + menu_item->SetProperty(views::kElementIdentifierKey, + kTabGroupEditorBubbleManageSharedGroupButtonId); + return menu_item; } std::unique_ptr<views::LabelButton> TabGroupEditorBubbleView::BuildShareGroupButton() { - return CreateMenuItem( + auto menu_item = CreateMenuItem( TAB_GROUP_HEADER_CXMENU_SHARE, l10n_util::GetStringUTF16(IDS_TAB_GROUP_HEADER_CXMENU_SHARE_GROUP), base::BindRepeating(&TabGroupEditorBubbleView::ShareOrManagePressed, base::Unretained(this)), ui::ImageModel::FromVectorIcon(kTabGroupSharingIcon)); + menu_item->SetProperty(views::kElementIdentifierKey, + kTabGroupEditorBubbleShareGroupButtonId); + return menu_item; } TabGroupEditorBubbleView::~TabGroupEditorBubbleView() = default; @@ -652,19 +658,17 @@ void TabGroupEditorBubbleView::OnSaveTogglePressed() { // TODO(crbug.com/356886508): When V2 launches remove this function as it will // no longer be used. - tab_groups::SavedTabGroupKeyedService* const saved_tab_group_service = - tab_groups::SavedTabGroupServiceFactory::GetForProfile( - browser_->profile()); - CHECK(saved_tab_group_service); + tab_groups::TabGroupSyncService* tab_group_service = + tab_groups::SavedTabGroupUtils::GetServiceForProfile(browser_->profile()); + CHECK(tab_group_service); if (save_group_toggle_->GetIsOn()) { base::RecordAction( base::UserMetricsAction("TabGroups_TabGroupBubble_GroupSaved")); - saved_tab_group_service->SaveGroup( - group_, - /*is_pinned=*/tab_groups::SavedTabGroupUtils::ShouldAutoPinNewTabGroups( - browser_->profile())); + tab_groups::SavedTabGroup group = + tab_groups::SavedTabGroupUtils::CreateSavedTabGroupFromLocalId(group_); + tab_group_service->AddGroup(std::move(group)); views::ElementTrackerViews::GetInstance()->NotifyCustomEvent( kTabGroupSavedCustomEventId, save_group_toggle_); @@ -679,8 +683,7 @@ } else { base::RecordAction( base::UserMetricsAction("TabGroups_TabGroupBubble_GroupUnsaved")); - saved_tab_group_service->UnsaveGroup( - group_, tab_groups::ClosingSource::kDeletedByUser); + tab_group_service->RemoveGroup(group_); } save_group_toggle_->GetViewAccessibility().SetName( @@ -722,11 +725,9 @@ } void TabGroupEditorBubbleView::ShareOrManagePressed() { - // TODO(b/353577560): Placeholder impl for ease of testing. Add real impl - // later. DataSharingBubbleController::GetOrCreateForBrowser( const_cast<Browser*>(browser_.get())) - ->Show(); + ->Show(group_); } // static
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index ad1fac7..3cbe9d4 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -4791,7 +4791,7 @@ enabled_features.push_back(apps::features::kLinkCapturingUiUpdate); #else // TODO(b/313492499): Update test driver to work with new intent picker UI. - enabled_features.push_back(features::kDesktopPWAsLinkCapturing); + enabled_features.push_back(features::kPwaNavigationCapturing); #endif // BUILDFLAG(IS_CHROMEOS) scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features); }
diff --git a/chrome/browser/ui/views/web_apps/web_app_link_capturing_test_utils.h b/chrome/browser/ui/views/web_apps/web_app_link_capturing_test_utils.h index aad3ebf4..99f11ce 100644 --- a/chrome/browser/ui/views/web_apps/web_app_link_capturing_test_utils.h +++ b/chrome/browser/ui/views/web_apps/web_app_link_capturing_test_utils.h
@@ -25,7 +25,7 @@ namespace web_app { // These test functions work only with the new intent picker UX and requires the -// following flags to be enabled: features::kDesktopPWAsLinkCapturing on +// following flags to be enabled: features::kPwaNavigationCapturing on // Windows, Mac and Linux. apps::features::kLinkCapturingUiUpdate on CrOS. // Without these flags set on their respective platforms, the tests will CHECK // fail.
diff --git a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc index 9a54a8f..d9ca04b 100644 --- a/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/web_app_tab_strip_browsertest.cc
@@ -1322,4 +1322,83 @@ u"Favicon only")); } +#if BUILDFLAG(IS_CHROMEOS_ASH) + +// Browser tests that verify web-app tab strip behavior when locked (and not +// locked) for OnTask. Only relevant for non-web browser scenarios. +using WebAppTabStripForOnTaskBrowserTest = WebAppTabStripBrowserTest; + +IN_PROC_BROWSER_TEST_F(WebAppTabStripForOnTaskBrowserTest, + MiddleClickDoesNotCloseTabsWhenLockedForOnTask) { + // Set up app and lock the app for OnTask. + GURL start_url = + embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html"); + const webapps::AppId app_id = InstallTestWebApp(start_url); + Browser* const app_browser = FindWebAppBrowser(browser()->profile(), app_id); + app_browser->SetLockedForOnTask(true); + + const TabStripModel* const tab_strip_model = app_browser->tab_strip_model(); + ASSERT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id)); + ASSERT_EQ(tab_strip_model->count(), 1); + ASSERT_TRUE(tab_strip_model->IsTabPinned(0)); + + // Open another tab so we can test tab close behavior on both home and + // non-home tabs. + OpenUrlAndWait(app_browser, + embedded_test_server()->GetURL("/web_apps/get_manifest.html")); + ASSERT_EQ(tab_strip_model->count(), 2); + + // Verify home tab cannot be closed. + auto* const tab_strip = + BrowserView::GetBrowserViewForBrowser(app_browser)->tabstrip(); + tab_strip->CloseTab(tab_strip->tab_at(0), + CloseTabSource::CLOSE_TAB_FROM_MOUSE); + ASSERT_EQ(tab_strip_model->count(), 2); + + // Also verify the non-home tab cannot be closed. + tab_strip->CloseTab(tab_strip->tab_at(1), + CloseTabSource::CLOSE_TAB_FROM_MOUSE); + EXPECT_EQ(tab_strip_model->count(), 2); +} + +IN_PROC_BROWSER_TEST_F(WebAppTabStripForOnTaskBrowserTest, + MiddleClickCanCloseTabsWhenNotLockedForOnTask) { + // Set up app and do not lock the app for OnTask. + GURL start_url = + embedded_test_server()->GetURL("/web_apps/tab_strip_customizations.html"); + const webapps::AppId app_id = InstallTestWebApp(start_url); + Browser* const app_browser = FindWebAppBrowser(browser()->profile(), app_id); + app_browser->SetLockedForOnTask(false); + + const TabStripModel* const tab_strip_model = app_browser->tab_strip_model(); + ASSERT_TRUE(registrar().IsTabbedWindowModeEnabled(app_id)); + ASSERT_EQ(tab_strip_model->count(), 1); + ASSERT_TRUE(tab_strip_model->IsTabPinned(0)); + + // Open another tab so we can test tab close behavior on both home and + // non-home tabs. + OpenUrlAndWait(app_browser, + embedded_test_server()->GetURL("/web_apps/get_manifest.html")); + ASSERT_EQ(tab_strip_model->count(), 2); + + // Verify home tab cannot be closed (default behavior on tabbed web apps). + auto* const tab_strip = + BrowserView::GetBrowserViewForBrowser(app_browser)->tabstrip(); + tab_strip->CloseTab(tab_strip->tab_at(0), + CloseTabSource::CLOSE_TAB_FROM_MOUSE); + ASSERT_EQ(tab_strip_model->count(), 2); + + // Verify the non-home tab can be closed. + tab_strip->CloseTab(tab_strip->tab_at(1), + CloseTabSource::CLOSE_TAB_FROM_MOUSE); + ASSERT_EQ(tab_strip_model->count(), 1); + + // The home tab is the only tab open so it can be closed now. + tab_strip->CloseTab(tab_strip->tab_at(0), + CloseTabSource::CLOSE_TAB_FROM_MOUSE); + EXPECT_EQ(tab_strip_model->count(), 0); +} + +#endif + } // namespace web_app
diff --git a/chrome/browser/ui/web_applications/web_app_launch_utils.cc b/chrome/browser/ui/web_applications/web_app_launch_utils.cc index e97554c..c13d07c 100644 --- a/chrome/browser/ui/web_applications/web_app_launch_utils.cc +++ b/chrome/browser/ui/web_applications/web_app_launch_utils.cc
@@ -930,7 +930,7 @@ // Below here handles the states outlined in // https://bit.ly/pwa-navigation-capturing - if (!apps::features::IsLinkCapturingReimplementationEnabled() || + if (!apps::features::IsNavigationCapturingReimplEnabled() || params.started_from_context_menu) { return std::nullopt; }
diff --git a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc index 6208fa48..fcd70e2c 100644 --- a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc +++ b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
@@ -587,7 +587,7 @@ return; } - if (WebAppPrefGuardrails::GetForLinkCapturingIph( + if (WebAppPrefGuardrails::GetForNavigationCapturingIph( app_browser->profile()->GetPrefs()) .IsBlockedByGuardrails(app_id)) { return; @@ -843,7 +843,7 @@ case user_education::FeaturePromoClosedReason::kAction: base::RecordAction( base::UserMetricsAction("LinkCapturingIPHAppBubbleAccepted")); - WebAppPrefGuardrails::GetForLinkCapturingIph( + WebAppPrefGuardrails::GetForNavigationCapturingIph( browser->profile()->GetPrefs()) .RecordAccept(app_id); break; @@ -851,7 +851,7 @@ case user_education::FeaturePromoClosedReason::kCancel: base::RecordAction( base::UserMetricsAction("LinkCapturingIPHAppBubbleNotAccepted")); - WebAppPrefGuardrails::GetForLinkCapturingIph( + WebAppPrefGuardrails::GetForNavigationCapturingIph( browser->profile()->GetPrefs()) .RecordDismiss(app_id, base::Time::Now()); break;
diff --git a/chrome/browser/ui/webui/data_sharing/data_sharing.mojom b/chrome/browser/ui/webui/data_sharing/data_sharing.mojom index 665a7933..76df035 100644 --- a/chrome/browser/ui/webui/data_sharing/data_sharing.mojom +++ b/chrome/browser/ui/webui/data_sharing/data_sharing.mojom
@@ -4,6 +4,7 @@ module data_sharing.mojom; +import "url/mojom/url.mojom"; import "components/data_sharing/public/protocol/group_data.mojom"; // Factory ensures that the Page and PageHandler interfaces are always created @@ -25,6 +26,15 @@ // All other APIs on the Page such as ReadGroups should only be invoked // after ApiInitComplete. ApiInitComplete(); + + // `group_id` connects the shared tab group with people group. `access_token` + // is used to check link validity. Chrome stitches them together with a host + // and generates an invite link. Owner can share the link to the public. + GetShareLink(string group_id, string access_token) => (url.mojom.Url url); + + // `tab_group_id` is the local id of the group in tab strip that gets shared. + // `group_id` is the id that connects the people with the shared tab group. + AssociateTabGroupWithGroupId(string tab_group_id, string group_id); }; // WebUI-side handler for requests from the browser.
diff --git a/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.cc b/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.cc index 05e6fb49..12c9076 100644 --- a/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.cc +++ b/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.cc
@@ -8,6 +8,7 @@ #include "build/branding_buildflags.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/signin/identity_manager_factory.h" +#include "chrome/browser/ui/views/data_sharing/data_sharing_utils.h" #include "chrome/browser/ui/webui/data_sharing/data_sharing_ui.h" #include "components/signin/public/identity_manager/access_token_info.h" #include "components/signin/public/identity_manager/identity_manager.h" @@ -60,6 +61,20 @@ webui_controller_->ApiInitComplete(); } +void DataSharingPageHandler::GetShareLink(const std::string& group_id, + const std::string& access_token, + GetShareLinkCallback callback) { + std::move(callback).Run( + data_sharing::GetShareLink(group_id, access_token, GetProfile())); +} + +void DataSharingPageHandler::AssociateTabGroupWithGroupId( + const std::string& tab_group_id, + const std::string& group_id) { + data_sharing::AssociateTabGroupWithGroupId(tab_group_id, group_id, + GetProfile()); +} + Profile* DataSharingPageHandler::GetProfile() { CHECK(webui_controller_); return Profile::FromWebUI(webui_controller_->web_ui());
diff --git a/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.h b/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.h index 07d4d49..c882206 100644 --- a/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.h +++ b/chrome/browser/ui/webui/data_sharing/data_sharing_page_handler.h
@@ -37,6 +37,13 @@ void ApiInitComplete() override; + void GetShareLink(const std::string& group_id, + const std::string& access_token, + GetShareLinkCallback callback) override; + + void AssociateTabGroupWithGroupId(const std::string& tab_group_id, + const std::string& group_id) override; + void ReadGroups(std::vector<std::string> group_ids, data_sharing::mojom::Page::ReadGroupsCallback callback);
diff --git a/chrome/browser/ui/webui/downloads/downloads_page_interactive_uitest.cc b/chrome/browser/ui/webui/downloads/downloads_page_interactive_uitest.cc index 8f1424c..5297898 100644 --- a/chrome/browser/ui/webui/downloads/downloads_page_interactive_uitest.cc +++ b/chrome/browser/ui/webui/downloads/downloads_page_interactive_uitest.cc
@@ -133,7 +133,7 @@ const DeepQuery kPathToClearAllButton{ "downloads-manager", "downloads-toolbar", - "#clear-all", + "#clearAll", }; return ExecuteJsAt(kDownloadsPageTabId, kPathToClearAllButton, kClickFn); } @@ -316,7 +316,7 @@ DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kReadyEvent); const DeepQuery kPathToDialog{ "downloads-manager", - "download-bypass-warning-confirmation-dialog", + "downloads-bypass-warning-confirmation-dialog", }; StateChange dialog_visible; dialog_visible.type = StateChange::Type::kExists; @@ -329,7 +329,7 @@ DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kReadyEvent); const DeepQuery path_to_button{ "downloads-manager", - "download-bypass-warning-confirmation-dialog", + "downloads-bypass-warning-confirmation-dialog", button_selector, }; StateChange button_visible;
diff --git a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc index 4ef152ae..26af57ed 100644 --- a/chrome/browser/ui/webui/interstitials/interstitial_ui.cc +++ b/chrome/browser/ui/webui/interstitials/interstitial_ui.cc
@@ -385,7 +385,7 @@ return std::make_unique<SupervisedUserVerificationPage>( web_contents, "first.last@gmail.com", kRequestUrl, SupervisedUserVerificationPage::VerificationPurpose::REAUTH_REQUIRED_SITE, - /*child_account_service*/ nullptr, + /*child_account_service*/ nullptr, ukm::kInvalidSourceId, std::make_unique<SupervisedUserVerificationControllerClient>( web_contents, Profile::FromBrowserContext(web_contents->GetBrowserContext()) @@ -401,7 +401,7 @@ return std::make_unique<SupervisedUserVerificationPage>( web_contents, "first.last@gmail.com", kRequestUrl, SupervisedUserVerificationPage::VerificationPurpose::BLOCKED_SITE, - /*child_account_service*/ nullptr, + /*child_account_service*/ nullptr, ukm::kInvalidSourceId, std::make_unique<SupervisedUserVerificationControllerClient>( web_contents, Profile::FromBrowserContext(web_contents->GetBrowserContext())
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc index 068c789..da47bd7 100644 --- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc +++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_ui.cc
@@ -303,6 +303,7 @@ // Modules. {"dismissModuleToastMessage", IDS_NTP_MODULES_DISMISS_TOAST_MESSAGE}, {"disableModuleToastMessage", IDS_NTP_MODULES_DISABLE_TOAST_MESSAGE}, + {"moduleHeaderMoreActionsMenu", IDS_NTP_MODULE_HEADER_MORE_ACTIONS_MENU}, {"moduleInfoButtonTitle", IDS_NTP_MODULES_INFO_BUTTON_TITLE}, {"modulesDismissButtonText", IDS_NTP_MODULES_DISMISS_BUTTON_TEXT}, {"modulesDisableButtonText", IDS_NTP_MODULES_DISABLE_BUTTON_TEXT},
diff --git a/chrome/browser/web_applications/web_app_link_capturing_parameterized_browsertest.cc b/chrome/browser/web_applications/web_app_link_capturing_parameterized_browsertest.cc index 524992c..35026d2 100644 --- a/chrome/browser/web_applications/web_app_link_capturing_parameterized_browsertest.cc +++ b/chrome/browser/web_applications/web_app_link_capturing_parameterized_browsertest.cc
@@ -40,13 +40,13 @@ #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/browser/web_applications/web_app_registry_update.h" -#include "chrome/common/chrome_features.h" #include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/ui_test_utils.h" #include "components/services/app_service/public/cpp/app_launch_util.h" #include "components/webapps/common/web_app_id.h" #include "content/public/browser/navigation_entry.h" #include "content/public/browser/navigation_handle.h" +#include "content/public/common/content_features.h" #include "content/public/test/browser_test.h" #include "content/public/test/browser_test_utils.h" #include "content/public/test/test_navigation_observer.h" @@ -478,7 +478,7 @@ } // namespace -// This test verifies the link capture logic by testing by launching sites +// This test verifies the navigation capture logic by testing by launching sites // inside app containers and tabs and test what happens when links are // left/middle clicked and window.open is used (whether browser objects are // reused and what type gets launched). @@ -512,7 +512,7 @@ std::map<std::string, std::string> parameters; parameters["link_capturing_state"] = "reimpl_default_on"; scoped_feature_list_.InitAndEnableFeatureWithParameters( - features::kDesktopPWAsLinkCapturing, parameters); + features::kPwaNavigationCapturing, parameters); InitializeTestExpectations(); }
diff --git a/chrome/browser/web_applications/web_app_pref_guardrails.cc b/chrome/browser/web_applications/web_app_pref_guardrails.cc index 10878f5..130b0d1 100644 --- a/chrome/browser/web_applications/web_app_pref_guardrails.cc +++ b/chrome/browser/web_applications/web_app_pref_guardrails.cc
@@ -21,6 +21,7 @@ #include "components/webapps/browser/features.h" #include "components/webapps/common/web_app_id.h" #include "content/public/browser/browser_thread.h" +#include "content/public/common/content_features.h" namespace web_app { @@ -91,12 +92,12 @@ } // static -WebAppPrefGuardrails WebAppPrefGuardrails::GetForLinkCapturingIph( +WebAppPrefGuardrails WebAppPrefGuardrails::GetForNavigationCapturingIph( PrefService* pref_service) { return WebAppPrefGuardrails( - pref_service, web_app::kIPHLinkCapturingGuardrails, - web_app::kIPHLinkCapturingPrefNames, - features::kLinkCapturingIPHGuardrailStorageDuration.Get()); + pref_service, web_app::kIPHNavigationCapturingGuardrails, + web_app::kIPHNavigationCapturingPrefNames, + features::kNavigationCapturingIPHGuardrailStorageDuration.Get()); } // static
diff --git a/chrome/browser/web_applications/web_app_pref_guardrails.h b/chrome/browser/web_applications/web_app_pref_guardrails.h index fc1aaa6..0ae5864 100644 --- a/chrome/browser/web_applications/web_app_pref_guardrails.h +++ b/chrome/browser/web_applications/web_app_pref_guardrails.h
@@ -69,7 +69,8 @@ // Returns an instance of the WebAppPrefGuardrails built to handle when the // IPH bubble for apps launched via link capturing should be shown. - static WebAppPrefGuardrails GetForLinkCapturingIph(PrefService* pref_service); + static WebAppPrefGuardrails GetForNavigationCapturingIph( + PrefService* pref_service); // The time values are stored as a string-flavored base::value representing // the int64_t number of microseconds since the Windows epoch, using @@ -255,8 +256,8 @@ .block_reason_name = "ML_guardrail_blocked", }; -// -----------------------IPH Link Capturing guardrails------------------- -// Link capturing In Product Help (IPH) is limited by guardrails to avoid +// -----------------------IPH Navigation Capturing guardrails------------------- +// Navigation capturing In Product Help (IPH) is limited by guardrails to avoid // becoming a nuisance to users. This is an overview of how they work: // - Accepting the IPH bubble will not decrease further prompts, and resets // existing guardrails. All values are measured globally and not per app. @@ -264,19 +265,21 @@ // - The IPH bubble shows up 6 times at max, after which it does not show up // again. // - Example scenarios for triggering guardrails: -// - User launches a site in an installed app with link capturing enabled and -// dismisses the IPH prompt. The prompt is then seen on days 0, 1, 2, 3, 4 and -// 5, after which the user never sees the IPH prompt again. -inline constexpr GuardrailData kIPHLinkCapturingGuardrails{ - // Number of times IPH bubble can show up for any apps launched via link - // capturing before it's muted. +// - User launches a site in an installed app with navigation capturing +// enabled and dismisses the IPH prompt. The prompt is then seen on days 0, 1, +// 2, 3, 4 and 5, after which the user never sees the IPH prompt again. +inline constexpr GuardrailData kIPHNavigationCapturingGuardrails{ + // Number of times IPH bubble can show up for any apps launched via + // navigation capturing before it's muted. .global_not_accept_count = 6, - // Number of days to mute IPH for link captured app launches after it's - // dismissed for any app. + // Number of days to mute IPH for navigation captured app launches after + // it's dismissed for any app. .global_mute_after_dismiss_days = 1, }; -inline constexpr GuardrailPrefNames kIPHLinkCapturingPrefNames{ +// TODO(crbug.com/362123239): Rename pref keys from link capturing to navigation +// capturing, migrate data if needed. +inline constexpr GuardrailPrefNames kIPHNavigationCapturingPrefNames{ .last_dismiss_time_name = "IPH_link_capturing_last_time_dismissed", .not_accepted_count_name = "IPH_link_capturing_consecutive_not_accepted_num",
diff --git a/chrome/browser/web_applications/web_app_pref_guardrails_unittest.cc b/chrome/browser/web_applications/web_app_pref_guardrails_unittest.cc index 7e38393..74ecfaf 100644 --- a/chrome/browser/web_applications/web_app_pref_guardrails_unittest.cc +++ b/chrome/browser/web_applications/web_app_pref_guardrails_unittest.cc
@@ -18,6 +18,7 @@ #include "components/sync_preferences/testing_pref_service_syncable.h" #include "components/webapps/browser/features.h" #include "components/webapps/common/web_app_id.h" +#include "content/public/common/content_features.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" @@ -553,7 +554,7 @@ base::FieldTrialParams params; params["link_capturing_guardrail_storage_duration"] = "2"; feature_list_.InitAndEnableFeatureWithParameters( - features::kDesktopPWAsLinkCapturing, std::move(params)); + features::kPwaNavigationCapturing, std::move(params)); } void SetUp() override { WebAppTest::SetUp(); } @@ -561,21 +562,22 @@ bool IsDesktopIphBlockedTimeSet() { const auto& dict = prefs()->GetDict(prefs::kWebAppsAppAgnosticIPHLinkCapturingState); - return dict.contains(kIPHLinkCapturingPrefNames.all_blocked_time_name); + return dict.contains( + kIPHNavigationCapturingPrefNames.all_blocked_time_name); } std::optional<base::Time> GetIphBlockedTime() { const auto& dict = prefs()->GetDict(prefs::kWebAppsAppAgnosticIPHLinkCapturingState); - auto* value = - dict.FindByDottedPath(kIPHLinkCapturingPrefNames.all_blocked_time_name); + auto* value = dict.FindByDottedPath( + kIPHNavigationCapturingPrefNames.all_blocked_time_name); EXPECT_NE(value, nullptr) << " "; return base::ValueToTime(value); } void FastForwardTimeForMaxDaysToStoreGuardrails() { - task_environment()->FastForwardBy( - base::Days(features::kLinkCapturingIPHGuardrailStorageDuration.Get())); + task_environment()->FastForwardBy(base::Days( + features::kNavigationCapturingIPHGuardrailStorageDuration.Get())); } bool IsDesktopLinkCapturingIphBlocked(const webapps::AppId& app) { @@ -595,7 +597,7 @@ protected: WebAppPrefGuardrails guardrails() { - return WebAppPrefGuardrails::GetForLinkCapturingIph(prefs()); + return WebAppPrefGuardrails::GetForNavigationCapturingIph(prefs()); } sync_preferences::TestingPrefServiceSyncable* prefs() { return &prefs_; } @@ -610,11 +612,12 @@ { const auto& dict = prefs()->GetDict(prefs::kWebAppsAppAgnosticIPHLinkCapturingState); - EXPECT_EQ(dict.FindInt(kIPHLinkCapturingPrefNames.not_accepted_count_name) - .value_or(0), - 1); - EXPECT_EQ(base::ValueToTime( - dict.Find(kIPHLinkCapturingPrefNames.last_dismiss_time_name)), + EXPECT_EQ( + dict.FindInt(kIPHNavigationCapturingPrefNames.not_accepted_count_name) + .value_or(0), + 1); + EXPECT_EQ(base::ValueToTime(dict.Find( + kIPHNavigationCapturingPrefNames.last_dismiss_time_name)), dismiss_time); } } @@ -624,17 +627,19 @@ { const auto& dict = prefs()->GetDict(prefs::kWebAppsAppAgnosticIPHLinkCapturingState); - EXPECT_EQ(dict.FindInt(kIPHLinkCapturingPrefNames.not_accepted_count_name) - .value_or(0), - 1); + EXPECT_EQ( + dict.FindInt(kIPHNavigationCapturingPrefNames.not_accepted_count_name) + .value_or(0), + 1); } guardrails().RecordAccept(app_id); { const auto& dict = prefs()->GetDict(prefs::kWebAppsAppAgnosticIPHLinkCapturingState); - EXPECT_EQ(dict.FindInt(kIPHLinkCapturingPrefNames.not_accepted_count_name) - .value_or(0), - 0); + EXPECT_EQ( + dict.FindInt(kIPHNavigationCapturingPrefNames.not_accepted_count_name) + .value_or(0), + 0); } } @@ -659,7 +664,7 @@ const base::Value::Dict& dict = prefs()->GetDict(prefs::kWebAppsAppAgnosticIPHLinkCapturingState); std::optional<int> agnostic_not_installed_count = - dict.FindInt(kIPHLinkCapturingPrefNames.not_accepted_count_name); + dict.FindInt(kIPHNavigationCapturingPrefNames.not_accepted_count_name); EXPECT_TRUE(agnostic_not_installed_count.has_value()); EXPECT_EQ(*agnostic_not_installed_count, 0); }
diff --git a/chrome/browser/web_applications/web_app_registrar.cc b/chrome/browser/web_applications/web_app_registrar.cc index ebb297a5..8eab286 100644 --- a/chrome/browser/web_applications/web_app_registrar.cc +++ b/chrome/browser/web_applications/web_app_registrar.cc
@@ -79,10 +79,10 @@ } bool IsLinkCapturingDisabledByDefaultBasedOnFlagState() { - return features::kLinkCapturingDefaultState.Get() == - features::LinkCapturingState::kDefaultOff || - features::kLinkCapturingDefaultState.Get() == - features::LinkCapturingState::kReimplDefaultOff; + return features::kNavigationCapturingDefaultState.Get() == + features::CapturingState::kDefaultOff || + features::kNavigationCapturingDefaultState.Get() == + features::CapturingState::kReimplDefaultOff; } } // namespace @@ -1096,7 +1096,7 @@ bool WebAppRegistrar::CanCaptureLinksInScope( const webapps::AppId& app_id) const { - if (!base::FeatureList::IsEnabled(features::kDesktopPWAsLinkCapturing)) { + if (!base::FeatureList::IsEnabled(features::kPwaNavigationCapturing)) { return false; } if (!IsInstallState(app_id, @@ -1180,7 +1180,7 @@ } int score; if (base::FeatureList::IsEnabled( - features::kDesktopPWAsLinkCapturingWithScopeExtensions)) { + features::kPwaNavigationCapturingWithScopeExtensions)) { score = GetAppExtendedScopeScore(url, app_id); } else { score = GetUrlInAppScopeScore(url.spec(), app_id); @@ -1212,7 +1212,7 @@ CHECK(url.is_valid()); int app_score; if (base::FeatureList::IsEnabled( - features::kDesktopPWAsLinkCapturingWithScopeExtensions)) { + features::kPwaNavigationCapturingWithScopeExtensions)) { app_score = GetAppExtendedScopeScore(url, app); } else { app_score = GetUrlInAppScopeScore(url.spec(), app); @@ -1223,7 +1223,7 @@ return base::ranges::none_of(GetAppIds(), [&](const webapps::AppId& app_id) { int other_score; if (base::FeatureList::IsEnabled( - features::kDesktopPWAsLinkCapturingWithScopeExtensions)) { + features::kPwaNavigationCapturingWithScopeExtensions)) { other_score = GetAppExtendedScopeScore(url, app_id); } else {
diff --git a/chrome/browser/web_applications/web_app_scope_extensions_browsertest.cc b/chrome/browser/web_applications/web_app_scope_extensions_browsertest.cc index a003120..466dea97 100644 --- a/chrome/browser/web_applications/web_app_scope_extensions_browsertest.cc +++ b/chrome/browser/web_applications/web_app_scope_extensions_browsertest.cc
@@ -58,7 +58,7 @@ std::vector<base::test::FeatureRefAndParams> enabled_features = apps::test::GetFeaturesToEnableLinkCapturingUX(); enabled_features.emplace_back( - features::kDesktopPWAsLinkCapturingWithScopeExtensions, + features::kPwaNavigationCapturingWithScopeExtensions, base::FieldTrialParams()); std::vector<base::test::FeatureRef> disabled_features;
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_controller.cc b/chrome/browser/webauthn/authenticator_request_dialog_controller.cc index cef5f8a..39987ed 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_controller.cc +++ b/chrome/browser/webauthn/authenticator_request_dialog_controller.cc
@@ -1345,8 +1345,6 @@ void AuthenticatorRequestDialogController::SetSelectedAuthenticatorForTesting( AuthenticatorReference test_authenticator) { - ephemeral_state_.selected_authenticator_id_ = - test_authenticator.authenticator_id; ephemeral_state_.saved_authenticators_.AddAuthenticator( std::move(test_authenticator)); }
diff --git a/chrome/browser/webauthn/authenticator_request_dialog_controller.h b/chrome/browser/webauthn/authenticator_request_dialog_controller.h index ccde54e..264f32d0 100644 --- a/chrome/browser/webauthn/authenticator_request_dialog_controller.h +++ b/chrome/browser/webauthn/authenticator_request_dialog_controller.h
@@ -63,10 +63,6 @@ // is only resolved after the UI is dismissed. bool is_request_complete() const; - const std::optional<std::string>& selected_authenticator_id() const { - return ephemeral_state_.selected_authenticator_id_; - } - // Starts the UX flow, by either showing the transport selection screen or // the guided flow for them most likely transport. // @@ -379,10 +375,6 @@ EphemeralState& operator=(EphemeralState&&); ~EphemeralState(); - // Represents the id of the Bluetooth authenticator that the user is trying - // to connect to or conduct WebAuthN request to via the WebAuthN UI. - std::optional<std::string> selected_authenticator_id_; - // Stores a list of |AuthenticatorReference| values such that a request can // be dispatched dispatched after some UI interaction. This is useful for // platform authenticators (and Windows) where dispatch to the authenticator
diff --git a/chrome/build/android-arm32.pgo.txt b/chrome/build/android-arm32.pgo.txt index 230ebc9..7e69b2b 100644 --- a/chrome/build/android-arm32.pgo.txt +++ b/chrome/build/android-arm32.pgo.txt
@@ -1 +1 @@ -chrome-android32-main-1724846055-7a086095d712c13898682cc9639acf086362c024-fd5edebfd768539f5ed330d660970aff8557925d.profdata +chrome-android32-main-1724867988-564f5749380a6eea85701c97b8c7471012769ae7-1b5e43a26a4ec291718b36d0e6de68c449ffa8e5.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 0dde2d15..6dc371cb 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1724853410-afac9ae0291055907f834d0e7adae6584faba5ce-bcb42fce5e8db83c65a3b2eb465866644b4d511b.profdata +chrome-mac-arm-main-1724867988-d0f55834015f2c5301f22065d5083f656f09c358-1b5e43a26a4ec291718b36d0e6de68c449ffa8e5.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index cde3eff..d8ef6e43 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1724846055-0cfeb2fb82e0f7f7a0370f9c238a7a3485e3fdfa-fd5edebfd768539f5ed330d660970aff8557925d.profdata +chrome-win32-main-1724857129-706716391862150281c7a31fdb48ef83027e3214-29afbdec0ee6a20f9c60ccdc1e9fc1734a358d2d.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index d209444a..30676ed3 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1724846055-455636d8280953a0f5f6366abf6d84398df90a68-fd5edebfd768539f5ed330d660970aff8557925d.profdata +chrome-win64-main-1724857129-b3af8a46e659676954a86f100c36727746aacabe-29afbdec0ee6a20f9c60ccdc1e9fc1734a358d2d.profdata
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 9fef1a71..8f3ff1f 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -286,24 +286,7 @@ "DesktopPWAsIconHealthChecks", base::FEATURE_ENABLED_BY_DEFAULT); -BASE_FEATURE(kDesktopPWAsLinkCapturing, - "DesktopPWAsLinkCapturing", - base::FEATURE_DISABLED_BY_DEFAULT); -const base::FeatureParam<LinkCapturingState>::Option kLinkCapturingParams[] = { - {LinkCapturingState::kDefaultOn, "on_by_default"}, - {LinkCapturingState::kDefaultOff, "off_by_default"}, - {LinkCapturingState::kReimplDefaultOn, "reimpl_default_on"}, - {LinkCapturingState::kReimplDefaultOff, "reimpl_default_off"}}; - -const base::FeatureParam<LinkCapturingState> kLinkCapturingDefaultState{ - &kDesktopPWAsLinkCapturing, "link_capturing_state", - LinkCapturingState::kDefaultOn, &kLinkCapturingParams}; - -const base::FeatureParam<int> kLinkCapturingIPHGuardrailStorageDuration{ - &kDesktopPWAsLinkCapturing, "link_capturing_guardrail_storage_duration", - kTotalDaysToStoreLinkCapturingIPHGuardrails}; - -BASE_FEATURE(kDesktopPWAsLinkCapturingWithScopeExtensions, +BASE_FEATURE(kPwaNavigationCapturingWithScopeExtensions, "DesktopPWAsLinkCapturingWithScopeExtensions", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 707079e..4bb809d2 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -162,29 +162,8 @@ COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kDesktopPWAsIconHealthChecks); -// Enables user link capturing on all desktop platforms. COMPONENT_EXPORT(CHROME_FEATURES) -BASE_DECLARE_FEATURE(kDesktopPWAsLinkCapturing); -enum class LinkCapturingState { - kDefaultOn = 0, - kDefaultOff = 1, - kReimplDefaultOn = 2, - kReimplDefaultOff = 3 -}; -// If links should be captured by apps by default. -COMPONENT_EXPORT(CHROME_FEATURES) -extern const base::FeatureParam<LinkCapturingState> kLinkCapturingDefaultState; - -COMPONENT_EXPORT(CHROME_FEATURES) -BASE_DECLARE_FEATURE(kDesktopPWAsLinkCapturingWithScopeExtensions); - -// Default amount of days after which the global link capturing IPH guardrails -// are cleared from storage. -inline constexpr int kTotalDaysToStoreLinkCapturingIPHGuardrails = 30; -// Number of days to "store" IPH guardrails for link captured app launches till -// they are cleared. -COMPONENT_EXPORT(CHROME_FEATURES) -extern const base::FeatureParam<int> kLinkCapturingIPHGuardrailStorageDuration; +BASE_DECLARE_FEATURE(kPwaNavigationCapturingWithScopeExtensions); COMPONENT_EXPORT(CHROME_FEATURES) BASE_DECLARE_FEATURE(kDesktopPWAsRunOnOsLogin);
diff --git a/chrome/renderer/accessibility/read_aloud_app_model.cc b/chrome/renderer/accessibility/read_aloud_app_model.cc index fd36bff3..716e4bd 100644 --- a/chrome/renderer/accessibility/read_aloud_app_model.cc +++ b/chrome/renderer/accessibility/read_aloud_app_model.cc
@@ -513,6 +513,10 @@ bool is_docs, const std::set<ui::AXNodeID>* current_nodes) const { ui::AXNode* anchor_node = GetAnchorNode(position); + if (!anchor_node) { + return false; + } + bool was_previously_spoken = NodeBeenOrWillBeSpoken(current_granularity, anchor_node->id()); bool is_text_node = a11y::IsTextForReadAnything(anchor_node, is_pdf, is_docs);
diff --git a/chrome/renderer/accessibility/read_anything_node_utils.cc b/chrome/renderer/accessibility/read_anything_node_utils.cc index 4b135b22..36685fe 100644 --- a/chrome/renderer/accessibility/read_anything_node_utils.cc +++ b/chrome/renderer/accessibility/read_anything_node_utils.cc
@@ -60,6 +60,10 @@ } bool IsTextForReadAnything(ui::AXNode* node, bool is_pdf, bool is_docs) { + if (!node) { + return false; + } + // ListMarkers will have an HTML tag of "::marker," so they won't be // considered text when checking for the length of the html tag. However, in // order to read out loud ordered bullets, nodes that have the kListMarker
diff --git a/chrome/renderer/accessibility/read_anything_node_utils_unittest.cc b/chrome/renderer/accessibility/read_anything_node_utils_unittest.cc new file mode 100644 index 0000000..6860301d --- /dev/null +++ b/chrome/renderer/accessibility/read_anything_node_utils_unittest.cc
@@ -0,0 +1,22 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/renderer/accessibility/read_anything_node_utils.h" + +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/accessibility/ax_node_position.h" + +class ReadAnythingNodeUtilsTest : public testing::Test { + protected: + ReadAnythingNodeUtilsTest() = default; +}; + +using testing::ElementsAre; +using testing::IsEmpty; + +TEST_F(ReadAnythingNodeUtilsTest, + IsTextForReadAnything_ReturnsFalseOnNullNode) { + EXPECT_FALSE(a11y::IsTextForReadAnything(nullptr, false, false)); +}
diff --git a/chrome/services/sharing/nearby/platform/ble_v2_medium.cc b/chrome/services/sharing/nearby/platform/ble_v2_medium.cc index d9bf71ba..e15e9f3 100644 --- a/chrome/services/sharing/nearby/platform/ble_v2_medium.cc +++ b/chrome/services/sharing/nearby/platform/ble_v2_medium.cc
@@ -111,6 +111,10 @@ return "JNI Thread Attach"; case bluetooth::mojom::ConnectResult::WAKELOCK: return "Wakelock"; + case bluetooth::mojom::ConnectResult::UNEXPECTED_STATE: + return "Unexpected State"; + case bluetooth::mojom::ConnectResult::SOCKET: + return "Socket Error"; } NOTREACHED();
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 9d37c78..5b1fec03 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -4148,6 +4148,7 @@ sources += [ "../browser/extensions/api/system_indicator/system_indicator_apitest.cc", "../browser/extensions/api/web_authentication_proxy/web_authentication_proxy_apitest.cc", + "../browser/supervised_user/supervised_user_verification_page_browsertest.cc", "../browser/ui/views/web_apps/file_handler_launch_dialog_browsertest.cc", "../browser/ui/webui/app_home/app_home_page_handler_browsertest.cc", "../browser/ui/webui/app_home/mock_app_home_page.cc", @@ -8011,6 +8012,7 @@ "../common/importer/mock_importer_bridge.cc", "../common/importer/mock_importer_bridge.h", "../renderer/accessibility/read_aloud_traversal_utils_unittest.cc", + "../renderer/accessibility/read_anything_node_utils_unittest.cc", "../renderer/media/webrtc_logging_agent_impl_unittest.cc", "../renderer/searchbox/searchbox_unittest.cc", "../utility/importer/bookmark_html_reader_unittest.cc", @@ -8212,6 +8214,7 @@ "//chrome/browser/ui/exclusive_access", "//chrome/browser/ui/lens:unit_tests", "//chrome/browser/ui/omnibox", + "//chrome/browser/ui/toasts:unit_tests", "//chrome/browser/ui/toasts/api:unit_tests", "//chrome/browser/ui/views/bubble", "//chrome/browser/ui/webui/cr_components/theme_color_picker",
diff --git a/chrome/test/data/extensions/api_test/file_system_provider/service_worker/evil/test.js b/chrome/test/data/extensions/api_test/file_system_provider/service_worker/evil/test.js index 00e014c..9865c963 100644 --- a/chrome/test/data/extensions/api_test/file_system_provider/service_worker/evil/test.js +++ b/chrome/test/data/extensions/api_test/file_system_provider/service_worker/evil/test.js
@@ -40,7 +40,7 @@ const error = await catchError(readTextFromBlob(fileSlice)); chrome.test.assertTrue(!!error, 'Reading should fail.'); - chrome.test.assertEq('NotReadableError', error.name); + chrome.test.assertEq('NotFoundError', error.name); chrome.test.succeed(); },
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test.ts b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test.ts index bc34bb16..fc60c24 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_app_test.ts
@@ -1260,9 +1260,9 @@ } } - setup(async () => { + setup(() => { // Reset to default state before each test to reduce dependencies. - await window.personalizationTestApi.reset(); + window.personalizationTestApi.goToRootPath(); // Disables transition animation for tests. setTransitionsEnabled(false); @@ -1311,6 +1311,7 @@ }); test('selects color scheme options', async () => { + await window.personalizationTestApi.setDefaultColorScheme(); const toggleDescription = getDynamicColorElement().shadowRoot?.getElementById( 'dynamicColorToggleDescription'); @@ -1364,6 +1365,7 @@ }); test('selects static color options', async () => { + await window.personalizationTestApi.setDefaultColorScheme(); const theme = getRouter() .shadowRoot?.querySelector('personalization-main') ?.shadowRoot?.querySelector<PersonalizationThemeElement>(
diff --git a/chrome/test/data/webui/cr_components/certificate_manager/certificate_manager_v2_focus_test.ts b/chrome/test/data/webui/cr_components/certificate_manager/certificate_manager_v2_focus_test.ts index f2026a4e..5c4e634f 100644 --- a/chrome/test/data/webui/cr_components/certificate_manager/certificate_manager_v2_focus_test.ts +++ b/chrome/test/data/webui/cr_components/certificate_manager/certificate_manager_v2_focus_test.ts
@@ -13,6 +13,7 @@ import {CertificateSource} from 'chrome://resources/cr_components/certificate_manager/certificate_manager_v2.mojom-webui.js'; import {CertificatesV2BrowserProxy} from 'chrome://resources/cr_components/certificate_manager/certificates_v2_browser_proxy.js'; import {PromiseResolver} from 'chrome://resources/js/promise_resolver.js'; +import {getDeepActiveElement} from 'chrome://resources/js/util.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {microtasksFinished} from 'chrome://webui-test/test_util.js'; @@ -174,4 +175,30 @@ assertEquals('deadbeef4', await navigator.clipboard.readText()); }); // </if> + + test('Check Focus when going in and out of subpages', async () => { + initializeElement(); + await microtasksFinished(); + certManager.$.viewOsImportedCerts.click(); + await microtasksFinished(); + + // Check focus is on back button in platform certs section. + assertTrue( + certManager.$.platformCertsSection.classList.contains('selected')); + const elementInFocus = getDeepActiveElement(); + assertTrue(!!elementInFocus); + assertEquals('backButton', elementInFocus.id); + const subsection = (elementInFocus.getRootNode() as ShadowRoot).host; + assertEquals('platformCertsSection', subsection.id); + + (elementInFocus as HTMLElement).click(); + await microtasksFinished(); + + // Check focus is on link row going to platform certs section. + assertTrue(certManager.$.localCertSection.classList.contains('selected')); + const newElementInFocus = getDeepActiveElement(); + assertTrue(!!newElementInFocus); + const linkRow = (newElementInFocus.getRootNode() as ShadowRoot).host; + assertEquals('viewOsImportedCerts', linkRow.id); + }); });
diff --git a/chrome/test/data/webui/cr_components/cr_components_browsertest.cc b/chrome/test/data/webui/cr_components/cr_components_browsertest.cc index 387d0ba62..63c7c6c 100644 --- a/chrome/test/data/webui/cr_components/cr_components_browsertest.cc +++ b/chrome/test/data/webui/cr_components/cr_components_browsertest.cc
@@ -116,6 +116,10 @@ "mocha.run()"); } +IN_PROC_BROWSER_TEST_F(CrComponentsHistoryClustersTest, Cluster) { + RunTest("cr_components/history_clusters/cluster_test.js", "mocha.run()"); +} + class CrComponentsMostVisitedTest : public WebUIMochaBrowserTest { protected: CrComponentsMostVisitedTest() {
diff --git a/chrome/test/data/webui/cr_components/history_clusters/BUILD.gn b/chrome/test/data/webui/cr_components/history_clusters/BUILD.gn index c7f245b..aa917576 100644 --- a/chrome/test/data/webui/cr_components/history_clusters/BUILD.gn +++ b/chrome/test/data/webui/cr_components/history_clusters/BUILD.gn
@@ -8,6 +8,7 @@ build_webui_tests("build") { files = [ + "cluster_test.ts", "history_clusters_test.ts", "horizontal_carousel_test.ts", "infinite_list_test.ts",
diff --git a/chrome/test/data/webui/cr_components/history_clusters/cluster_test.ts b/chrome/test/data/webui/cr_components/history_clusters/cluster_test.ts new file mode 100644 index 0000000..82f8761 --- /dev/null +++ b/chrome/test/data/webui/cr_components/history_clusters/cluster_test.ts
@@ -0,0 +1,148 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'chrome://history/strings.m.js'; +import 'chrome://resources/cr_components/history_clusters/cluster.js'; + +import {BrowserProxyImpl} from 'chrome://resources/cr_components/history_clusters/browser_proxy.js'; +import type {ClusterElement} from 'chrome://resources/cr_components/history_clusters/cluster.js'; +import type {Cluster, RawVisitData, URLVisit} from 'chrome://resources/cr_components/history_clusters/history_cluster_types.mojom-webui.js'; +import {PageCallbackRouter, PageHandlerRemote} from 'chrome://resources/cr_components/history_clusters/history_clusters.mojom-webui.js'; +import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; +import {assertEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {TestMock} from 'chrome://webui-test/test_mock.js'; +import {eventToPromise, microtasksFinished} from 'chrome://webui-test/test_util.js'; + +let handler: TestMock<PageHandlerRemote>&PageHandlerRemote; + +function createBrowserProxy() { + handler = TestMock.fromClass(PageHandlerRemote); + const callbackRouter = new PageCallbackRouter(); + BrowserProxyImpl.setInstance(new BrowserProxyImpl(handler, callbackRouter)); + callbackRouter.$.bindNewPipeAndPassRemote(); +} + +function getTestCluster(): Cluster { + const rawVisitData: RawVisitData = { + url: {url: ''}, + visitTime: {internalValue: BigInt(0)}, + }; + + const urlVisit1: URLVisit = { + visitId: BigInt(1), + normalizedUrl: {url: 'https://www.google.com'}, + urlForDisplay: 'https://www.google.com', + pageTitle: '', + titleMatchPositions: [], + urlForDisplayMatchPositions: [], + duplicates: [], + relativeDate: '', + annotations: [], + debugInfo: {}, + rawVisitData: rawVisitData, + isKnownToSync: false, + hasUrlKeyedImage: false, + }; + + const urlVisit2: URLVisit = { + visitId: BigInt(2), + normalizedUrl: {url: 'https://www.example.com'}, + urlForDisplay: 'https://www.example.com', + pageTitle: '', + titleMatchPositions: [], + urlForDisplayMatchPositions: [], + duplicates: [], + relativeDate: '', + annotations: [], + debugInfo: {}, + rawVisitData: rawVisitData, + isKnownToSync: false, + hasUrlKeyedImage: false, + }; + + const relatedSearch1 = { + query: 'abc', + url: {url: 'https://www.google.com'}, + }; + const relatedSearch2 = { + query: 'example', + url: {url: 'https://www.example.com'}, + }; + + return { + id: BigInt(111), + visits: [urlVisit1, urlVisit2], + label: '', + labelMatchPositions: [], + relatedSearches: [relatedSearch1, relatedSearch2], + imageUrl: null, + fromPersistence: false, + debugInfo: null, + tabGroupName: null, + }; +} + +suite('cluster element', () => { + let cluster: ClusterElement; + + suiteSetup(() => { + loadTimeData.overrideValues({ + isHistoryClustersImagesEnabled: true, + }); + }); + + setup(() => { + document.body.innerHTML = window.trustedTypes!.emptyHTML; + createBrowserProxy(); + cluster = document.createElement('history-cluster'); + cluster.cluster = getTestCluster(); + cluster.index = 0; + document.body.appendChild(cluster); + }); + + test('Fires events for url visit actions', async () => { + const menu = cluster.shadowRoot!.querySelector('cluster-menu'); + assertTrue(!!menu); + // Open cluster action menu. + menu.$.actionMenuButton.click(); + await microtasksFinished(); + + const hideEvent = eventToPromise('hide-visits', cluster); + const hideAllButton = + menu.shadowRoot!.querySelector<HTMLButtonElement>('#hideAllButton'); + assertTrue(!!hideAllButton); + hideAllButton.click(); + await hideEvent; + + await microtasksFinished(); + // Re-open cluster action menu. + menu.$.actionMenuButton.click(); + await microtasksFinished(); + const removeAllButton = + menu.shadowRoot!.querySelector<HTMLButtonElement>('#removeAllButton'); + assertTrue(!!removeAllButton); + const removeEvent = eventToPromise('remove-visits', cluster); + removeAllButton.click(); + await removeEvent; + + await microtasksFinished(); + // Re-open cluster action menu. + menu.$.actionMenuButton.click(); + await microtasksFinished(); + const openAllButton = + menu.shadowRoot!.querySelector<HTMLButtonElement>('#openAllButton'); + assertTrue(!!openAllButton); + openAllButton.click(); + await handler.whenCalled('openVisitUrlsInTabGroup'); + }); + + test('displays search queries', async () => { + const queries = cluster.shadowRoot!.querySelectorAll('search-query'); + assertEquals(2, queries.length); + + queries[0]!.$.searchQueryLink.click(); + const params = await handler.whenCalled('openHistoryCluster'); + assertEquals('https://www.google.com', params[0].url); + }); +});
diff --git a/chrome/test/data/webui/cr_components/history_clusters/history_clusters_test.ts b/chrome/test/data/webui/cr_components/history_clusters/history_clusters_test.ts index d7fe1de..c6cc32a 100644 --- a/chrome/test/data/webui/cr_components/history_clusters/history_clusters_test.ts +++ b/chrome/test/data/webui/cr_components/history_clusters/history_clusters_test.ts
@@ -261,6 +261,7 @@ await imageServiceHandler.whenCalled('getPageImageUrl'); await microtasksFinished(); assertEquals(PageImageServiceClientId.Journeys, clientId); + assertTrue(!!urlVisit.visit); assertEquals(urlVisit.visit.normalizedUrl, pageUrl); // Verify the icon element received the handler's response.
diff --git a/chrome/test/data/webui/downloads/bypass_warning_confirmation_interstitial_test.ts b/chrome/test/data/webui/downloads/bypass_warning_confirmation_interstitial_test.ts index e689ddba..1458bfce 100644 --- a/chrome/test/data/webui/downloads/bypass_warning_confirmation_interstitial_test.ts +++ b/chrome/test/data/webui/downloads/bypass_warning_confirmation_interstitial_test.ts
@@ -6,7 +6,6 @@ import type {DownloadsDangerousDownloadInterstitialElement, PageRemote} from 'chrome://downloads/downloads.js'; import {BrowserProxy, loadTimeData} from 'chrome://downloads/downloads.js'; -import {flush} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {keyDownOn} from 'chrome://webui-test/keyboard_mock_interactions.js'; import {isVisible, microtasksFinished} from 'chrome://webui-test/test_util.js'; @@ -35,7 +34,6 @@ 'warningBypassInterstitialSurveyTrustSiteWithUrl', displayReferrerUrl); interstitial.bypassPromptItemId = bypassPromptItemId; document.body.appendChild(interstitial); - flush(); }); test('trust site line with url displays correctly', function() { @@ -45,9 +43,10 @@ assertEquals(trustSiteLineUrl, trustSiteRadioButton.textContent!.trim()); }); - test('trust site line without url displays correctly', function() { + test('trust site line without url displays correctly', async () => { interstitial.trustSiteLine = loadTimeData.getString( 'warningBypassInterstitialSurveyTrustSiteWithoutUrl'); + await microtasksFinished(); const trustSiteRadioButton = interstitial.shadowRoot!.querySelector( 'cr-radio-button[name=TrustSite]'); @@ -133,12 +132,12 @@ assertFalse(isVisible(surveyAndDownloadButton)); continueAnywayButton.click(); + await microtasksFinished(); assertTrue(isVisible(surveyAndDownloadButton)); assertTrue(continueAnywayButton.disabled); await callbackRouterRemote.$.flushForTesting(); - flush(); const openSurveyId = await testDownloadsProxy.handler.whenCalled( 'recordOpenSurveyOnDangerousInterstitial');
diff --git a/chrome/test/data/webui/downloads/manager_test.ts b/chrome/test/data/webui/downloads/manager_test.ts index 448de6e4..d5a73f2 100644 --- a/chrome/test/data/webui/downloads/manager_test.ts +++ b/chrome/test/data/webui/downloads/manager_test.ts
@@ -268,7 +268,7 @@ 'recordOpenBypassWarningDialog'); assertEquals('itemId', recordOpenId); const dialog = manager.shadowRoot!.querySelector( - 'download-bypass-warning-confirmation-dialog'); + 'downloads-bypass-warning-confirmation-dialog'); assertTrue(!!dialog); assertTrue(dialog.$.dialog.open); assertEquals('item.pdf', dialog.fileName); @@ -307,7 +307,7 @@ 'recordOpenBypassWarningDialog'); assertEquals('itemId', recordOpenId); const dialog = manager.shadowRoot!.querySelector( - 'download-bypass-warning-confirmation-dialog'); + 'downloads-bypass-warning-confirmation-dialog'); assertTrue(!!dialog); assertTrue(dialog.$.dialog.open); assertEquals('item.pdf', dialog.fileName); @@ -343,7 +343,7 @@ })); flush(); const dialog = manager.shadowRoot!.querySelector( - 'download-bypass-warning-confirmation-dialog'); + 'downloads-bypass-warning-confirmation-dialog'); assertTrue(!!dialog); assertTrue(dialog.$.dialog.open); // Remove the file and check that the dialog is hidden.
diff --git a/chrome/test/data/webui/downloads/toolbar_test.ts b/chrome/test/data/webui/downloads/toolbar_test.ts index 354228dc..a0b7252 100644 --- a/chrome/test/data/webui/downloads/toolbar_test.ts +++ b/chrome/test/data/webui/downloads/toolbar_test.ts
@@ -5,6 +5,7 @@ import type {CrToastManagerElement, DownloadsToolbarElement} from 'chrome://downloads/downloads.js'; import {SearchService} from 'chrome://downloads/downloads.js'; import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {microtasksFinished} from 'chrome://webui-test/test_util.js'; import {createDownload} from './test_support.js'; @@ -40,13 +41,15 @@ assertFalse(toolbar.spinnerActive); }); - test('clear all shown/hidden', () => { - const clearAll = - toolbar.shadowRoot!.querySelector<HTMLButtonElement>('#clear-all')!; + test('clear all shown/hidden', async () => { + const clearAll = toolbar.$.clearAll; assertTrue(clearAll.hidden); toolbar.hasClearableDownloads = true; + await microtasksFinished(); assertFalse(clearAll.hidden); + toolbar.$.toolbar.getSearchField().setValue('test'); + await microtasksFinished(); assertTrue(clearAll.hidden); }); @@ -54,7 +57,7 @@ assertFalse(toastManager.isToastOpen); assertFalse(toastManager.slottedHidden); toolbar.hasClearableDownloads = true; - toolbar.shadowRoot!.querySelector<HTMLButtonElement>('#clear-all')!.click(); + toolbar.$.clearAll.click(); assertTrue(toastManager.isToastOpen); assertTrue(toastManager.slottedHidden); }); @@ -67,7 +70,7 @@ toastManager.show('', /* hideSlotted= */ false); assertFalse(toastManager.slottedHidden); toolbar.hasClearableDownloads = true; - toolbar.shadowRoot!.querySelector<HTMLButtonElement>('#clear-all')!.click(); + toolbar.$.clearAll.click(); assertTrue(toastManager.isToastOpen); assertTrue(toastManager.slottedHidden); }); @@ -81,7 +84,7 @@ toastManager.show('', /* hideSlotted= */ true); assertTrue(toastManager.slottedHidden); toolbar.hasClearableDownloads = true; - toolbar.shadowRoot!.querySelector<HTMLButtonElement>('#clear-all')!.click(); + toolbar.$.clearAll.click(); assertTrue(toastManager.isToastOpen); assertFalse(toastManager.slottedHidden); });
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 fbe45d6..c817acb5 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
@@ -14,7 +14,6 @@ import {CustomizeToolbarApiProxy} from 'chrome://customize-chrome-side-panel.top-chrome/customize_toolbar/customize_toolbar_api_proxy.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.js'; import {assertEquals, assertGE, assertTrue} from 'chrome://webui-test/chai_assert.js'; -import type {MetricsTracker} from 'chrome://webui-test/metrics_test_support.js'; import {fakeMetricsPrivate} from 'chrome://webui-test/metrics_test_support.js'; import type {TestMock} from 'chrome://webui-test/test_mock.js'; import {eventToPromise, microtasksFinished} from 'chrome://webui-test/test_util.js'; @@ -42,19 +41,14 @@ }); suite('Metrics', () => { - let metrics: MetricsTracker; - suiteSetup(() => { - document.body.innerHTML = window.trustedTypes!.emptyHTML; - customizeChromeApp = document.createElement('customize-chrome-app'); - document.body.appendChild(customizeChromeApp); loadTimeData.overrideValues({ 'extensionsCardEnabled': true, }); - metrics = fakeMetricsPrivate(); }); - test('Rendering extensions card section sets metric', async () => { + test('rendering extensions card section sets metric', async () => { + const metrics = fakeMetricsPrivate(); window.dispatchEvent(new Event('load')); const eventPromise = eventToPromise( 'detect-extensions-card-section-impression', customizeChromeApp);
diff --git a/chrome/test/interaction/interactive_browser_test_interactive_uitest.cc b/chrome/test/interaction/interactive_browser_test_interactive_uitest.cc index 202e2d02..9d434ff1 100644 --- a/chrome/test/interaction/interactive_browser_test_interactive_uitest.cc +++ b/chrome/test/interaction/interactive_browser_test_interactive_uitest.cc
@@ -426,8 +426,8 @@ SendAcceleratorToWebContents) { DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kWebContentsId); DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kClearAllClickEvent); - const DeepQuery kClearAllDownloadsButton = { - "downloads-manager", "downloads-toolbar", "#clear-all"}; + const DeepQuery kClearAllDownloadsButton = {"downloads-manager", + "downloads-toolbar", "#clearAll"}; const ui::Accelerator kClickWebButtonAccelerator(ui::KeyboardCode::VKEY_SPACE, ui::EF_NONE); StateChange clear_all_downloads_click;
diff --git a/chrome/updater/installer.h b/chrome/updater/installer.h index a6de3e9..1b1ac1f3 100644 --- a/chrome/updater/installer.h +++ b/chrome/updater/installer.h
@@ -46,14 +46,15 @@ base::FilePath ecp; }; -using AppInstallerResult = update_client::CrxInstaller::Result; using InstallProgressCallback = update_client::CrxInstaller::ProgressCallback; +using InstallerResult = update_client::CrxInstaller::Result; + // Runs an app installer. // The file `server_install_data` contains additional application-specific // install configuration parameters extracted either from the update response or // the app manifest. -AppInstallerResult RunApplicationInstaller( +InstallerResult RunApplicationInstaller( const AppInfo& app_info, const base::FilePath& installer_path, const std::string& install_args,
diff --git a/chrome/updater/installer_linux.cc b/chrome/updater/installer_linux.cc index 0d4e0bc..306a070 100644 --- a/chrome/updater/installer_linux.cc +++ b/chrome/updater/installer_linux.cc
@@ -15,7 +15,7 @@ namespace updater { -AppInstallerResult RunApplicationInstaller( +InstallerResult RunApplicationInstaller( const AppInfo& app_info, const base::FilePath& installer_path, const std::string& arguments, @@ -48,15 +48,15 @@ if (!process.IsValid() || !process.WaitForExitWithTimeout(timeout, &exit_code)) { LOG(ERROR) << "Could not launch application installer."; - return AppInstallerResult(kErrorApplicationInstallerFailed, - kErrorProcessLaunchFailed); + return InstallerResult(kErrorApplicationInstallerFailed, + kErrorProcessLaunchFailed); } if (exit_code != 0) { LOG(ERROR) << "Installer returned error code " << exit_code; - return AppInstallerResult(kErrorApplicationInstallerFailed, exit_code); + return InstallerResult(kErrorApplicationInstallerFailed, exit_code); } - return AppInstallerResult(); + return InstallerResult(); } std::string LookupString(const base::FilePath& path,
diff --git a/chrome/updater/installer_mac.cc b/chrome/updater/installer_mac.cc index cd212e2..1ecb3ce5 100644 --- a/chrome/updater/installer_mac.cc +++ b/chrome/updater/installer_mac.cc
@@ -17,7 +17,7 @@ namespace updater { -AppInstallerResult RunApplicationInstaller( +InstallerResult RunApplicationInstaller( const AppInfo& app_info, const base::FilePath& app_installer, const std::string& arguments, @@ -37,8 +37,8 @@ app_info.scope, app_info.version, arguments, installer_data_file, usage_stats_enabled, timeout); return exit_code == 0 - ? AppInstallerResult() - : AppInstallerResult(kErrorApplicationInstallerFailed, exit_code); + ? InstallerResult() + : InstallerResult(kErrorApplicationInstallerFailed, exit_code); } std::string LookupString(const base::FilePath& path,
diff --git a/chrome/updater/mac/BUILD.gn b/chrome/updater/mac/BUILD.gn index 76b4d00..8366457 100644 --- a/chrome/updater/mac/BUILD.gn +++ b/chrome/updater/mac/BUILD.gn
@@ -610,7 +610,6 @@ "$root_build_dir/Updater Packaging/signing/pkg-dmg", "$root_build_dir/Updater Packaging/signing/pkg/postinstall", "$root_build_dir/chrome/updater/.install", - "$root_build_dir/UpdaterSetup", "$root_build_dir/qualification_app", "$root_build_dir/${updater_product_full_name}Util", ] @@ -621,7 +620,6 @@ ":updater_bundle", ":updater_bundle_test", ":updater_install_script", - "//chrome/updater/mac/installer:metainstaller", "//chrome/updater/mac/signing", "//chrome/updater/test/qualification_app", "//chrome/updater/tools:${updater_product_full_name}Util",
diff --git a/chrome/updater/update_service.h b/chrome/updater/update_service.h index 25ef563..36d92c4 100644 --- a/chrome/updater/update_service.h +++ b/chrome/updater/update_service.h
@@ -215,8 +215,6 @@ std::string cohort; }; - using InstallerResult = update_client::CrxInstaller::Result; - // Returns the version of the active updater. The version object is invalid // if an error (including timeout) occurs. virtual void GetVersion(base::OnceCallback<void(const base::Version&)>) = 0;
diff --git a/chrome/updater/update_service_impl_impl.cc b/chrome/updater/update_service_impl_impl.cc index 6fdd5d6..3fd9864 100644 --- a/chrome/updater/update_service_impl_impl.cc +++ b/chrome/updater/update_service_impl_impl.cc
@@ -113,8 +113,8 @@ scoped_refptr<PolicyService> policy_service, crx_file::VerifierFormat verifier_format, scoped_refptr<PersistedData> persisted_data, - const AppClientInstallData& app_client_install_data, - const AppInstallDataIndex& app_install_data_index, + const base::flat_map<std::string, std::string>& app_client_install_data, + const base::flat_map<std::string, std::string>& app_install_data_index, const std::string& install_source, UpdateService::Priority priority, bool update_blocked, @@ -824,8 +824,8 @@ Priority::kBackground, base::BindOnce( &UpdateServiceImplImpl::OnShouldBlockForceInstallForMeteredNetwork, - this, app_ids_to_install, AppClientInstallData(), - AppInstallDataIndex(), + this, app_ids_to_install, base::flat_map<std::string, std::string>(), + base::flat_map<std::string, std::string>(), UpdateService::PolicySameVersionUpdate::kNotAllowed, state_update, std::move(callback))); } @@ -888,8 +888,10 @@ priority, base::BindOnce( &UpdateServiceImplImpl::OnShouldBlockUpdateForMeteredNetwork, this, - std::vector<std::string>{app_id}, AppClientInstallData(), - AppInstallDataIndex({std::make_pair(app_id, install_data_index)}), + std::vector<std::string>{app_id}, + base::flat_map<std::string, std::string>(), + base::flat_map<std::string, std::string>( + {std::make_pair(app_id, install_data_index)}), priority, policy_same_version_update, state_update, std::move(callback))); } @@ -910,7 +912,8 @@ priority, base::BindOnce( &UpdateServiceImplImpl::OnShouldBlockUpdateForMeteredNetwork, this, - app_ids, AppClientInstallData(), AppInstallDataIndex(), priority, + app_ids, base::flat_map<std::string, std::string>(), + base::flat_map<std::string, std::string>(), priority, UpdateService::PolicySameVersionUpdate::kNotAllowed, state_update, base::BindOnce( [](base::OnceCallback<void(Result)> callback, @@ -967,9 +970,9 @@ base::BindOnce( &internal::GetComponents, config_->GetPolicyService(), config_->GetCrxVerifierFormat(), config_->GetUpdaterPersistedData(), - AppClientInstallData( + base::flat_map<std::string, std::string>( {std::make_pair(registration.app_id, client_install_data)}), - AppInstallDataIndex( + base::flat_map<std::string, std::string>( {std::make_pair(registration.app_id, install_data_index)}), kInstallSourceTaggedMetainstaller, priority, /*update_blocked=*/false, PolicySameVersionUpdate::kAllowed), @@ -1250,7 +1253,8 @@ base::BindOnce(&internal::GetComponents, config_->GetPolicyService(), config_->GetCrxVerifierFormat(), config_->GetUpdaterPersistedData(), - AppClientInstallData(), AppInstallDataIndex(), + base::flat_map<std::string, std::string>(), + base::flat_map<std::string, std::string>(), priority == UpdateService::Priority::kForeground ? kInstallSourceOnDemand : "", @@ -1264,8 +1268,8 @@ void UpdateServiceImplImpl::OnShouldBlockUpdateForMeteredNetwork( const std::vector<std::string>& app_ids, - const AppClientInstallData& app_client_install_data, - const AppInstallDataIndex& app_install_data_index, + const base::flat_map<std::string, std::string>& app_client_install_data, + const base::flat_map<std::string, std::string>& app_install_data_index, Priority priority, PolicySameVersionUpdate policy_same_version_update, base::RepeatingCallback<void(const UpdateState&)> state_update, @@ -1293,8 +1297,8 @@ void UpdateServiceImplImpl::OnShouldBlockForceInstallForMeteredNetwork( const std::vector<std::string>& app_ids, - const AppClientInstallData& app_client_install_data, - const AppInstallDataIndex& app_install_data_index, + const base::flat_map<std::string, std::string>& app_client_install_data, + const base::flat_map<std::string, std::string>& app_install_data_index, PolicySameVersionUpdate policy_same_version_update, base::RepeatingCallback<void(const UpdateState&)> state_update, base::OnceCallback<void(Result)> callback,
diff --git a/chrome/updater/update_service_impl_impl.h b/chrome/updater/update_service_impl_impl.h index 0a6b3ef..0784956f 100644 --- a/chrome/updater/update_service_impl_impl.h +++ b/chrome/updater/update_service_impl_impl.h
@@ -34,9 +34,6 @@ class PolicyService; struct RegistrationRequest; -using AppClientInstallData = base::flat_map<std::string, std::string>; -using AppInstallDataIndex = base::flat_map<std::string, std::string>; - // All functions and callbacks must be called on the same sequence. class UpdateServiceImplImpl : public UpdateService { public: @@ -116,8 +113,8 @@ void OnShouldBlockUpdateForMeteredNetwork( const std::vector<std::string>& app_ids, - const AppClientInstallData& app_client_install_data, - const AppInstallDataIndex& app_install_data_index, + const base::flat_map<std::string, std::string>& app_client_install_data, + const base::flat_map<std::string, std::string>& app_install_data_index, Priority priority, PolicySameVersionUpdate policy_same_version_update, base::RepeatingCallback<void(const UpdateState&)> state_update, @@ -126,8 +123,8 @@ void OnShouldBlockForceInstallForMeteredNetwork( const std::vector<std::string>& app_ids, - const AppClientInstallData& app_client_install_data, - const AppInstallDataIndex& app_install_data_index, + const base::flat_map<std::string, std::string>& app_client_install_data, + const base::flat_map<std::string, std::string>& app_install_data_index, PolicySameVersionUpdate policy_same_version_update, base::RepeatingCallback<void(const UpdateState&)> state_update, base::OnceCallback<void(Result)> callback, @@ -153,8 +150,8 @@ scoped_refptr<PolicyService> policy_service, crx_file::VerifierFormat verifier_format, scoped_refptr<PersistedData> persisted_data, - const AppClientInstallData& app_client_install_data, - const AppInstallDataIndex& app_install_data_index, + const base::flat_map<std::string, std::string>& app_client_install_data, + const base::flat_map<std::string, std::string>& app_install_data_index, const std::string& install_source, UpdateService::Priority priority, bool update_blocked,
diff --git a/chrome/updater/win/installer/msi_custom_action.cc b/chrome/updater/win/installer/msi_custom_action.cc index b8916060..6c9b9bdf 100644 --- a/chrome/updater/win/installer/msi_custom_action.cc +++ b/chrome/updater/win/installer/msi_custom_action.cc
@@ -115,7 +115,7 @@ key->ReadValueDW(kRegValueLastInstallerResult, &last_installer_result) == ERROR_SUCCESS && last_installer_result == - static_cast<DWORD>(InstallerResult::kCustomError) && + static_cast<DWORD>(InstallerApiResult::kCustomError) && key->ReadValue(kRegValueLastInstallerResultUIString, &val) == ERROR_SUCCESS && !val.empty()
diff --git a/chrome/updater/win/installer/msi_custom_action_unittest.cc b/chrome/updater/win/installer/msi_custom_action_unittest.cc index 423e492..1789cd2 100644 --- a/chrome/updater/win/installer/msi_custom_action_unittest.cc +++ b/chrome/updater/win/installer/msi_custom_action_unittest.cc
@@ -15,6 +15,7 @@ #include "chrome/updater/test/unit_test_util.h" #include "chrome/updater/util/win_util.h" #include "chrome/updater/win/installer_api.h" +#include "chrome/updater/win/win_constants.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -145,7 +146,7 @@ registry_override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE)); if (SetResults()) { InstallerOutcome installer_outcome = {}; - installer_outcome.installer_result = InstallerResult::kCustomError; + installer_outcome.installer_result = InstallerApiResult::kCustomError; installer_outcome.installer_text = "some text"; EXPECT_TRUE(SetInstallerOutcomeForTesting( UpdaterScope::kSystem, base::WideToASCII(kAppId), installer_outcome));
diff --git a/chrome/updater/win/installer_api.cc b/chrome/updater/win/installer_api.cc index 0e0ffa3e..368fcde 100644 --- a/chrome/updater/win/installer_api.cc +++ b/chrome/updater/win/installer_api.cc
@@ -150,7 +150,7 @@ DWORD val = 0; if (key->ReadValueDW(kRegValueLastInstallerResult, &val) == ERROR_SUCCESS) { installer_outcome.installer_result = - *CheckedCastToEnum<InstallerResult>(val); + *CheckedCastToEnum<InstallerApiResult>(val); } if (key->ReadValueDW(kRegValueLastInstallerError, &val) == ERROR_SUCCESS) { installer_outcome.installer_error = val; @@ -284,7 +284,7 @@ DWORD val = 0; if (key->ReadValueDW(kRegValueInstallerResult, &val) == ERROR_SUCCESS) { installer_outcome.installer_result = - *CheckedCastToEnum<InstallerResult>(val); + *CheckedCastToEnum<InstallerApiResult>(val); } if (key->ReadValueDW(kRegValueInstallerError, &val) == ERROR_SUCCESS) { installer_outcome.installer_error = val; @@ -396,9 +396,9 @@ } else { // Set the installer result based on whether this is a success or an error. if (exit_code == 0) { - outcome.installer_result = InstallerResult::kSuccess; + outcome.installer_result = InstallerApiResult::kSuccess; } else { - outcome.installer_result = InstallerResult::kExitCode; + outcome.installer_result = InstallerApiResult::kExitCode; outcome.installer_error = exit_code; } } @@ -413,7 +413,7 @@ } switch (*outcome.installer_result) { - case InstallerResult::kSuccess: + case InstallerApiResult::kSuccess: // This is unconditional success: // - use the command line if available, and ignore everything else. if (outcome.installer_cmd_line) { @@ -421,10 +421,10 @@ } break; - case InstallerResult::kCustomError: - case InstallerResult::kMsiError: - case InstallerResult::kSystemError: - case InstallerResult::kExitCode: + case InstallerApiResult::kCustomError: + case InstallerApiResult::kMsiError: + case InstallerApiResult::kSystemError: + case InstallerApiResult::kExitCode: // These are usually unconditional errors: // - use the installer error, or the exit code, or report a generic // error. @@ -462,7 +462,7 @@ // The installer progress is written by the application installer as a value // under the application's client state in the Windows registry and read by // polling in a loop, while waiting for the installer to exit. -AppInstallerResult RunApplicationInstaller( +InstallerResult RunApplicationInstaller( const AppInfo& app_info, const base::FilePath& app_installer, const std::string& arguments, @@ -472,8 +472,8 @@ InstallProgressCallback progress_callback) { if (!app_installer.MatchesExtension(L".exe") && !app_installer.MatchesExtension(L".msi")) { - return AppInstallerResult(GOOPDATEINSTALL_E_FILENAME_INVALID, - kErrorInvalidFileExtension); + return InstallerResult(GOOPDATEINSTALL_E_FILENAME_INVALID, + kErrorInvalidFileExtension); } DeleteInstallerOutput(app_info.scope, app_info.app_id); @@ -511,8 +511,8 @@ process = base::LaunchProcess(cmdline, options); if (!process.IsValid()) { - return AppInstallerResult(GOOPDATEINSTALL_E_INSTALLER_FAILED_START, - HRESULTFromLastError()); + return InstallerResult(GOOPDATEINSTALL_E_INSTALLER_FAILED_START, + HRESULTFromLastError()); } } @@ -533,9 +533,9 @@ } } while (timer.Elapsed() < timeout && num_tries < kNumAlreadyRunningMaxTries); - return AppInstallerResult(exit_code == ERROR_INSTALL_ALREADY_RUNNING - ? GOOPDATEINSTALL_E_INSTALL_ALREADY_RUNNING - : GOOPDATEINSTALL_E_INSTALLER_TIMED_OUT); + return InstallerResult(exit_code == ERROR_INSTALL_ALREADY_RUNNING + ? GOOPDATEINSTALL_E_INSTALL_ALREADY_RUNNING + : GOOPDATEINSTALL_E_INSTALLER_TIMED_OUT); } std::string LookupString(const base::FilePath& path,
diff --git a/chrome/updater/win/installer_api.h b/chrome/updater/win/installer_api.h index f089b14..396bde48 100644 --- a/chrome/updater/win/installer_api.h +++ b/chrome/updater/win/installer_api.h
@@ -24,7 +24,7 @@ // // `InstallerProgress` (DWORD) - a percentage value [0-100]. // -// `InstallerResult` (DWORD) - specifies the result type and how to determine +// `InstallerApiResult` (DWORD) - specifies the result type and how to determine // success or failure. Allowable values are: // // 0 - Reports success regardless of the exit code or `InstallerError`. @@ -50,8 +50,8 @@ // it is available. // // `InstallerError` (DWORD) - specifies the error (or success) value. Overrides -// the exit code unless `InstallerResult` indicates that the exit code must be -// used (case 4). +// the exit code unless `InstallerApiResult` indicates that the exit code must +// be used (case 4). // // `InstallerExtraCode1` (DWORD) - additional information set by the installer. // @@ -70,8 +70,8 @@ // short company name specified in branding.gni (e.g. "GOOGLE"). template <> -struct EnumTraits<InstallerResult> { - using R = InstallerResult; +struct EnumTraits<InstallerApiResult> { + using R = InstallerApiResult; static constexpr R first_elem = R::kSuccess; static constexpr R last_elem = R::kExitCode; }; @@ -84,7 +84,7 @@ InstallerOutcome(const InstallerOutcome&); ~InstallerOutcome(); - std::optional<InstallerResult> installer_result; + std::optional<InstallerApiResult> installer_result; std::optional<int> installer_error; std::optional<int> installer_extracode1; std::optional<std::string> installer_text;
diff --git a/chrome/updater/win/installer_api_unittest.cc b/chrome/updater/win/installer_api_unittest.cc index af6a9cc..4d5f62f 100644 --- a/chrome/updater/win/installer_api_unittest.cc +++ b/chrome/updater/win/installer_api_unittest.cc
@@ -13,7 +13,6 @@ #include "chrome/updater/constants.h" #include "chrome/updater/updater_scope.h" #include "chrome/updater/util/win_util.h" -#include "chrome/updater/win/win_constants.h" #include "components/update_client/update_client.h" #include "testing/gtest/include/gtest/gtest.h" @@ -65,7 +64,7 @@ { InstallerOutcome installer_outcome; - installer_outcome.installer_result = InstallerResult::kSystemError; + installer_outcome.installer_result = InstallerApiResult::kSystemError; installer_outcome.installer_error = 1; installer_outcome.installer_extracode1 = -2; installer_outcome.installer_text = "some text"; @@ -77,7 +76,8 @@ std::optional<InstallerOutcome> installer_outcome = GetInstallerOutcome(updater_scope_, kAppId); ASSERT_TRUE(installer_outcome); - EXPECT_EQ(installer_outcome->installer_result, InstallerResult::kSystemError); + EXPECT_EQ(installer_outcome->installer_result, + InstallerApiResult::kSystemError); EXPECT_EQ(installer_outcome->installer_error, 1); EXPECT_EQ(installer_outcome->installer_extracode1, -2); EXPECT_STREQ(installer_outcome->installer_text->c_str(), "some text"); @@ -113,7 +113,7 @@ { InstallerOutcome installer_outcome_for_deletion; installer_outcome_for_deletion.installer_result = - InstallerResult::kSystemError; + InstallerApiResult::kSystemError; installer_outcome_for_deletion.installer_error = 1; installer_outcome_for_deletion.installer_extracode1 = -2; installer_outcome_for_deletion.installer_text = "some text"; @@ -138,7 +138,7 @@ TEST_P(InstallerAPITest, MakeInstallerResult) { { InstallerOutcome installer_outcome; - installer_outcome.installer_result = InstallerResult::kSuccess; + installer_outcome.installer_result = InstallerApiResult::kSuccess; installer_outcome.installer_error = 1; installer_outcome.installer_extracode1 = -2; installer_outcome.installer_text = "some text"; @@ -154,7 +154,7 @@ { InstallerOutcome installer_outcome; - installer_outcome.installer_result = InstallerResult::kCustomError; + installer_outcome.installer_result = InstallerApiResult::kCustomError; installer_outcome.installer_error = 1; installer_outcome.installer_extracode1 = -2; installer_outcome.installer_text = "some text"; @@ -178,7 +178,7 @@ { InstallerOutcome installer_outcome; - installer_outcome.installer_result = InstallerResult::kMsiError; + installer_outcome.installer_result = InstallerApiResult::kMsiError; installer_outcome.installer_error = 1; installer_outcome.installer_extracode1 = -2; installer_outcome.installer_text = "some text"; @@ -202,7 +202,7 @@ { InstallerOutcome installer_outcome; - installer_outcome.installer_result = InstallerResult::kSystemError; + installer_outcome.installer_result = InstallerApiResult::kSystemError; installer_outcome.installer_error = 1; installer_outcome.installer_extracode1 = -2; installer_outcome.installer_text = "some text"; @@ -226,7 +226,7 @@ { InstallerOutcome installer_outcome; - installer_outcome.installer_result = InstallerResult::kExitCode; + installer_outcome.installer_result = InstallerApiResult::kExitCode; installer_outcome.installer_error = 1; installer_outcome.installer_extracode1 = -2; installer_outcome.installer_text = "some text";
diff --git a/chrome/updater/win/win_constants.h b/chrome/updater/win/win_constants.h index 5f08b22..2c808ea 100644 --- a/chrome/updater/win/win_constants.h +++ b/chrome/updater/win/win_constants.h
@@ -157,8 +157,8 @@ extern const wchar_t kLegacyTaskNamePrefixSystem[]; extern const wchar_t kLegacyTaskNamePrefixUser[]; -// `InstallerResult` values defined by the Installer API. -enum class InstallerResult { +// `InstallerApiResult` values defined by the Installer API. +enum class InstallerApiResult { // The installer succeeded, unconditionally. // - if a launch command was provided via the installer API, the command will // be launched and the updater UI will exit silently. Otherwise, the updater
diff --git a/chromeos/ash/services/bluetooth_config/device_pairing_handler.cc b/chromeos/ash/services/bluetooth_config/device_pairing_handler.cc index 0dabe0b..dfcb3679 100644 --- a/chromeos/ash/services/bluetooth_config/device_pairing_handler.cc +++ b/chromeos/ash/services/bluetooth_config/device_pairing_handler.cc
@@ -82,6 +82,10 @@ case device::ConnectionFailureReason::kJniThreadAttach: [[fallthrough]]; case device::ConnectionFailureReason::kWakelock: + [[fallthrough]]; + case device::ConnectionFailureReason::kUnexpectedState: + [[fallthrough]]; + case device::ConnectionFailureReason::kSocketError: return mojom::PairingResult::kNonAuthFailure; } }
diff --git a/clank b/clank index 1dff60f..9ab4f67 160000 --- a/clank +++ b/clank
@@ -1 +1 @@ -Subproject commit 1dff60ff4bbb8b13831e78c6c4e32a1445b37cbe +Subproject commit 9ab4f6780971f4824a29937121d8e447a043b67d
diff --git a/components/accessibility/internal b/components/accessibility/internal index ecd750e..2e6c405 160000 --- a/components/accessibility/internal +++ b/components/accessibility/internal
@@ -1 +1 @@ -Subproject commit ecd750e333640c29bc0228ea55a9234693e327c6 +Subproject commit 2e6c405fd5f09ad9d8933bc531af8c5dd24f348c
diff --git a/components/autofill/core/browser/BUILD.gn b/components/autofill/core/browser/BUILD.gn index f463a6f..cab8675f 100644 --- a/components/autofill/core/browser/BUILD.gn +++ b/components/autofill/core/browser/BUILD.gn
@@ -1025,6 +1025,7 @@ "//components/variations:test_support", "//components/variations/net", "//components/version_info:version_info", + "//components/webdata/common", "//google_apis:test_support", "//services/network:test_support", "//services/network/public/cpp",
diff --git a/components/autofill/core/browser/autofill_external_delegate_unittest.cc b/components/autofill/core/browser/autofill_external_delegate_unittest.cc index 7200976..03a58c81 100644 --- a/components/autofill/core/browser/autofill_external_delegate_unittest.cc +++ b/components/autofill/core/browser/autofill_external_delegate_unittest.cc
@@ -1852,7 +1852,6 @@ AutofillSuggestionTriggerSource::kManualFallbackPayments); - const CreditCard unlocked_card = test::GetFullServerCard(); EXPECT_CALL(manager(), AuthenticateThenFillCreditCardForm( Property(&FormData::global_id, form.global_id()), Property(&FormFieldData::global_id,
diff --git a/components/autofill/core/browser/personal_data_manager_test_base.cc b/components/autofill/core/browser/personal_data_manager_test_base.cc index 600836d8..eeb229e 100644 --- a/components/autofill/core/browser/personal_data_manager_test_base.cc +++ b/components/autofill/core/browser/personal_data_manager_test_base.cc
@@ -37,8 +37,7 @@ std::unique_ptr<WebDatabaseTable>(profile_autofill_table_)); profile_web_database_->LoadDatabase(); profile_database_service_ = new AutofillWebDataService( - profile_web_database_, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault()); + profile_web_database_, base::SingleThreadTaskRunner::GetCurrentDefault()); profile_database_service_->Init(base::NullCallback()); account_web_database_ = @@ -50,8 +49,7 @@ std::unique_ptr<WebDatabaseTable>(account_autofill_table_)); account_web_database_->LoadDatabase(); account_database_service_ = new AutofillWebDataService( - account_web_database_, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault()); + account_web_database_, base::SingleThreadTaskRunner::GetCurrentDefault()); account_database_service_->Init(base::NullCallback()); strike_database_ = std::make_unique<TestInMemoryStrikeDatabase>(); @@ -62,6 +60,8 @@ void PersonalDataManagerTestBase::TearDownTest() { // Order of destruction is important as BrowserAutofillManager relies on // PersonalDataManager to be around when it gets destroyed. + account_database_service_->ShutdownDatabase(); + profile_web_database_->ShutdownDatabase(); test::ReenableSystemServices(); OSCryptMocker::TearDown(); }
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc index 2451cfc..86864b43 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_backend_impl.cc
@@ -124,9 +124,6 @@ "WebDatabase.AutofillWebDataBackendImpl.OperationResult", result); } -WebDatabase::State DoNothingAndCommit(WebDatabase* db) { - return WebDatabase::COMMIT_NEEDED; -} } // namespace AutofillWebDataBackendImpl::AutofillWebDataBackendImpl( @@ -173,7 +170,8 @@ } void AutofillWebDataBackendImpl::CommitChanges() { - web_database_backend_->ExecuteWriteTask(base::BindOnce(&DoNothingAndCommit)); + web_database_backend_->database()->CommitTransaction(); + web_database_backend_->database()->BeginTransaction(); } std::unique_ptr<WDTypedResult>
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.cc b/components/autofill/core/browser/webdata/autofill_webdata_service.cc index 3012c65..f8dbdf292 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_service.cc +++ b/components/autofill/core/browser/webdata/autofill_webdata_service.cc
@@ -26,35 +26,22 @@ AutofillWebDataService::AutofillWebDataService( scoped_refptr<WebDatabaseService> wdbs, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner) + scoped_refptr<base::SequencedTaskRunner> ui_task_runner) : WebDataServiceBase(std::move(wdbs), ui_task_runner), ui_task_runner_(std::move(ui_task_runner)), - db_task_runner_(std::move(db_task_runner)), autofill_backend_(nullptr) { base::RepeatingCallback<void(syncer::DataType)> on_autofill_changed_by_sync_callback = base::BindRepeating( &AutofillWebDataService::NotifyOnAutofillChangedBySyncOnUISequence, weak_ptr_factory_.GetWeakPtr()); autofill_backend_ = new AutofillWebDataBackendImpl( - wdbs_->GetBackend(), ui_task_runner_, db_task_runner_, + wdbs_->GetBackend(), ui_task_runner_, wdbs_->GetDbSequence(), on_autofill_changed_by_sync_callback); } -AutofillWebDataService::AutofillWebDataService( - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner) - : WebDataServiceBase(nullptr, ui_task_runner), - ui_task_runner_(std::move(ui_task_runner)), - db_task_runner_(std::move(db_task_runner)), - autofill_backend_(new AutofillWebDataBackendImpl(nullptr, - ui_task_runner_, - db_task_runner_, - base::NullCallback())) {} - void AutofillWebDataService::ShutdownOnUISequence() { weak_ptr_factory_.InvalidateWeakPtrs(); - db_task_runner_->PostTask( + wdbs_->GetDbSequence()->PostTask( FROM_HERE, BindOnce(&AutofillWebDataBackendImpl::ResetUserData, autofill_backend_)); WebDataServiceBase::ShutdownOnUISequence(); @@ -375,14 +362,12 @@ void AutofillWebDataService::AddObserver( AutofillWebDataServiceObserverOnDBSequence* observer) { - DCHECK(db_task_runner_->RunsTasksInCurrentSequence()); if (autofill_backend_) autofill_backend_->AddObserver(observer); } void AutofillWebDataService::RemoveObserver( AutofillWebDataServiceObserverOnDBSequence* observer) { - DCHECK(db_task_runner_->RunsTasksInCurrentSequence()); if (autofill_backend_) autofill_backend_->RemoveObserver(observer); } @@ -400,19 +385,19 @@ } base::SupportsUserData* AutofillWebDataService::GetDBUserData() { - DCHECK(db_task_runner_->RunsTasksInCurrentSequence()); return autofill_backend_->GetDBUserData(); } void AutofillWebDataService::GetAutofillBackend( base::OnceCallback<void(AutofillWebDataBackend*)> callback) { - db_task_runner_->PostTask( + wdbs_->GetDbSequence()->PostTask( FROM_HERE, base::BindOnce(std::move(callback), base::RetainedRef(autofill_backend_))); } -base::SequencedTaskRunner* AutofillWebDataService::GetDBTaskRunner() { - return db_task_runner_.get(); +scoped_refptr<base::SequencedTaskRunner> +AutofillWebDataService::GetDBTaskRunner() { + return wdbs_->GetDbSequence(); } WebDataServiceBase::Handle
diff --git a/components/autofill/core/browser/webdata/autofill_webdata_service.h b/components/autofill/core/browser/webdata/autofill_webdata_service.h index 7106350..b0df487 100644 --- a/components/autofill/core/browser/webdata/autofill_webdata_service.h +++ b/components/autofill/core/browser/webdata/autofill_webdata_service.h
@@ -40,13 +40,10 @@ // API for Autofill web data. class AutofillWebDataService : public WebDataServiceBase { public: - AutofillWebDataService( - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner); + // Runs db tasks on the wdbs db task runner. AutofillWebDataService( scoped_refptr<WebDatabaseService> wdbs, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner); + scoped_refptr<base::SequencedTaskRunner> ui_task_runner); AutofillWebDataService(const AutofillWebDataService&) = delete; AutofillWebDataService& operator=(const AutofillWebDataService&) = delete; @@ -236,7 +233,7 @@ // Returns a task runner that can be used to schedule tasks on the DB // sequence. - base::SequencedTaskRunner* GetDBTaskRunner(); + scoped_refptr<base::SequencedTaskRunner> GetDBTaskRunner(); // Triggers an Autocomplete retention policy run which will cleanup data that // hasn't been used since over the retention threshold. @@ -265,9 +262,6 @@ // The task runner that this class uses for UI tasks. scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; - // The task runner that this class uses for DB tasks. - scoped_refptr<base::SequencedTaskRunner> db_task_runner_; - scoped_refptr<AutofillWebDataBackendImpl> autofill_backend_; // This factory is used on the UI sequence. All vended weak pointers are
diff --git a/components/autofill/core/browser/webdata/mock_autofill_webdata_service.cc b/components/autofill/core/browser/webdata/mock_autofill_webdata_service.cc index d0965df..899f3c1 100644 --- a/components/autofill/core/browser/webdata/mock_autofill_webdata_service.cc +++ b/components/autofill/core/browser/webdata/mock_autofill_webdata_service.cc
@@ -3,13 +3,18 @@ // found in the LICENSE file. #include "components/autofill/core/browser/webdata/mock_autofill_webdata_service.h" + #include "base/task/single_thread_task_runner.h" +#include "components/webdata/common/web_database_service.h" namespace autofill { MockAutofillWebDataService::MockAutofillWebDataService() : AutofillWebDataService( - base::SingleThreadTaskRunner::GetCurrentDefault(), + base::MakeRefCounted<WebDatabaseService>( + base::FilePath(), + base::SingleThreadTaskRunner::GetCurrentDefault(), + base::SingleThreadTaskRunner::GetCurrentDefault()), base::SingleThreadTaskRunner::GetCurrentDefault()) {} MockAutofillWebDataService::~MockAutofillWebDataService() = default;
diff --git a/components/autofill/core/browser/webdata/web_data_service_unittest.cc b/components/autofill/core/browser/webdata/web_data_service_unittest.cc index e6afc76..dcac78d 100644 --- a/components/autofill/core/browser/webdata/web_data_service_unittest.cc +++ b/components/autofill/core/browser/webdata/web_data_service_unittest.cc
@@ -103,9 +103,7 @@ class WebDataServiceTest : public testing::Test { public: WebDataServiceTest() - : task_environment_(base::test::TaskEnvironment::MainThreadType::UI), - db_task_runner_( - base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})) {} + : task_environment_(base::test::TaskEnvironment::MainThreadType::UI) {} protected: void SetUp() override { @@ -114,14 +112,15 @@ wdbs_ = base::MakeRefCounted<WebDatabaseService>( base::FilePath(WebDatabase::kInMemoryPath), - base::SequencedTaskRunner::GetCurrentDefault(), db_task_runner_); + base::SequencedTaskRunner::GetCurrentDefault(), + base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})); wdbs_->AddTable(std::make_unique<AddressAutofillTable>()); wdbs_->AddTable(std::make_unique<AutocompleteTable>()); wdbs_->AddTable(std::make_unique<PaymentsAutofillTable>()); wdbs_->LoadDatabase(); wds_ = base::MakeRefCounted<AutofillWebDataService>( - wdbs_, base::SequencedTaskRunner::GetCurrentDefault(), db_task_runner_); + wdbs_, base::SequencedTaskRunner::GetCurrentDefault()); wds_->Init(base::NullCallback()); } @@ -134,13 +133,13 @@ void WaitForEmptyDBSequence() { base::RunLoop run_loop; - db_task_runner_->PostTaskAndReply(FROM_HERE, base::DoNothing(), - run_loop.QuitClosure()); + wdbs_->GetDbSequence()->PostTaskAndReply(FROM_HERE, base::DoNothing(), + run_loop.QuitClosure()); run_loop.Run(); } base::test::TaskEnvironment task_environment_; - scoped_refptr<base::SequencedTaskRunner> db_task_runner_; + base::FilePath profile_dir_; scoped_refptr<WebDatabaseService> wdbs_; scoped_refptr<AutofillWebDataService> wds_; };
diff --git a/components/autofill/core/common/autofill_features.cc b/components/autofill/core/common/autofill_features.cc index a3d3e62a..3c68c0a5 100644 --- a/components/autofill/core/common/autofill_features.cc +++ b/components/autofill/core/common/autofill_features.cc
@@ -254,15 +254,6 @@ "AutofillExtractOnlyNonAdFrames", base::FEATURE_DISABLED_BY_DEFAULT); -// LINT.IfChange(autofill_xhr_submission_detection_ios) -// If enabled, XHR form submissions are detected on iOS when the last interacted -// form in a frame is removed. Otherwise only HTTP form submissions are detected -// on iOS. -BASE_FEATURE(kAutofillEnableXHRSubmissionDetectionIOS, - "AutofillEnableXHRSubmissionDetectionIOS", - base::FEATURE_ENABLED_BY_DEFAULT); -// LINT.ThenChange(//components/autofill/ios/form_util/resources/autofill_form_features.ts:autofill_xhr_submission_detection_ios) - // When enabled, focusing on an autofilled field that was traditionally filled // with address data (meaning filled with the value of their classified type) // will yield field-by-field filling suggestions without prefix matching.
diff --git a/components/autofill/core/common/autofill_features.h b/components/autofill/core/common/autofill_features.h index 806b3e9..f99cf9f5 100644 --- a/components/autofill/core/common/autofill_features.h +++ b/components/autofill/core/common/autofill_features.h
@@ -91,8 +91,6 @@ COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillExtractOnlyNonAdFrames); COMPONENT_EXPORT(AUTOFILL) -BASE_DECLARE_FEATURE(kAutofillEnableXHRSubmissionDetectionIOS); -COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillAddressFieldSwapping); COMPONENT_EXPORT(AUTOFILL) BASE_DECLARE_FEATURE(kAutofillFixCachingOnJavaScriptChanges);
diff --git a/components/autofill/ios/browser/BUILD.gn b/components/autofill/ios/browser/BUILD.gn index acd37cab..89766329 100644 --- a/components/autofill/ios/browser/BUILD.gn +++ b/components/autofill/ios/browser/BUILD.gn
@@ -148,17 +148,17 @@ ":util", "//base", "//base/test:test_support", + "//components/autofill/core/browser", "//components/autofill/core/browser:test_support", "//components/autofill/core/common", + "//components/autofill/core/common:features", "//components/autofill/core/common:test_support", + "//components/autofill/core/common/mojom:mojo_types_shared_cpp_sources", "//components/autofill/ios/common", - "//components/autofill/ios/form_util", "//components/autofill/ios/form_util:child_frame_registrar", "//components/autofill/ios/form_util:form_handler_feature", "//components/autofill/ios/form_util:form_util_feature", "//components/autofill/ios/form_util:test_support", - "//components/leveldb_proto:leveldb_proto", - "//components/prefs", "//components/prefs:test_support", "//ios/testing:embedded_test_server_support", "//ios/web/public",
diff --git a/components/autofill/ios/browser/autofill_across_iframes_unittest.mm b/components/autofill/ios/browser/autofill_across_iframes_unittest.mm index d48dbba8..947b01452 100644 --- a/components/autofill/ios/browser/autofill_across_iframes_unittest.mm +++ b/components/autofill/ios/browser/autofill_across_iframes_unittest.mm
@@ -1431,10 +1431,6 @@ // Tests that form deletion in a child frame is taken into consideration where // the parent browser form is updated accordingly. TEST_F(AutofillAcrossIframesTest, UpdateOnFormDeletion) { - // Enable Autofill XHR detection to enable the detection of deleted forms. - base::test::ScopedFeatureList feature_list( - autofill::features::kAutofillEnableXHRSubmissionDetectionIOS); - AddIframe("cf1", "<form><input type=\"text\"></form>"); AddIframe("cf2", "<form><input type=\"text\"></form>"); StartTestServerAndLoad(); @@ -1479,10 +1475,6 @@ // Tests that synthethic form deletion in a child frame is taken into // consideration where the parent browser form is updated accordingly. TEST_F(AutofillAcrossIframesTest, UpdateOnFormDeletion_Synthetic) { - // Enable Autofill XHR detection to enable the detection of deleted forms. - base::test::ScopedFeatureList feature_list( - autofill::features::kAutofillEnableXHRSubmissionDetectionIOS); - AddIframe("cf1", "<div id=\"form1\"><input type=\"text\">" "<input type=\"text\"></div>"); AddIframe("cf2", "<div id=\"form1\"><input type=\"text\">" @@ -1531,10 +1523,6 @@ // Tests that the partial deletion of fields in the synthethic form of a child // frame isn't reported as form removal since the synthetic still remains. TEST_F(AutofillAcrossIframesTest, UpdateOnFormDeletion_Synthetic_Partial) { - // Enable Autofill XHR detection to enable the detection of deleted forms. - base::test::ScopedFeatureList feature_list( - autofill::features::kAutofillEnableXHRSubmissionDetectionIOS); - AddIframe("cf1", "<input type=\"text\">" "<input type=\"text\">"); AddIframe("cf2", "<input type=\"text\">"
diff --git a/components/autofill/ios/browser/autofill_agent.mm b/components/autofill/ios/browser/autofill_agent.mm index 9266f2c..1489e36a 100644 --- a/components/autofill/ios/browser/autofill_agent.mm +++ b/components/autofill/ios/browser/autofill_agent.mm
@@ -869,11 +869,6 @@ - (void)webState:(web::WebState*)webState didRegisterFormRemoval:(const autofill::FormRemovalParams&)params inFrame:(web::WebFrame*)frame { - if (!base::FeatureList::IsEnabled( - autofill::features::kAutofillEnableXHRSubmissionDetectionIOS)) { - return; - } - CHECK_EQ(_webState, webState); CHECK(!params.removed_forms.empty() || !params.removed_unowned_fields.empty()) << "Invalid params. Form removal events with missing input should have " @@ -1313,10 +1308,6 @@ frame, base::FeatureList::IsEnabled( autofill::features::kAutofillAcrossIframesIos)); - FormUtilJavaScriptFeature::GetInstance()->SetAutofillXHRSubmissionDetection( - frame, base::FeatureList::IsEnabled( - autofill::features::kAutofillEnableXHRSubmissionDetectionIOS)); - FormUtilJavaScriptFeature::GetInstance()->SetAutofillIsolatedContentWorld( frame, base::FeatureList::IsEnabled(kAutofillIsolatedWorldForJavascriptIos));
diff --git a/components/autofill/ios/browser/autofill_driver_ios.mm b/components/autofill/ios/browser/autofill_driver_ios.mm index 5f1da16..1e40d25 100644 --- a/components/autofill/ios/browser/autofill_driver_ios.mm +++ b/components/autofill/ios/browser/autofill_driver_ios.mm
@@ -14,7 +14,6 @@ #import "components/autofill/core/browser/autofill_driver_router.h" #import "components/autofill/core/browser/form_filler.h" #import "components/autofill/core/browser/form_structure.h" -#import "components/autofill/core/common/autofill_features.h" #import "components/autofill/core/common/field_data_manager.h" #import "components/autofill/core/common/mojom/autofill_types.mojom-shared.h" #import "components/autofill/core/common/unique_ids.h" @@ -462,12 +461,6 @@ void AutofillDriverIOS::UpdateLastInteractedForm( const FormData& form_data, const FieldRendererId& formless_field) { - // No-op when XHR submission detection disabled. - if (!base::FeatureList::IsEnabled( - autofill::features::kAutofillEnableXHRSubmissionDetectionIOS)) { - return; - } - last_interacted_form_.emplace(form_data, formless_field); } @@ -513,9 +506,6 @@ void AutofillDriverIOS::FormsRemoved( const std::set<FormRendererId>& removed_forms, const std::set<FieldRendererId>& removed_unowned_fields) { - CHECK(base::FeatureList::IsEnabled( - autofill::features::kAutofillEnableXHRSubmissionDetectionIOS)); - const bool submission_detected = DetectFormSubmissionAfterFormRemoval( removed_forms, removed_unowned_fields); RecordFormRemoval(
diff --git a/components/autofill/ios/browser/autofill_xhr_sumission_detection_unittest.mm b/components/autofill/ios/browser/autofill_xhr_sumission_detection_unittest.mm index 55b65b5..927e3ba 100644 --- a/components/autofill/ios/browser/autofill_xhr_sumission_detection_unittest.mm +++ b/components/autofill/ios/browser/autofill_xhr_sumission_detection_unittest.mm
@@ -12,7 +12,6 @@ #import "base/time/time.h" #import "components/autofill/core/browser/browser_autofill_manager.h" #import "components/autofill/core/browser/test_autofill_client.h" -#import "components/autofill/core/common/autofill_features.h" #import "components/autofill/core/common/field_data_manager.h" #import "components/autofill/core/common/form_data.h" #import "components/autofill/core/common/form_field_data.h" @@ -58,10 +57,6 @@ // AutofillDriverIOS. class AutofillXHRSubmissionDetectionTest : public PlatformTest { public: - AutofillXHRSubmissionDetectionTest() - : PlatformTest(), - feature_list_(features::kAutofillEnableXHRSubmissionDetectionIOS) {} - void SetUp() override { PlatformTest::SetUp(); @@ -106,7 +101,6 @@ main_frame_driver()->GetAutofillManager()); } - base::test::ScopedFeatureList feature_list_; base::test::TaskEnvironment task_environment_; autofill::TestAutofillClient autofill_client_; web::FakeWebState web_state_;
diff --git a/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm b/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm index fb7a4f0f..89d9557 100644 --- a/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm +++ b/components/autofill/ios/form_util/form_activity_tab_helper_unittest.mm
@@ -297,23 +297,17 @@ // Test fixture verifying the behavior of FormActivityTabHelper when handling // form mutation events. -class FormMutationTest : public FormActivityTabHelperTest, - public testing::WithParamInterface<bool> { +class FormMutationTest : public FormActivityTabHelperTest { public: void SetUp() override { FormActivityTabHelperTest::SetUp(); } protected: - // Loads the specified HTML content, prepares for form mutation tracking, and - // optionally enables XHR submission detection. + // Loads the specified HTML content, prepares for form mutation tracking. void LoadHtmlForMutationTest(NSString* html) { LoadHtml(html); web::WebFrame* main_frame = WaitForMainFrame(); ASSERT_TRUE(main_frame); TrackFormMutations(main_frame); - - autofill::FormUtilJavaScriptFeature::GetInstance() - ->SetAutofillXHRSubmissionDetection(main_frame, - IsXHRSubmissionDetectionEnabled()); // Force fetching forms to set the elements renderer IDs. // Element IDs are set on demand, the first time they are queried for an // element. Setting them here make the tests easier to maintain because the @@ -361,9 +355,6 @@ return info->form_removal_params; } - // Helper functions to access parameters: - bool IsXHRSubmissionDetectionEnabled() const { return GetParam(); } - // Forces fetching forms in the main frame which sets renderer IDs in the // relevant forms and fields. IDs are set in the order the elements appear in // the DOM tree. @@ -386,7 +377,7 @@ }; // Tests that observer is called on form removal. -TEST_P(FormMutationTest, PasswordFormRemovalRegistered) { +TEST_F(FormMutationTest, PasswordFormRemovalRegistered) { LoadHtmlForMutationTest( @"<form name=\"form1\" id=\"form1\">" "<input type=\"text\" name=\"username\" id=\"id1\">" @@ -404,15 +395,15 @@ ElementsAre(FormRendererId(1))); EXPECT_THAT(form_removal_params.value().removed_unowned_fields, IsEmpty()); - histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.DropCount", - /*sample=*/0, - /*expected_bucket_count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendCount", - /*sample=*/1, - /*expected_bucket_count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendRatio", - /*sample=*/100, - /*expected_bucket_count=*/1); + histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.DropCount", + /*sample=*/0, + /*expected_bucket_count=*/1); + histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendCount", + /*sample=*/1, + /*expected_bucket_count=*/1); + histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendRatio", + /*sample=*/100, + /*expected_bucket_count=*/1); // Validate that only one removal event is received. ASSERT_FALSE(WaitUntilConditionOrTimeout( @@ -423,7 +414,7 @@ // Tests that removing non-password form triggers // 'form_removed" event. -TEST_P(FormMutationTest, RemoveNonPasswordForm) { +TEST_F(FormMutationTest, RemoveNonPasswordForm) { // Load html with one form. LoadHtmlForMutationTest(@"<form id='form1'>" "<input type='text'>" @@ -432,19 +423,15 @@ std::optional<autofill::FormRemovalParams> form_removal_params = RemoveElement(/*element_id=*/@"form1"); - if (IsXHRSubmissionDetectionEnabled()) { - ASSERT_TRUE(form_removal_params); - EXPECT_THAT(form_removal_params.value().removed_forms, - ElementsAre(FormRendererId(1))); - EXPECT_THAT(form_removal_params.value().removed_unowned_fields, IsEmpty()); - } else { - ASSERT_FALSE(form_removal_params); - } + ASSERT_TRUE(form_removal_params); + EXPECT_THAT(form_removal_params.value().removed_forms, + ElementsAre(FormRendererId(1))); + EXPECT_THAT(form_removal_params.value().removed_unowned_fields, IsEmpty()); } // Tests that removing multiple forms triggers // 'form_removed" event. -TEST_P(FormMutationTest, RemoveMultipleForms) { +TEST_F(FormMutationTest, RemoveMultipleForms) { // Load html with multiple forms. LoadHtmlForMutationTest(@"<div id='div'>" "<form id='form1'>" @@ -467,20 +454,15 @@ const FormRendererId form2_id = FormRendererId(3); const FormRendererId form3_id = FormRendererId(5); - if (IsXHRSubmissionDetectionEnabled()) { - EXPECT_THAT(form_removal_params.value().removed_forms, - UnorderedElementsAre(form1_id, form2_id, form3_id)); + EXPECT_THAT(form_removal_params.value().removed_forms, + UnorderedElementsAre(form1_id, form2_id, form3_id)); - } else { - EXPECT_THAT(form_removal_params.value().removed_forms, - ElementsAre(form1_id)); - } EXPECT_THAT(form_removal_params.value().removed_unowned_fields, IsEmpty()); } // Tests that removing unowned password fields triggers 'password_form_removed" // event. -TEST_P(FormMutationTest, RemoveFormlessPasswordFields) { +TEST_F(FormMutationTest, RemoveFormlessPasswordFields) { LoadHtmlForMutationTest( @"<body><div>" "<input type=\"password\" name=\"password\" id=\"pw\">" @@ -499,15 +481,15 @@ ElementsAre(FieldRendererId(1))); EXPECT_THAT(form_removal_params.value().frame_id, Not(IsEmpty())); - histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.DropCount", - /*sample=*/0, - /*expected_bucket_count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendCount", - /*sample=*/1, - /*expected_bucket_count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendRatio", - /*sample=*/100, - /*expected_bucket_count=*/1); + histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.DropCount", + /*sample=*/0, + /*expected_bucket_count=*/1); + histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendCount", + /*sample=*/1, + /*expected_bucket_count=*/1); + histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendRatio", + /*sample=*/100, + /*expected_bucket_count=*/1); // Validate that only one removal event is received. ASSERT_FALSE(WaitUntilConditionOrTimeout( @@ -518,7 +500,7 @@ // Tests that removing multiple forms and formless fields triggers // 'form_removed" event. -TEST_P(FormMutationTest, RemoveMultipleFormsAndFormlessFields) { +TEST_F(FormMutationTest, RemoveMultipleFormsAndFormlessFields) { // Load html with multiple forms and formless fields. LoadHtmlForMutationTest(@"<div id='div'>" "<form id='form1'>" @@ -545,22 +527,15 @@ const FieldRendererId password_id = FieldRendererId(7); const FieldRendererId text_id = FieldRendererId(8); - if (IsXHRSubmissionDetectionEnabled()) { - EXPECT_THAT(form_removal_params.value().removed_forms, - UnorderedElementsAre(form1_id, form2_id, form3_id)); - EXPECT_THAT(form_removal_params.value().removed_unowned_fields, - UnorderedElementsAre(password_id, text_id)); - - } else { - EXPECT_THAT(form_removal_params.value().removed_forms, - ElementsAre(form1_id)); - EXPECT_THAT(form_removal_params.value().removed_unowned_fields, IsEmpty()); - } + EXPECT_THAT(form_removal_params.value().removed_forms, + UnorderedElementsAre(form1_id, form2_id, form3_id)); + EXPECT_THAT(form_removal_params.value().removed_unowned_fields, + UnorderedElementsAre(password_id, text_id)); } // Tests that removing a form control element and adding a new one in the same // mutations batch is notified with a message for each mutation, sent // back-to-back. -TEST_P(FormMutationTest, RemovedAndAddedFormsRegistered) { +TEST_F(FormMutationTest, RemovedAndAddedFormsRegistered) { // Basic HTML page in which we add a HTML form. NSString* const html = @"<html><body><form id=\"form1\">" "<input type=\"password\"></form></body></html>"; @@ -606,20 +581,20 @@ ValidateParamsAfterFormChangedEvent( observer_->form_activity_info()->form_activity); - histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.DropCount", - /*sample=*/0, - /*expected_bucket_count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendCount", - /*sample=*/2, - /*expected_bucket_count=*/1); - histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendRatio", - /*sample=*/100, - /*expected_bucket_count=*/1); + histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.DropCount", + /*sample=*/0, + /*expected_bucket_count=*/1); + histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendCount", + /*sample=*/2, + /*expected_bucket_count=*/1); + histogram_tester_.ExpectUniqueSample("Autofill.iOS.FormActivity.SendRatio", + /*sample=*/100, + /*expected_bucket_count=*/1); } // Tests that messages that were batched and dropped are correctly recorded as // such. -TEST_P(FormMutationTest, RemovedAndAddedFormsRegistered_WithDroppedMessages) { +TEST_F(FormMutationTest, RemovedAndAddedFormsRegistered_WithDroppedMessages) { // Basic HTML page with 2 password forms and one formless password form. NSString* const html = @"<html><body><form id=\"form1\">" "<input type=\"password\"></form>" @@ -678,7 +653,7 @@ } // Tests that removing input fields triggers the right events. -TEST_P(FormMutationTest, RemoveFormlessFields) { +TEST_F(FormMutationTest, RemoveFormlessFields) { LoadHtmlForMutationTest(@"<body><div id='div'>" "<input type='password' id='password'/>" "<input type='text' id='text'/>" @@ -715,20 +690,14 @@ EXPECT_THAT(form_removal_params.value().removed_forms, IsEmpty()); - if (IsXHRSubmissionDetectionEnabled()) { - EXPECT_THAT(form_removal_params.value().removed_unowned_fields, - UnorderedElementsAre(password_id, text_id, email_id, phone_id, - url_id, number_id, checkbox_id, radio_id, - select_id, textarea_id)); - } else { - EXPECT_THAT(form_removal_params.value().removed_unowned_fields, - ElementsAre(password_id)); - EXPECT_FALSE(observer_->form_activity_info()); - } + EXPECT_THAT(form_removal_params.value().removed_unowned_fields, + UnorderedElementsAre(password_id, text_id, email_id, phone_id, + url_id, number_id, checkbox_id, radio_id, + select_id, textarea_id)); } // Tests that a new form triggers form_changed event. -TEST_P(FormMutationTest, AddForm) { +TEST_F(FormMutationTest, AddForm) { LoadHtmlForMutationTest(@"<body></body>"); web::WebFrame* main_frame = WaitForMainFrame(); @@ -746,13 +715,6 @@ ValidateParamsAfterFormChangedEvent(info->form_activity); } -INSTANTIATE_TEST_SUITE_P( - /* No InstantiationName */, - FormMutationTest, - - ::testing::Bool() // XHR submission detection enabled -); - // Test fixture verifying the behavior of FormActivityTabHelper when handling // mutations involving form control elements. class FormMutationFormControlElements
diff --git a/components/autofill/ios/form_util/form_util_java_script_feature.h b/components/autofill/ios/form_util/form_util_java_script_feature.h index a316d15..122ee6f 100644 --- a/components/autofill/ios/form_util/form_util_java_script_feature.h +++ b/components/autofill/ios/form_util/form_util_java_script_feature.h
@@ -25,9 +25,6 @@ // Enables/disables the AutofillAcrossIframes feature in `frame`. void SetAutofillAcrossIframes(web::WebFrame* frame, bool enabled); - // Enables/disables XHR form submission detection in `frame`. - void SetAutofillXHRSubmissionDetection(web::WebFrame* frame, bool enabled); - // Enables/disables the renderer side behaviours in `frame` needed for // Autofill features to work in an isolated content world. void SetAutofillIsolatedContentWorld(web::WebFrame* frame, bool enabled);
diff --git a/components/autofill/ios/form_util/form_util_java_script_feature.mm b/components/autofill/ios/form_util/form_util_java_script_feature.mm index 6c2ab780..b919566 100644 --- a/components/autofill/ios/form_util/form_util_java_script_feature.mm +++ b/components/autofill/ios/form_util/form_util_java_script_feature.mm
@@ -53,14 +53,6 @@ base::Value::List().Append(enabled)); } -void FormUtilJavaScriptFeature::SetAutofillXHRSubmissionDetection( - web::WebFrame* frame, - bool enabled) { - CallJavaScriptFunction( - frame, "autofill_form_features.setAutofillXHRSubmissionDetection", - base::Value::List().Append(enabled)); -} - void FormUtilJavaScriptFeature::SetAutofillIsolatedContentWorld( web::WebFrame* frame, bool enabled) {
diff --git a/components/autofill/ios/form_util/resources/autofill_form_features.ts b/components/autofill/ios/form_util/resources/autofill_form_features.ts index 549d441..716652e 100644 --- a/components/autofill/ios/form_util/resources/autofill_form_features.ts +++ b/components/autofill/ios/form_util/resources/autofill_form_features.ts
@@ -18,14 +18,6 @@ let autofillAcrossIframes: boolean = false; // LINT.ThenChange(//components/autofill/core/common/autofill_features.cc:autofill_across_iframes_ios) -// LINT.IfChange(autofill_xhr_submission_detection_ios) -/** - * Enables sending all form removal events to the browser for submission detection. - * Corresponds to autofill::feature::AutofillEnableXHRSubmissionDetectionIOS. - */ -let autofillXHRSubmissionDetection: boolean = true; -// LINT.ThenChange(//components/autofill/core/common/autofill_features.cc:autofill_xhr_submission_detection_ios) - // LINT.IfChange(autofill_isolated_content_world) /** Enables the logic necessary for Autofill to work from an isolated content world @@ -49,20 +41,6 @@ } /** - * @see autofillXHRSubmissionDetectionEnabled - */ -function setAutofillXHRSubmissionDetection(enabled: boolean): void { - autofillXHRSubmissionDetection = enabled; -} - -/** - * @see autofillXHRSubmissionDetection - */ -function isAutofillXHRSubmissionDetectionEnabled(): boolean { - return autofillXHRSubmissionDetection; -} - -/** * @see autofillIsolatedContentWorld */ function setAutofillIsolatedContentWorld(enabled: boolean): void { @@ -81,8 +59,6 @@ gCrWeb.autofill_form_features = { setAutofillAcrossIframes, isAutofillAcrossIframesEnabled, - setAutofillXHRSubmissionDetection, - isAutofillXHRSubmissionDetectionEnabled, setAutofillIsolatedContentWorld, isAutofillIsolatedContentWorldEnabled, };
diff --git a/components/autofill/ios/form_util/resources/form_handlers.ts b/components/autofill/ios/form_util/resources/form_handlers.ts index c1aa2ef..84e1d7c8 100644 --- a/components/autofill/ios/form_util/resources/form_handlers.ts +++ b/components/autofill/ios/form_util/resources/form_handlers.ts
@@ -83,15 +83,6 @@ } /** - * @param A form element to check. - * @return Whether the element is an input of type password. - */ -function isPasswordField(element: Element): boolean { - return element.tagName === 'INPUT' && - (element as HTMLInputElement).type === 'password'; -} - -/** * Focus, input, change, keyup, blur and reset events for form elements (form * and input elements) are messaged to the main application for broadcast to * WebStateObservers. @@ -321,47 +312,20 @@ } /** - * Finds a password form element, which is defined as a form with - * at least one password element as the immediate child (depth = 1). - * - * For example: <from><input type="password"></form> is considered as a password - * form. - * - * @param elements Array of elements within which to search. - * @return Extracted password form or undefined if there is no - * match. - */ -function findPasswordForm(elements: Element[]): HTMLFormElement|undefined { - return elements.filter(e => e.tagName === 'FORM') - .find( - e => [...(e as HTMLFormElement).elements].some( - isPasswordField)) as HTMLFormElement; -} - -/** * Finds the renderer IDs of the formless input elements in an array of * elements. * * @param elements Array of elements within which to search. - * @return Renderer ids of the formless fields. When XHR submission detection is - * disabled, only returns password fields. + * @return Renderer ids of the formless fields. */ function findFormlessFieldsIds(elements: Element[]): string[] { - const returnAllInputElements = - gCrWeb.autofill_form_features.isAutofillXHRSubmissionDetectionEnabled(); - - - return elements .filter( e => gCrWeb.fill.isAutofillableElement(e) && - !(e as HTMLInputElement).form && - (returnAllInputElements || isPasswordField(e))) + !(e as HTMLInputElement).form) .map(gCrWeb.fill.getUniqueID); } - - /** * Installs a MutationObserver to track form related changes. Waits |delay| * milliseconds before sending a message to browser. A delay is used because @@ -420,27 +384,14 @@ continue; } - // When detecting XHR submissions for Autofill is enabled, all forms are - // sent to the browser to determine if one of them was submitted. Fallback - // to the old behavior that only sends the first removed password form. - let forms: Element[]; - const xhrEnabled = gCrWeb.autofill_form_features - .isAutofillXHRSubmissionDetectionEnabled(); - - if (xhrEnabled) { - forms = removedFormElements.filter(e => e.tagName === 'FORM'); - } else { - const removedPasswordForm = findPasswordForm(removedFormElements); - forms = removedPasswordForm ? [removedPasswordForm] : []; - } + const forms = removedFormElements.filter(e => e.tagName === 'FORM'); const removedFormlessFieldsIds = findFormlessFieldsIds(removedFormElements); const formlessFieldsWereRemoved = removedFormlessFieldsIds.length > 0; - // Send removed forms and unowned field id's in the same message when XHR - // submissions are enabled. - if (forms.length > 0 || (xhrEnabled && formlessFieldsWereRemoved)) { + // Send removed forms and unowned field id's in the same message. + if (forms.length > 0 || formlessFieldsWereRemoved) { // Drop removed form message if there is one scheduled. if (removedFormMessage) { ++formMsgBatchMetadata.dropCount; @@ -453,8 +404,7 @@ 'command': 'form.removal', 'frameID': gCrWeb.message.getFrameId(), 'removedFormIDs': gCrWeb.stringify(filteredFormIDs), - 'removedFieldIDs': - xhrEnabled ? gCrWeb.stringify(removedFormlessFieldsIds) : null, + 'removedFieldIDs': gCrWeb.stringify(removedFormlessFieldsIds), }; continue; }
diff --git a/components/browser_sync/common_controller_builder.cc b/components/browser_sync/common_controller_builder.cc index a0ca47c5..4b02010 100644 --- a/components/browser_sync/common_controller_builder.cc +++ b/components/browser_sync/common_controller_builder.cc
@@ -166,13 +166,11 @@ void CommonControllerBuilder::SetAutofillWebDataService( const scoped_refptr<base::SequencedTaskRunner>& ui_thread, - const scoped_refptr<base::SequencedTaskRunner>& db_thread, const scoped_refptr<autofill::AutofillWebDataService>& web_data_service_on_disk, const scoped_refptr<autofill::AutofillWebDataService>& web_data_service_in_memory) { autofill_web_data_ui_thread_.Set(ui_thread); - autofill_web_data_db_thread_.Set(db_thread); autofill_web_data_service_on_disk_.Set(web_data_service_on_disk); autofill_web_data_service_in_memory_.Set(web_data_service_in_memory); } @@ -331,14 +329,14 @@ std::make_unique<syncer::ForwardingDataTypeControllerDelegate>( device_info_sync_service_.value()->GetControllerDelegate().get()))); - // These features are enabled only if there's a DB thread to post tasks to. - if (autofill_web_data_db_thread_.value()) { + // These features are enabled only if there's a web data service on disk. + if (autofill_web_data_service_on_disk_.value()) { if (!disabled_types.Has(syncer::AUTOFILL)) { // Note: Transport mode is not and will not be supported. controllers.push_back(std::make_unique<DataTypeController>( syncer::AUTOFILL, std::make_unique<syncer::ProxyDataTypeControllerDelegate>( - autofill_web_data_db_thread_.value(), + autofill_web_data_service_on_disk_.value()->GetDBTaskRunner(), base::BindRepeating( &AutocompleteDelegateFromDataService, base::RetainedRef( @@ -352,7 +350,7 @@ controllers.push_back(std::make_unique<syncer::DataTypeController>( syncer::AUTOFILL_PROFILE, std::make_unique<syncer::ProxyDataTypeControllerDelegate>( - autofill_web_data_db_thread_.value(), + autofill_web_data_service_on_disk_.value()->GetDBTaskRunner(), base::BindRepeating( &AutofillProfileDelegateFromDataService, base::RetainedRef( @@ -366,14 +364,14 @@ std::make_unique<autofill::ContactInfoDataTypeController>( /*delegate_for_full_sync_mode=*/ std::make_unique<syncer::ProxyDataTypeControllerDelegate>( - autofill_web_data_db_thread_.value(), + autofill_web_data_service_on_disk_.value()->GetDBTaskRunner(), base::BindRepeating( &ContactInfoDelegateFromDataService, base::RetainedRef( autofill_web_data_service_on_disk_.value()))), /*delegate_for_transport_mode=*/ std::make_unique<syncer::ProxyDataTypeControllerDelegate>( - autofill_web_data_db_thread_.value(), + autofill_web_data_service_on_disk_.value()->GetDBTaskRunner(), base::BindRepeating( &ContactInfoDelegateFromDataService, base::RetainedRef( @@ -758,14 +756,14 @@ type == syncer::AUTOFILL_WALLET_OFFER); auto delegate_for_full_sync_mode = std::make_unique<syncer::ProxyDataTypeControllerDelegate>( - autofill_web_data_db_thread_.value(), + autofill_web_data_service_on_disk_.value()->GetDBTaskRunner(), base::BindRepeating( delegate_from_web_data, base::RetainedRef(autofill_web_data_service_on_disk_.value()))); auto delegate_for_transport_mode = with_transport_mode_support ? std::make_unique<syncer::ProxyDataTypeControllerDelegate>( - autofill_web_data_db_thread_.value(), + autofill_web_data_service_in_memory_.value()->GetDBTaskRunner(), base::BindRepeating( delegate_from_web_data, base::RetainedRef(
diff --git a/components/browser_sync/common_controller_builder.h b/components/browser_sync/common_controller_builder.h index 98c1d6b..d4f91be 100644 --- a/components/browser_sync/common_controller_builder.h +++ b/components/browser_sync/common_controller_builder.h
@@ -125,7 +125,6 @@ // before invoking `Build()`. In some cases it is allowed to inject nullptr. void SetAutofillWebDataService( const scoped_refptr<base::SequencedTaskRunner>& ui_thread, - const scoped_refptr<base::SequencedTaskRunner>& db_thread, const scoped_refptr<autofill::AutofillWebDataService>& web_data_service_on_disk, const scoped_refptr<autofill::AutofillWebDataService>& @@ -258,8 +257,6 @@ SafeOptional<raw_ptr<syncer::UserEventService>> user_event_service_; SafeOptional<scoped_refptr<base::SequencedTaskRunner>> autofill_web_data_ui_thread_; - SafeOptional<scoped_refptr<base::SequencedTaskRunner>> - autofill_web_data_db_thread_; SafeOptional<scoped_refptr<autofill::AutofillWebDataService>> autofill_web_data_service_on_disk_; SafeOptional<scoped_refptr<autofill::AutofillWebDataService>>
diff --git a/components/browsing_data/core/BUILD.gn b/components/browsing_data/core/BUILD.gn index b362eca..928e9fd 100644 --- a/components/browsing_data/core/BUILD.gn +++ b/components/browsing_data/core/BUILD.gn
@@ -92,6 +92,7 @@ "//components/sync:test_support", "//components/sync_preferences:test_support", "//components/version_info:version_info", + "//components/webdata/common", "//net:test_support", "//testing/gtest", ]
diff --git a/components/browsing_data/core/browsing_data_utils_unittest.cc b/components/browsing_data/core/browsing_data_utils_unittest.cc index 2fcff39d..1d49b9d 100644 --- a/components/browsing_data/core/browsing_data_utils_unittest.cc +++ b/components/browsing_data/core/browsing_data_utils_unittest.cc
@@ -21,6 +21,7 @@ #include "components/password_manager/core/browser/password_store/test_password_store.h" #include "components/prefs/pref_service.h" #include "components/sync_preferences/testing_pref_service_syncable.h" +#include "components/webdata/common/web_database_service.h" #include "testing/gtest/include/gtest/gtest.h" namespace browsing_data { @@ -31,7 +32,10 @@ public: FakeWebDataService() : AutofillWebDataService( - base::SingleThreadTaskRunner::GetCurrentDefault(), + base::MakeRefCounted<WebDatabaseService>( + base::FilePath(), + base::SingleThreadTaskRunner::GetCurrentDefault(), + base::SingleThreadTaskRunner::GetCurrentDefault()), base::SingleThreadTaskRunner::GetCurrentDefault()) {} protected:
diff --git a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_page_activation_throttle.cc b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_page_activation_throttle.cc index eb446ac..a71cc55 100644 --- a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_page_activation_throttle.cc +++ b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_page_activation_throttle.cc
@@ -14,9 +14,6 @@ #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_throttle.h" -#include "services/metrics/public/cpp/ukm_builders.h" -#include "services/metrics/public/cpp/ukm_recorder.h" -#include "services/metrics/public/cpp/ukm_source.h" namespace fingerprinting_protection_filter { @@ -89,8 +86,8 @@ // Making sure the WebContentsHelper exists is outside the scope of this // class. if (web_contents_helper) { - web_contents_helper->NotifyPageActivationComputed(navigation_handle(), - activation_state); + web_contents_helper->NotifyPageActivationComputed( + navigation_handle(), activation_state, decision); } LogMetricsOnChecksComplete(decision, activation_level); @@ -102,23 +99,6 @@ UMA_HISTOGRAM_ENUMERATION(ActivationLevelHistogramName, level); UMA_HISTOGRAM_ENUMERATION(ActivationDecisionHistogramName, decision, ActivationDecision::ACTIVATION_DECISION_MAX); - - ukm::SourceId source_id = ukm::ConvertToSourceId( - navigation_handle()->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID); - ukm::builders::FingerprintingProtection builder(source_id); - - builder.SetActivationDecision(static_cast<int64_t>(decision)); - if (level == ActivationLevel::kDryRun) { - DCHECK_EQ(ActivationDecision::ACTIVATED, decision); - builder.SetDryRun(true); - } - if (decision == ActivationDecision::URL_ALLOWLISTED && - profile_interaction_manager_) { - builder.SetAllowlistSource(static_cast<int64_t>( - profile_interaction_manager_->GetTrackingProtectionSettingSource( - navigation_handle()->GetURL()))); - } - builder.Record(ukm::UkmRecorder::Get()); } } // namespace fingerprinting_protection_filter
diff --git a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_page_activation_throttle_unittest.cc b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_page_activation_throttle_unittest.cc index 06e87d3..6d13a8d 100644 --- a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_page_activation_throttle_unittest.cc +++ b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_page_activation_throttle_unittest.cc
@@ -20,13 +20,10 @@ #include "components/subresource_filter/core/common/activation_decision.h" #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" #include "components/sync_preferences/testing_pref_service_syncable.h" -#include "components/ukm/content/source_url_recorder.h" -#include "components/ukm/test_ukm_recorder.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/web_contents.h" #include "content/public/test/mock_navigation_handle.h" #include "content/public/test/test_renderer_host.h" -#include "services/metrics/public/cpp/ukm_builders.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" @@ -115,10 +112,6 @@ FlagDisabled_IsUnknown) { base::HistogramTester histograms; - ukm::InitializeSourceUrlRecorderForWebContents( - mock_nav_handle_->GetWebContents()); - ukm::TestAutoSetUkmRecorder test_ukm_recorder; - // Disable the feature. scoped_feature_list_.InitAndDisableFeature( features::kEnableFingerprintingProtectionFilter); @@ -146,17 +139,12 @@ // Expect no histograms are emitted when the feature flag is disabled. histograms.ExpectTotalCount(ActivationDecisionHistogramName, 0); histograms.ExpectTotalCount(ActivationLevelHistogramName, 0); - - EXPECT_EQ(0u, test_ukm_recorder.entries_count()); } TEST_F(FingerprintingProtectionPageActivationThrottleTest, FlagEnabledDefaultActivatedParams_IsActivated) { base::HistogramTester histograms; - ukm::InitializeSourceUrlRecorderForWebContents( - mock_nav_handle_->GetWebContents()); - ukm::TestAutoSetUkmRecorder test_ukm_recorder; // Enable the feature with default params, i.e. activation_level = enabled. scoped_feature_list_.InitWithFeatures( {features::kEnableFingerprintingProtectionFilter}, {}); @@ -187,30 +175,12 @@ histograms.ExpectBucketCount( ActivationLevelHistogramName, subresource_filter::mojom::ActivationLevel::kEnabled, 1); - - const auto& entries = test_ukm_recorder.GetEntriesByName( - ukm::builders::FingerprintingProtection::kEntryName); - EXPECT_EQ(1u, test_ukm_recorder.entries_count()); - for (const ukm::mojom::UkmEntry* entry : entries) { - test_ukm_recorder.ExpectEntryMetric( - entry, ukm::builders::FingerprintingProtection::kActivationDecisionName, - static_cast<int64_t>( - subresource_filter::ActivationDecision::ACTIVATED)); - EXPECT_FALSE(test_ukm_recorder.EntryHasMetric( - entry, ukm::builders::FingerprintingProtection::kDryRunName)); - EXPECT_FALSE(test_ukm_recorder.EntryHasMetric( - entry, ukm::builders::FingerprintingProtection::kAllowlistSourceName)); - } } TEST_F(FingerprintingProtectionPageActivationThrottleTest, FlagEnabledWithDryRun_IsActivated) { base::HistogramTester histograms; - ukm::InitializeSourceUrlRecorderForWebContents( - mock_nav_handle_->GetWebContents()); - ukm::TestAutoSetUkmRecorder test_ukm_recorder; - // Enable the feature with dry_run params: activation_level = dry_run. scoped_feature_list_.InitWithFeaturesAndParameters( {{features::kEnableFingerprintingProtectionFilter, @@ -243,30 +213,12 @@ histograms.ExpectBucketCount( ActivationLevelHistogramName, subresource_filter::mojom::ActivationLevel::kDryRun, 1); - - const auto& entries = test_ukm_recorder.GetEntriesByName( - ukm::builders::FingerprintingProtection::kEntryName); - EXPECT_EQ(1u, test_ukm_recorder.entries_count()); - for (const ukm::mojom::UkmEntry* entry : entries) { - test_ukm_recorder.ExpectEntryMetric( - entry, ukm::builders::FingerprintingProtection::kActivationDecisionName, - static_cast<int64_t>( - subresource_filter::ActivationDecision::ACTIVATED)); - test_ukm_recorder.ExpectEntryMetric( - entry, ukm::builders::FingerprintingProtection::kDryRunName, true); - EXPECT_FALSE(test_ukm_recorder.EntryHasMetric( - entry, ukm::builders::FingerprintingProtection::kAllowlistSourceName)); - } } TEST_F(FingerprintingProtectionPageActivationThrottleTest, FlagEnabledWithAllSitesDisabledParams_IsDisabled) { base::HistogramTester histograms; - ukm::InitializeSourceUrlRecorderForWebContents( - mock_nav_handle_->GetWebContents()); - ukm::TestAutoSetUkmRecorder test_ukm_recorder; - // Enable the feature with disabling params, i.e. activation_level = disabled. scoped_feature_list_.InitWithFeaturesAndParameters( {{features::kEnableFingerprintingProtectionFilter, @@ -303,30 +255,12 @@ histograms.ExpectBucketCount( ActivationLevelHistogramName, subresource_filter::mojom::ActivationLevel::kDisabled, 1); - - const auto& entries = test_ukm_recorder.GetEntriesByName( - ukm::builders::FingerprintingProtection::kEntryName); - EXPECT_EQ(1u, test_ukm_recorder.entries_count()); - for (const ukm::mojom::UkmEntry* entry : entries) { - test_ukm_recorder.ExpectEntryMetric( - entry, ukm::builders::FingerprintingProtection::kActivationDecisionName, - static_cast<int64_t>( - subresource_filter::ActivationDecision::ACTIVATION_DISABLED)); - EXPECT_FALSE(test_ukm_recorder.EntryHasMetric( - entry, ukm::builders::FingerprintingProtection::kDryRunName)); - EXPECT_FALSE(test_ukm_recorder.EntryHasMetric( - entry, ukm::builders::FingerprintingProtection::kAllowlistSourceName)); - } } TEST_F(FingerprintingProtectionPageActivationThrottleTest, FlagEnabledDefaultActivatedParams_IsAllowlisted) { base::HistogramTester histograms; - ukm::InitializeSourceUrlRecorderForWebContents( - mock_nav_handle_->GetWebContents()); - ukm::TestAutoSetUkmRecorder test_ukm_recorder; - // Enable the feature with disabling params, i.e. activation_level = disabled. scoped_feature_list_.InitAndEnableFeature( features::kEnableFingerprintingProtectionFilter); @@ -349,21 +283,6 @@ histograms.ExpectBucketCount( ActivationLevelHistogramName, subresource_filter::mojom::ActivationLevel::kDisabled, 1); - - const auto& entries = test_ukm_recorder.GetEntriesByName( - ukm::builders::FingerprintingProtection::kEntryName); - EXPECT_EQ(1u, test_ukm_recorder.entries_count()); - for (const ukm::mojom::UkmEntry* entry : entries) { - test_ukm_recorder.ExpectEntryMetric( - entry, ukm::builders::FingerprintingProtection::kActivationDecisionName, - static_cast<int64_t>( - subresource_filter::ActivationDecision::URL_ALLOWLISTED)); - EXPECT_FALSE(test_ukm_recorder.EntryHasMetric( - entry, ukm::builders::FingerprintingProtection::kDryRunName)); - test_ukm_recorder.ExpectEntryMetric( - entry, ukm::builders::FingerprintingProtection::kAllowlistSourceName, - static_cast<int64_t>(content_settings::SettingSource::kUser)); - } } } // namespace fingerprinting_protection_filter
diff --git a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_web_contents_helper.cc b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_web_contents_helper.cc index 87d75d7..db92f851 100644 --- a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_web_contents_helper.cc +++ b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_web_contents_helper.cc
@@ -13,6 +13,7 @@ #include "components/privacy_sandbox/tracking_protection_settings.h" #include "components/subresource_filter/content/shared/common/subresource_filter_utils.h" #include "components/subresource_filter/core/browser/verified_ruleset_dealer.h" +#include "components/subresource_filter/core/common/load_policy.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_handle_user_data.h" #include "content/public/browser/web_contents.h" @@ -176,11 +177,12 @@ void FingerprintingProtectionWebContentsHelper::NotifyPageActivationComputed( content::NavigationHandle* navigation_handle, - const subresource_filter::mojom::ActivationState& activation_state) { + const subresource_filter::mojom::ActivationState& activation_state, + const subresource_filter::ActivationDecision& activation_decision) { if (ThrottleManager* throttle_manager = GetThrottleManager(*navigation_handle)) { - throttle_manager->OnPageActivationComputed(navigation_handle, - activation_state); + throttle_manager->OnPageActivationComputed( + navigation_handle, activation_state, activation_decision); } } @@ -190,6 +192,13 @@ subresource_filter::LoadPolicy load_policy) { // TODO(https://crbug.com/40280666): Notify throttle manager after blink // communication is implemented. + if (load_policy == subresource_filter::LoadPolicy::WOULD_DISALLOW || + load_policy == subresource_filter::LoadPolicy::DISALLOW) { + if (ThrottleManager* throttle_manager = + GetThrottleManager(*navigation_handle)) { + throttle_manager->NotifyDisallowLoadPolicy(navigation_handle); + } + } } void FingerprintingProtectionWebContentsHelper::FrameDeleted(
diff --git a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_web_contents_helper.h b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_web_contents_helper.h index 96e81b8..583a611 100644 --- a/components/fingerprinting_protection_filter/browser/fingerprinting_protection_web_contents_helper.h +++ b/components/fingerprinting_protection_filter/browser/fingerprinting_protection_web_contents_helper.h
@@ -28,6 +28,7 @@ namespace mojom { class ActivationState; } // namespace mojom +enum class ActivationDecision; enum class LoadPolicy; } // namespace subresource_filter @@ -70,7 +71,8 @@ // throttles created in MaybeAppendNavigationThrottles(). void NotifyPageActivationComputed( content::NavigationHandle* navigation_handle, - const subresource_filter::mojom::ActivationState& activation_state); + const subresource_filter::mojom::ActivationState& activation_state, + const subresource_filter::ActivationDecision& activation_decision); // Called in WillStartRequest or WillRedirectRequest stage from a // ChildFrameNavigationFilteringThrottle.
diff --git a/components/fingerprinting_protection_filter/browser/throttle_manager.cc b/components/fingerprinting_protection_filter/browser/throttle_manager.cc index 9007757..faa83201 100644 --- a/components/fingerprinting_protection_filter/browser/throttle_manager.cc +++ b/components/fingerprinting_protection_filter/browser/throttle_manager.cc
@@ -33,7 +33,9 @@ #include "content/public/browser/page.h" #include "content/public/browser/render_frame_host.h" #include "net/base/net_errors.h" -#include "url/gurl.h" +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_recorder.h" +#include "services/metrics/public/cpp/ukm_source.h" namespace fingerprinting_protection_filter { namespace { @@ -270,10 +272,13 @@ // activation for that page load. void ThrottleManager::OnPageActivationComputed( content::NavigationHandle* navigation_handle, - const subresource_filter::mojom::ActivationState& activation_state) { + const subresource_filter::mojom::ActivationState& activation_state, + const subresource_filter::ActivationDecision& activation_decision) { CHECK(IsInSubresourceFilterRoot(navigation_handle)); CHECK(!navigation_handle->HasCommitted()); + page_activation_decision_ = activation_decision; + ChildActivationThrottleHandle* throttle_handle = ChildActivationThrottleHandle::GetForNavigationHandle(*navigation_handle); if (!throttle_handle) { @@ -320,6 +325,28 @@ return std::nullopt; } +void ThrottleManager::LogActivationDecisionUkm( + content::NavigationHandle* navigation_handle) { + ukm::SourceId source_id = navigation_handle->GetNextPageUkmSourceId(); + ukm::builders::FingerprintingProtection builder(source_id); + + FilterHandle* filter_handle = + FilterHandle::GetForCurrentDocument(&page_->GetMainDocument()); + if (!filter_handle) { + // Without any active filtering, no need to emit ukm. + return; + } + if (filter_handle->filter()->activation_state().activation_level == + subresource_filter::mojom::ActivationLevel::kDryRun) { + DCHECK_EQ(subresource_filter::ActivationDecision::ACTIVATED, + page_activation_decision_); + builder.SetDryRun(true); + } + builder.SetActivationDecision( + static_cast<int64_t>(page_activation_decision_)); + builder.Record(ukm::UkmRecorder::Get()); +} + void ThrottleManager::MaybeNotifyOnBlockedResource( content::RenderFrameHost* frame_host) { CHECK(page_); @@ -332,8 +359,14 @@ FilterHandle* filter_handle = FilterHandle::GetForCurrentDocument(&page_->GetMainDocument()); if (!filter_handle || - filter_handle->filter()->activation_state().activation_level != - subresource_filter::mojom::ActivationLevel::kEnabled) { + filter_handle->filter()->activation_state().activation_level == + subresource_filter::mojom::ActivationLevel::kDisabled) { + return; + } + + if (!filter_handle || + filter_handle->filter()->activation_state().activation_level == + subresource_filter::mojom::ActivationLevel::kDryRun) { return; } @@ -347,6 +380,11 @@ } } +void ThrottleManager::NotifyDisallowLoadPolicy( + content::NavigationHandle* navigation_handle) { + LogActivationDecisionUkm(navigation_handle); +} + subresource_filter::mojom::ActivationState ThrottleManager::ActivationStateForNextCommittedLoad( content::NavigationHandle* navigation_handle) {
diff --git a/components/fingerprinting_protection_filter/browser/throttle_manager.h b/components/fingerprinting_protection_filter/browser/throttle_manager.h index da6b138d..a6298c1 100644 --- a/components/fingerprinting_protection_filter/browser/throttle_manager.h +++ b/components/fingerprinting_protection_filter/browser/throttle_manager.h
@@ -17,6 +17,7 @@ #include "base/supports_user_data.h" #include "components/subresource_filter/content/shared/browser/page_load_statistics.h" #include "components/subresource_filter/core/browser/verified_ruleset_dealer.h" +#include "components/subresource_filter/core/common/activation_decision.h" #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" #include "content/public/browser/document_user_data.h" #include "content/public/browser/navigation_handle_user_data.h" @@ -31,7 +32,6 @@ } // namespace content namespace subresource_filter { -enum class ActivationDecision; class AsyncDocumentSubresourceFilter; class ActivationStateComputingNavigationThrottle; @@ -125,6 +125,8 @@ return ruleset_handle_.get(); } + void NotifyDisallowLoadPolicy(content::NavigationHandle* navigation_handle); + protected: FRIEND_TEST_ALL_PREFIXES( ThrottleManagerEnabledTest, @@ -155,11 +157,14 @@ // Similar to above, called from the WebContentsHelper. void OnPageActivationComputed( content::NavigationHandle* navigation_handle, - const subresource_filter::mojom::ActivationState& activation_state); + const subresource_filter::mojom::ActivationState& activation_state, + const subresource_filter::ActivationDecision& activation_decision); private: friend FingerprintingProtectionWebContentsHelper; + void LogActivationDecisionUkm(content::NavigationHandle* navigation_handle); + // Keeps track of a filter that is associated with a document that already // has its activation computed. class FilterHandle : public content::DocumentUserData<FilterHandle> { @@ -287,6 +292,11 @@ // TODO(https://crbug.com/40280666): Triage dangling pointers. raw_ptr<content::Page, DanglingUntriaged> page_ = nullptr; + // One ThrottleManger per page means one page activation decision per throttle + // manager. + subresource_filter::ActivationDecision page_activation_decision_ = + subresource_filter::ActivationDecision::UNKNOWN; + // The helper class is attached to the WebContents so it is guaranteed to // outlive this class which is owned by either a Page or NavigationHandle in // the WebContents.
diff --git a/components/fingerprinting_protection_filter/browser/throttle_manager_unittest.cc b/components/fingerprinting_protection_filter/browser/throttle_manager_unittest.cc index ed9b2a9..31ef81bc 100644 --- a/components/fingerprinting_protection_filter/browser/throttle_manager_unittest.cc +++ b/components/fingerprinting_protection_filter/browser/throttle_manager_unittest.cc
@@ -23,6 +23,7 @@ #include "components/subresource_filter/core/common/test_ruleset_creator.h" #include "components/subresource_filter/core/common/test_ruleset_utils.h" #include "components/subresource_filter/core/mojom/subresource_filter.mojom.h" +#include "components/ukm/test_ukm_recorder.h" #include "components/url_pattern_index/proto/rules.pb.h" #include "content/public/browser/navigation_handle.h" #include "content/public/browser/navigation_throttle.h" @@ -34,9 +35,14 @@ #include "content/public/test/navigation_simulator.h" #include "content/public/test/test_renderer_host.h" #include "content/public/test/test_utils.h" +#include "services/metrics/public/cpp/ukm_builders.h" #include "testing/gtest/include/gtest/gtest.h" #include "url/gurl.h" +namespace subresource_filter { +enum class ActivationDecision; +} + namespace fingerprinting_protection_filter { namespace { @@ -119,8 +125,9 @@ FingerprintingProtectionWebContentsHelper::FromWebContents( navigation_handle()->GetWebContents()); if (web_contents_helper) { - web_contents_helper->NotifyPageActivationComputed(navigation_handle(), - it->second); + web_contents_helper->NotifyPageActivationComputed( + navigation_handle(), it->second, + subresource_filter::ActivationDecision::ACTIVATED); } } } @@ -388,6 +395,9 @@ TEST_P(ThrottleManagerEnabledTest, ActivateMainFrameAndFilterSubframeNavigation) { + // Set up test ukm recorder. + ukm::TestAutoSetUkmRecorder test_ukm_recorder; + // Commit a navigation that triggers page level activation. NavigateAndCommitMainFrame(GURL(kTestURLWithActivation)); @@ -396,9 +406,25 @@ GURL("https://www.example.com/disallowed.html"), main_rfh()); EXPECT_EQ(content::NavigationThrottle::BLOCK_REQUEST_AND_COLLAPSE, SimulateStartAndGetResult(navigation_simulator()).action()); + + // Check test ukm recorder contains event with expected metrics. + const auto& entries = test_ukm_recorder.GetEntriesByName( + ukm::builders::FingerprintingProtection::kEntryName); + EXPECT_EQ(1u, entries.size()); + for (const ukm::mojom::UkmEntry* entry : entries) { + test_ukm_recorder.ExpectEntryMetric( + entry, ukm::builders::FingerprintingProtection::kActivationDecisionName, + static_cast<int64_t>( + subresource_filter::ActivationDecision::ACTIVATED)); + EXPECT_FALSE(test_ukm_recorder.EntryHasMetric( + entry, ukm::builders::FingerprintingProtection::kDryRunName)); + } } TEST_P(ThrottleManagerEnabledTest, NoPageActivation) { + // Set up test ukm recorder. + ukm::TestAutoSetUkmRecorder test_ukm_recorder; + // Commit a navigation that does not trigger page level activation. NavigateAndCommitMainFrame(GURL(kTestURLWithNoActivation)); EXPECT_TRUE(ManagerHasRulesetHandle()); @@ -408,6 +434,11 @@ GURL("https://www.example.com/disallowed.html"), main_rfh()); EXPECT_EQ(content::NavigationThrottle::PROCEED, SimulateCommitAndGetResult(navigation_simulator()).action()); + + EXPECT_EQ(0u, test_ukm_recorder + .GetEntriesByName( + ukm::builders::FingerprintingProtection::kEntryName) + .size()); } // TODO(https://crbug.com/40280666): Dry run mode is not yet implemented and
diff --git a/components/ip_protection/BUILD.gn b/components/ip_protection/BUILD.gn index 40b65a0..a8dc152 100644 --- a/components/ip_protection/BUILD.gn +++ b/components/ip_protection/BUILD.gn
@@ -9,6 +9,10 @@ # should be safe to include in most builds. source_set("ip_protection") { sources = [ + "common/ip_protection_data_types.h", + "common/ip_protection_telemetry.h", + "common/ip_protection_telemetry_uma.cc", + "common/ip_protection_telemetry_uma.h", "common/masked_domain_list_manager.cc", "common/masked_domain_list_manager.h", "common/url_matcher_with_bypass.cc", @@ -54,6 +58,7 @@ deps = [ ":get_proxy_config_proto", + ":ip_protection", "//base", "//build:branding_buildflags", "//components/privacy_sandbox/masked_domain_list:masked_domain_list_proto",
diff --git a/components/ip_protection/common/ip_protection_config_provider_helper.cc b/components/ip_protection/common/ip_protection_config_provider_helper.cc index 3a6ba8b6..000b0d3 100644 --- a/components/ip_protection/common/ip_protection_config_provider_helper.cc +++ b/components/ip_protection/common/ip_protection_config_provider_helper.cc
@@ -12,6 +12,7 @@ #include "base/logging.h" #include "base/strings/strcat.h" #include "base/time/time.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "net/base/features.h" #include "net/base/proxy_string_util.h" #include "net/third_party/quiche/src/quiche/blind_sign_auth/blind_sign_auth.h" @@ -23,7 +24,7 @@ namespace ip_protection { // static -std::optional<network::BlindSignedAuthToken> +std::optional<ip_protection::BlindSignedAuthToken> IpProtectionConfigProviderHelper::CreateBlindSignedAuthToken( const quiche::BlindSignToken& bsa_token) { // If a GeoHint's country code is empty, the token is invalid. Return a @@ -48,13 +49,13 @@ } // Set GeoHint on BlindSignedAuthToken. - network::GeoHint geo_hint = { + ip_protection::GeoHint geo_hint = { .country_code = bsa_token.geo_hint.country_code, .iso_region = bsa_token.geo_hint.region, .city_name = bsa_token.geo_hint.city, }; - return std::make_optional<network::BlindSignedAuthToken>( + return std::make_optional<ip_protection::BlindSignedAuthToken>( {.token = std::move(token_header_value), .expiration = expiration, .geo_hint = std::move(geo_hint)}); @@ -83,7 +84,7 @@ IpProtectionConfigProviderHelper::CreateBlindSignTokenForTesting( std::string token_value, base::Time expiration, - const network::GeoHint& geo_hint) { + const ip_protection::GeoHint& geo_hint) { privacy::ppn::PrivacyPassTokenData privacy_pass_token_data = CreatePrivacyPassTokenForTesting(std::move(token_value)); // IN-TEST quiche::BlindSignToken blind_sign_token; @@ -103,11 +104,11 @@ return blind_sign_token; } -std::optional<network::BlindSignedAuthToken> +std::optional<ip_protection::BlindSignedAuthToken> IpProtectionConfigProviderHelper::CreateMockBlindSignedAuthTokenForTesting( std::string token_value, base::Time expiration, - const network::GeoHint& geo_hint) { + const ip_protection::GeoHint& geo_hint) { quiche::BlindSignToken blind_sign_token = CreateBlindSignTokenForTesting( token_value, expiration, geo_hint); // IN-TEST return CreateBlindSignedAuthToken(std::move(blind_sign_token));
diff --git a/components/ip_protection/common/ip_protection_config_provider_helper.h b/components/ip_protection/common/ip_protection_config_provider_helper.h index 89b3980..c646b72 100644 --- a/components/ip_protection/common/ip_protection_config_provider_helper.h +++ b/components/ip_protection/common/ip_protection_config_provider_helper.h
@@ -10,6 +10,7 @@ #include <vector> #include "base/time/time.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "components/ip_protection/get_proxy_config.pb.h" #include "net/third_party/quiche/src/quiche/blind_sign_auth/proto/spend_token_data.pb.h" #include "services/network/public/mojom/network_context.mojom.h" @@ -33,9 +34,8 @@ virtual ~IpProtectionConfigProviderHelper() = default; // Creates a blind-signed auth token by converting token fetched using the - // `quiche::BlindSignAuth` library to a - // `network::BlindSignedAuthToken`. - static std::optional<network::BlindSignedAuthToken> + // `quiche::BlindSignAuth` library to a `ip_protection::BlindSignedAuthToken`. + static std::optional<ip_protection::BlindSignedAuthToken> CreateBlindSignedAuthToken(const quiche::BlindSignToken& bsa_token); // Creates a `quiche::BlindSignToken()` in the format that the BSA library @@ -43,17 +43,18 @@ static quiche::BlindSignToken CreateBlindSignTokenForTesting( std::string token_value, base::Time expiration, - const network::GeoHint& geo_hint); + const ip_protection::GeoHint& geo_hint); static privacy::ppn::PrivacyPassTokenData CreatePrivacyPassTokenForTesting( std::string token_value); // Converts a mock token value and expiration time into the struct that will // be passed to the network service. - static std::optional<network::BlindSignedAuthToken> - CreateMockBlindSignedAuthTokenForTesting(std::string token_value, - base::Time expiration, - const network::GeoHint& geo_hint); + static std::optional<ip_protection::BlindSignedAuthToken> + CreateMockBlindSignedAuthTokenForTesting( + std::string token_value, + base::Time expiration, + const ip_protection::GeoHint& geo_hint); // Service types used for GetProxyConfigRequest. static constexpr char kChromeIpBlinding[] = "chromeipblinding";
diff --git a/components/ip_protection/common/ip_protection_data_types.h b/components/ip_protection/common/ip_protection_data_types.h new file mode 100644 index 0000000..86e7b3e1 --- /dev/null +++ b/components/ip_protection/common/ip_protection_data_types.h
@@ -0,0 +1,109 @@ +// Copyright 2024 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_IP_PROTECTION_COMMON_IP_PROTECTION_DATA_TYPES_H_ +#define COMPONENTS_IP_PROTECTION_COMMON_IP_PROTECTION_DATA_TYPES_H_ + +#include "base/time/time.h" + +namespace ip_protection { + +// The result of a fetch of tokens from the IP Protection auth token server. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. Keep this in sync with +// IpProtectionTokenBatchRequestResult in enums.xml. +enum class TryGetAuthTokensResult { + // The request was successful and resulted in new tokens. + kSuccess = 0, + // No primary account is set. + kFailedNoAccount = 1, + // Chrome determined the primary account is not eligible. + kFailedNotEligible = 2, + // There was a failure fetching an OAuth token for the primary account. + // Deprecated in favor of `kFailedOAuthToken{Transient,Persistent}`. + kFailedOAuthTokenDeprecated = 3, + // There was a failure in BSA with the given status code. + kFailedBSA400 = 4, + kFailedBSA401 = 5, + kFailedBSA403 = 6, + + // Any other issue calling BSA. + kFailedBSAOther = 7, + + // There was a transient failure fetching an OAuth token for the primary + // account. + kFailedOAuthTokenTransient = 8, + // There was a persistent failure fetching an OAuth token for the primary + // account. + kFailedOAuthTokenPersistent = 9, + + // The attempt to request tokens failed because IP Protection was disabled by + // the user. + kFailedDisabledByUser = 10, + + kMaxValue = kFailedDisabledByUser, +}; + +// The result of a fetch of tokens from the IP Protection auth token server on +// Android. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. Keep this in sync with +// AwIpProtectionTokenBatchRequestResult in enums.xml. +enum class TryGetAuthTokensAndroidResult { + // The request was successful and resulted in new tokens. + kSuccess = 0, + // A transient error, implies that retrying the action (with backoff) is + // appropriate. + kFailedBSATransient = 1, + // A persistent error, implies that the action should not be retried. + kFailedBSAPersistent = 2, + // Any other issue calling BSA. + kFailedBSAOther = 3, + // The attempt to request tokens failed because IP Protection is disabled by + // WebView. + kFailedDisabled = 4, + + kMaxValue = kFailedDisabled, +}; + +// A GeoHint represents a course location of a user. Values are based on +// RFC 8805 geolocation. +struct GeoHint { + // Country code of the geo. Example: "US". + std::string country_code; + + // ISO region of the geo. Example: "US-CA". + std::string iso_region; + + // City name of the geo. Example: "MOUNTAIN VIEW". + std::string city_name; + + bool operator==(const GeoHint& geo_hint) const = default; +}; + +// A blind-signed auth token, suitable for use with IP protection proxies. +struct BlindSignedAuthToken { + // The token value, for inclusion in a header. + std::string token; + + // The expiration time of this token. + base::Time expiration; + + // The GeoHint which specifies the coarse geolocation of the token. + GeoHint geo_hint; + + bool operator==(const BlindSignedAuthToken& token) const = default; +}; + +// The proxy layer to fetch batches of tokens for. +// +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +enum class ProxyLayer { kProxyA = 0, kProxyB = 1, kMaxValue = kProxyB }; + +} // namespace ip_protection + +#endif // COMPONENTS_IP_PROTECTION_COMMON_IP_PROTECTION_DATA_TYPES_H_
diff --git a/components/ip_protection/common/ip_protection_proxy_config_fetcher.cc b/components/ip_protection/common/ip_protection_proxy_config_fetcher.cc index d35a635b..ac285fd 100644 --- a/components/ip_protection/common/ip_protection_proxy_config_fetcher.cc +++ b/components/ip_protection/common/ip_protection_proxy_config_fetcher.cc
@@ -75,7 +75,7 @@ std::vector<net::ProxyChain> proxy_list = GetProxyListFromProxyConfigResponse(response.value()); - std::optional<network::GeoHint> geo_hint = + std::optional<ip_protection::GeoHint> geo_hint = GetGeoHintFromProxyConfigResponse(response.value()); std::move(callback).Run(std::move(proxy_list), std::move(geo_hint)); } @@ -155,14 +155,14 @@ return proxy_list; } -std::optional<network::GeoHint> +std::optional<ip_protection::GeoHint> IpProtectionProxyConfigFetcher::GetGeoHintFromProxyConfigResponse( ip_protection::GetProxyConfigResponse& response) { if (!response.has_geo_hint()) { return std::nullopt; // No GeoHint available in the response. } - return std::make_optional<network::GeoHint>( + return std::make_optional<ip_protection::GeoHint>( {.country_code = response.geo_hint().country_code(), .iso_region = response.geo_hint().iso_region(), .city_name = response.geo_hint().city_name()});
diff --git a/components/ip_protection/common/ip_protection_proxy_config_fetcher.h b/components/ip_protection/common/ip_protection_proxy_config_fetcher.h index 4df7ac0..6529349 100644 --- a/components/ip_protection/common/ip_protection_proxy_config_fetcher.h +++ b/components/ip_protection/common/ip_protection_proxy_config_fetcher.h
@@ -12,8 +12,9 @@ #include "base/functional/callback.h" #include "base/memory/scoped_refptr.h" #include "base/time/time.h" -#include "components/ip_protection/get_proxy_config.pb.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "components/ip_protection/common/ip_protection_proxy_config_retriever.h" +#include "components/ip_protection/get_proxy_config.pb.h" #include "net/base/proxy_chain.h" #include "services/network/public/cpp/shared_url_loader_factory.h" #include "services/network/public/mojom/network_context.mojom.h" @@ -30,7 +31,7 @@ public: using GetProxyListCallback = base::OnceCallback<void( const std::optional<std::vector<::net::ProxyChain>>&, - const std::optional<network::GeoHint>&)>; + const std::optional<ip_protection::GeoHint>&)>; explicit IpProtectionProxyConfigFetcher( scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, @@ -86,7 +87,7 @@ // Creates a GeoHint by converting the GeoHint from the // `GetProxyConfigResponse` to a `network::GeoHint`. - std::optional<network::GeoHint> GetGeoHintFromProxyConfigResponse( + std::optional<ip_protection::GeoHint> GetGeoHintFromProxyConfigResponse( ip_protection::GetProxyConfigResponse& response); std::unique_ptr<IpProtectionProxyConfigRetriever>
diff --git a/components/ip_protection/common/ip_protection_proxy_config_fetcher_unittest.cc b/components/ip_protection/common/ip_protection_proxy_config_fetcher_unittest.cc index e604e984..b7a355e 100644 --- a/components/ip_protection/common/ip_protection_proxy_config_fetcher_unittest.cc +++ b/components/ip_protection/common/ip_protection_proxy_config_fetcher_unittest.cc
@@ -14,6 +14,7 @@ #include "base/time/time.h" #include "base/types/expected.h" #include "components/ip_protection/common/ip_protection_config_provider_helper.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "services/network/test/test_shared_url_loader_factory.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -83,11 +84,11 @@ base::test::TaskEnvironment task_environment_; std::unique_ptr<IpProtectionProxyConfigFetcher> fetcher_; base::test::TestFuture<const std::optional<std::vector<net::ProxyChain>>&, - const std::optional<network::GeoHint>&> + const std::optional<ip_protection::GeoHint>&> proxy_list_future_; // A convenient geo hint for fake tokens. - network::GeoHint geo_hint_; + ip_protection::GeoHint geo_hint_; }; TEST_F(IpProtectionProxyConfigFetcherTest, CallGetProxyConfigProxyChains) { @@ -279,7 +280,7 @@ 2)}; // Country level geo only. - network::GeoHint exp_geo_hint; + ip_protection::GeoHint exp_geo_hint; exp_geo_hint.country_code = "US"; // Extract tuple elements for individual comparison.
diff --git a/components/ip_protection/common/ip_protection_telemetry.h b/components/ip_protection/common/ip_protection_telemetry.h new file mode 100644 index 0000000..6263b7d --- /dev/null +++ b/components/ip_protection/common/ip_protection_telemetry.h
@@ -0,0 +1,145 @@ +// Copyright 2024 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_IP_PROTECTION_COMMON_IP_PROTECTION_TELEMETRY_H_ +#define COMPONENTS_IP_PROTECTION_COMMON_IP_PROTECTION_TELEMETRY_H_ + +#include <optional> + +#include "base/time/time.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "net/base/proxy_chain.h" + +namespace ip_protection { + +// An enumeration of the eligibility finding for use with +// `UmaHistogramEnumeration`. These values are persisted to logs. Entries should +// not be renumbered and numeric values should never be reused. +enum class ProtectionEligibility { + kUnknown = 0, + kIneligible = 1, + kEligible = 2, + kMaxValue = kEligible, +}; + +// An enumeration of the result of an attempt to fetch a proxy list. These +// values are persisted to logs. Entries should not be renumbered and numeric +// values should never be reused. +enum class GetProxyListResult { + kFailed = 0, + kEmptyList = 1, + kPopulatedList = 2, + kMaxValue = kPopulatedList, +}; + +// These values are persisted to logs. Entries should not be renumbered and +// numeric values should never be reused. +// +// LINT.IfChange(AuthTokenResultForGeo) +enum class AuthTokenResultForGeo { + kUnavailableCacheEmpty = 0, + kUnavailableButCacheContainsTokens = 1, + kAvailableForCurrentGeo = 2, + kAvailableForOtherCachedGeo = 3, + kMaxValue = kAvailableForOtherCachedGeo, +}; +// LINT.ThenChange(//tools/metrics/histograms/metadata/network/enums.xml:IpProtectionGetAuthTokenResultForGeo) + +// An abstract interface for all of the telemetry associated with IP Protection. +// +// This is implemented by each telemetry platform, and a singleton made +// available on a per-process basis. +// +// More detail on the metrics produced here can be found in +// `tools/metrics/histograms/metadata/network/histograms.xml`. +class IpProtectionTelemetry { + public: + virtual ~IpProtectionTelemetry() = default; + + // Methods to make measurements of specific events related to IP Protection. + + // An OAuth token was fetched successfully, for purposes of authenticating + // calls to getInitialData and authAndSign (not for getProxyConfig). + virtual void OAuthTokenFetchComplete(base::TimeDelta duration) = 0; + + // A token batch was fetched. If result is not `kSuccess`, then the duration + // is nullopt. Records the elapsed time for successful requests by + // `IpProtectionConfigGetter` for blind-signed tokens from BSA. + virtual void TokenBatchFetchComplete( + TryGetAuthTokensResult result, + std::optional<base::TimeDelta> duration) = 0; + + // Completed an attempt to fetch tokens via the system-provided auth service + // on Android. + virtual void AndroidTokenBatchFetchComplete( + TryGetAuthTokensAndroidResult result, + std::optional<base::TimeDelta> duration) = 0; + + // Chrome has determined that a proxy chain with the given chain ID has failed + // and fallen back to the next chain in the list. + virtual void ProxyChainFallback(int proxy_chain_id) = 0; + + // The token cache for the given layer was empty during a call to + // OnResolveProxy. + virtual void EmptyTokenCache(ProxyLayer) = 0; + + // An eligibility determination has been made for a request, in a call to + // `OnResolveProxy`. + virtual void RequestIsEligibleForProtection(ProtectionEligibility) = 0; + + // An availability determination has been made for a request, in a call to + // `OnResolveProxy`. This only occurs when the request is eligible and IP + // Protection is enabled. Protection is considered available if both tokens + // and a proxy list are available. + virtual void ProtectionIsAvailableForRequest( + bool are_auth_tokens_available, + bool is_proxy_list_available) = 0; + + // Results of a call to GetAuthToken. `is_token_available` is true if a token + // was returned; `enable_token_caching_by_geo` represents the feature status; + // `is_cache_empty` is true if the manager has no cached tokens (for any geo); + // and `does_requested_geo_match_current` is true if the token request was + // made for the current geo. + virtual void GetAuthTokenResultForGeo( + bool is_token_available, + bool enable_token_caching_by_geo, + bool is_cache_empty, + bool does_requested_geo_match_current) = 0; + + // Token batch generation has completed, with the given duration. + // This measures the whole token batch generation process, from an + // `IpProtectionTokenCacheManagerImpl`'s perspective, from just before calling + // `IpProtectionConfigGetter::TryGetAuthTokens` until `OnGotAuthTokens`. + virtual void TokenBatchGenerationComplete(base::TimeDelta duration) = 0; + + // Whether tokens already exist for a new geo, as measured when current geo + // changes. + virtual void GeoChangeTokenPresence(bool) = 0; + + // A refresh of the proxy list has completed. Duration is set unless the + // result is `kFailed`. + virtual void ProxyListRefreshComplete( + GetProxyListResult result, + std::optional<base::TimeDelta> duration) = 0; + + // Token spend rate, in tokens per hour. This value is expected to be less + // than 1000. + virtual void TokenSpendRate(ProxyLayer, int) = 0; + + // Token expiration rate, in tokens per hour. This value is expected to be + // less than 100,000. + virtual void TokenExpirationRate(ProxyLayer, int) = 0; + + // The estimated memory usage of the MDL, in KB. This is emitted after the + // MDL is fully loaded/updated (with any exclusions applied). + virtual void MdlEstimatedMemoryUsage(size_t) = 0; +}; + +// Get the singleton instance of this type. This will be implemented by each +// subclass, with only one being built on any particular platform. +IpProtectionTelemetry& Telemetry(); + +} // namespace ip_protection + +#endif // COMPONENTS_IP_PROTECTION_COMMON_IP_PROTECTION_TELEMETRY_H_
diff --git a/components/ip_protection/common/ip_protection_telemetry_uma.cc b/components/ip_protection/common/ip_protection_telemetry_uma.cc new file mode 100644 index 0000000..1a37bc9 --- /dev/null +++ b/components/ip_protection/common/ip_protection_telemetry_uma.cc
@@ -0,0 +1,193 @@ +// Copyright 2024 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/ip_protection/common/ip_protection_telemetry_uma.h" + +#include <optional> + +#include "base/metrics/histogram_functions.h" +#include "base/strings/strcat.h" +#include "base/time/time.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" + +namespace ip_protection { + +namespace { + +// An enumeration of the `chain_id` values supplied in the GetProxyInfo RPC +// response, for use with `UmaHistogramEnumeration`. These values are persisted +// to logs. Entries should not be renumbered and numeric values should never be +// reused. +enum class ProxyChainId { + kUnknown = 0, + kChain1 = 1, + kChain2 = 2, + kChain3 = 3, + kMaxValue = kChain3, +}; + +// Convert a chain_id as given in `ProxyChain::ip_protection_chain_id()` into +// a value of the `ProxyChainId` enum. +ProxyChainId ChainIdToEnum(int chain_id) { + static_assert(net::ProxyChain::kMaxIpProtectionChainId == + static_cast<int>(ProxyChainId::kMaxValue), + "maximum `chain_id` must match between `net::ProxyChain` and " + "`ip_protection::ProxyChainId`"); + CHECK(chain_id >= static_cast<int>(ProxyChainId::kUnknown) && + chain_id <= static_cast<int>(ProxyChainId::kMaxValue)); + return static_cast<ProxyChainId>(chain_id); +} + +std::string ProxyLayerToString(ProxyLayer proxy_layer) { + switch (proxy_layer) { + case ip_protection::ProxyLayer::kProxyA: + return "ProxyA"; + case ip_protection::ProxyLayer::kProxyB: + return "ProxyB"; + } +} + +} // namespace + +IpProtectionTelemetry& Telemetry() { + static IpProtectionTelemetryUma instance; + return instance; +} + +void IpProtectionTelemetryUma::OAuthTokenFetchComplete( + base::TimeDelta duration) { + base::UmaHistogramTimes("NetworkService.IpProtection.OAuthTokenFetchTime", + duration); +} + +void IpProtectionTelemetryUma::TokenBatchFetchComplete( + TryGetAuthTokensResult result, + std::optional<base::TimeDelta> duration) { + base::UmaHistogramEnumeration( + "NetworkService.IpProtection.TryGetAuthTokensResult", result); + if (duration.has_value()) { + base::UmaHistogramTimes("NetworkService.IpProtection.TokenBatchRequestTime", + *duration); + } +} + +void IpProtectionTelemetryUma::AndroidTokenBatchFetchComplete( + TryGetAuthTokensAndroidResult result, + std::optional<base::TimeDelta> duration) { + base::UmaHistogramEnumeration( + "NetworkService.AwIpProtection.TryGetAuthTokensResult", result); + if (duration.has_value()) { + base::UmaHistogramTimes( + "NetworkService.AwIpProtection.TokenBatchRequestTime", *duration); + } +} + +void IpProtectionTelemetryUma::ProxyChainFallback(int proxy_chain_id) { + base::UmaHistogramEnumeration( + "NetworkService.IpProtection.ProxyChainFallback", + ChainIdToEnum(proxy_chain_id)); +} + +void IpProtectionTelemetryUma::EmptyTokenCache(ProxyLayer value) { + base::UmaHistogramEnumeration("NetworkService.IpProtection.EmptyTokenCache", + value); +} + +void IpProtectionTelemetryUma::RequestIsEligibleForProtection( + ProtectionEligibility value) { + base::UmaHistogramEnumeration( + "NetworkService.IpProtection.RequestIsEligibleForProtection", value); +} + +void IpProtectionTelemetryUma::ProtectionIsAvailableForRequest( + bool are_auth_tokens_available, + bool is_proxy_list_available) { + base::UmaHistogramBoolean( + "NetworkService.IpProtection.AreAuthTokensAvailable", + are_auth_tokens_available); + base::UmaHistogramBoolean("NetworkService.IpProtection.IsProxyListAvailable", + is_proxy_list_available); + base::UmaHistogramBoolean( + "NetworkService.IpProtection.ProtectionIsAvailableForRequest", + are_auth_tokens_available && is_proxy_list_available); +} + +void IpProtectionTelemetryUma::GetAuthTokenResultForGeo( + bool is_token_available, + bool enable_token_caching_by_geo, + bool is_cache_empty, + bool does_requested_geo_match_current) { + base::UmaHistogramBoolean("NetworkService.IpProtection.GetAuthTokenResult", + is_token_available); + + // Remaining metric is only recorded when caching for geo is enabled. + if (!enable_token_caching_by_geo) { + return; + } + + AuthTokenResultForGeo result; + if (is_token_available) { + if (does_requested_geo_match_current) { + result = AuthTokenResultForGeo::kAvailableForCurrentGeo; + } else { + result = AuthTokenResultForGeo::kAvailableForOtherCachedGeo; + } + } else if (!is_cache_empty) { + result = AuthTokenResultForGeo::kUnavailableButCacheContainsTokens; + } else { + result = AuthTokenResultForGeo::kUnavailableCacheEmpty; + } + base::UmaHistogramEnumeration( + "NetworkService.IpProtection.GetAuthTokenResultForGeo", result); +} + +void IpProtectionTelemetryUma::TokenBatchGenerationComplete( + base::TimeDelta duration) { + base::UmaHistogramMediumTimes( + "NetworkService.IpProtection.TokenBatchGenerationTime", duration); +} + +void IpProtectionTelemetryUma::GeoChangeTokenPresence(bool tokens_present) { + base::UmaHistogramBoolean( + "NetworkService.IpProtection.GeoChangeTokenPresence", tokens_present); +} + +void IpProtectionTelemetryUma::ProxyListRefreshComplete( + GetProxyListResult result, + std::optional<base::TimeDelta> duration) { + base::UmaHistogramEnumeration( + "NetworkService.IpProtection.GetProxyListResult", result); + if (duration.has_value()) { + base::UmaHistogramMediumTimes( + "NetworkService.IpProtection.ProxyListRefreshTime", *duration); + } +} + +void IpProtectionTelemetryUma::TokenSpendRate(ProxyLayer proxy_layer, + int value) { + base::UmaHistogramCounts1000( + base::StrCat({"NetworkService.IpProtection.", + ProxyLayerToString(proxy_layer), ".TokenSpendRate"}), + value); +} + +void IpProtectionTelemetryUma::TokenExpirationRate(ProxyLayer proxy_layer, + int value) { + base::UmaHistogramCounts100000( + base::StrCat({"NetworkService.IpProtection.", + ProxyLayerToString(proxy_layer), ".TokenExpirationRate"}), + value); +} + +void IpProtectionTelemetryUma::MdlEstimatedMemoryUsage(size_t usage) { + // TODO(crbug.com/356109549): Consider renaming this metric. + base::UmaHistogramMemoryKB( + "NetworkService.MaskedDomainList.NetworkServiceProxyAllowList." + "EstimatedMemoryUsageInKB", + // Convert to KB + usage / 1024); +} + +} // namespace ip_protection
diff --git a/components/ip_protection/common/ip_protection_telemetry_uma.h b/components/ip_protection/common/ip_protection_telemetry_uma.h new file mode 100644 index 0000000..f95c4e6 --- /dev/null +++ b/components/ip_protection/common/ip_protection_telemetry_uma.h
@@ -0,0 +1,47 @@ +// Copyright 2024 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_IP_PROTECTION_COMMON_IP_PROTECTION_TELEMETRY_UMA_H_ +#define COMPONENTS_IP_PROTECTION_COMMON_IP_PROTECTION_TELEMETRY_UMA_H_ + +#include <optional> + +#include "base/time/time.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" + +namespace ip_protection { + +// Implementation of IpProtectionTelemetry using UMA. +class IpProtectionTelemetryUma final : public IpProtectionTelemetry { + public: + void OAuthTokenFetchComplete(base::TimeDelta) override; + void TokenBatchFetchComplete(TryGetAuthTokensResult, + std::optional<base::TimeDelta>) override; + void AndroidTokenBatchFetchComplete( + TryGetAuthTokensAndroidResult result, + std::optional<base::TimeDelta> duration) override; + + void ProxyChainFallback(int) override; + void EmptyTokenCache(ProxyLayer) override; + void RequestIsEligibleForProtection(ProtectionEligibility) override; + void ProtectionIsAvailableForRequest(bool are_auth_tokens_available, + bool is_proxy_list_available) override; + void GetAuthTokenResultForGeo(bool is_token_available, + bool enable_token_caching_by_geo, + bool is_cache_empty, + bool does_requested_geo_match_current) override; + void TokenBatchGenerationComplete(base::TimeDelta duration) override; + void GeoChangeTokenPresence(bool) override; + void ProxyListRefreshComplete( + GetProxyListResult result, + std::optional<base::TimeDelta> duration) override; + void TokenSpendRate(ProxyLayer, int) override; + void TokenExpirationRate(ProxyLayer, int) override; + void MdlEstimatedMemoryUsage(size_t) override; +}; + +} // namespace ip_protection + +#endif // COMPONENTS_IP_PROTECTION_COMMON_IP_PROTECTION_TELEMETRY_UMA_H_
diff --git a/components/ip_protection/common/masked_domain_list_manager.cc b/components/ip_protection/common/masked_domain_list_manager.cc index f8119fe35..45150ddb 100644 --- a/components/ip_protection/common/masked_domain_list_manager.cc +++ b/components/ip_protection/common/masked_domain_list_manager.cc
@@ -10,6 +10,7 @@ #include "base/containers/contains.h" #include "base/metrics/histogram_functions.h" #include "base/trace_event/memory_usage_estimator.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "components/ip_protection/common/url_matcher_with_bypass.h" #include "components/privacy_sandbox/masked_domain_list/masked_domain_list.pb.h" #include "net/base/features.h" @@ -252,11 +253,7 @@ } AddPublicSuffixListRules(psl_private_domains); } - // TODO(crbug.com/356109549): Consider renaming this metric. - base::UmaHistogramMemoryKB( - "NetworkService.MaskedDomainList.NetworkServiceProxyAllowList." - "EstimatedMemoryUsageInKB", - EstimateMemoryUsage() / 1024); + ip_protection::Telemetry().MdlEstimatedMemoryUsage(EstimateMemoryUsage()); } bool MaskedDomainListManager::MatchesPublicSuffixList(
diff --git a/components/media_router/browser/android/java/src/org/chromium/components/media_router/BrowserMediaRouterDialogController.java b/components/media_router/browser/android/java/src/org/chromium/components/media_router/BrowserMediaRouterDialogController.java index 7983571..257f1113 100644 --- a/components/media_router/browser/android/java/src/org/chromium/components/media_router/BrowserMediaRouterDialogController.java +++ b/components/media_router/browser/android/java/src/org/chromium/components/media_router/BrowserMediaRouterDialogController.java
@@ -101,7 +101,7 @@ /** Closes the currently open dialog if it's open. */ @CalledByNative public void closeDialog() { - if (!isShowingDialog()) return; + if (mDialogManager == null) return; mDialogManager.closeDialog(); mDialogManager = null;
diff --git a/components/metrics/internal b/components/metrics/internal index ac1f976..ff75f09 160000 --- a/components/metrics/internal +++ b/components/metrics/internal
@@ -1 +1 @@ -Subproject commit ac1f976e1ef64a9b1df0e2a3ef0256d6f53bd5aa +Subproject commit ff75f0920247434231b3f71eb150713e2d3752b5
diff --git a/components/optimization_guide/internal b/components/optimization_guide/internal index 124a90e..6673382 160000 --- a/components/optimization_guide/internal +++ b/components/optimization_guide/internal
@@ -1 +1 @@ -Subproject commit 124a90e02063af1f40473e2213f0104c09c41e0f +Subproject commit 66733820b7ce999c31e929765140f207792127ff
diff --git a/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h b/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h index 3157aa1..c4af09f4 100644 --- a/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h +++ b/components/page_load_metrics/browser/observers/core/largest_contentful_paint_handler.h
@@ -189,10 +189,6 @@ base::TimeTicks navigation_start); void OnSubFrameDeleted(int frame_tree_node_id); - const ContentfulPaintTimingInfo& GetImageContentfulPaintTimingInfo() const { - return main_frame_contentful_paint_.Image(); - } - void UpdateSoftNavigationLargestContentfulPaint( const page_load_metrics::mojom::LargestContentfulPaintTiming&);
diff --git a/components/page_load_metrics/browser/page_load_tracker.cc b/components/page_load_metrics/browser/page_load_tracker.cc index 1a79df6a..69d6e6b 100644 --- a/components/page_load_metrics/browser/page_load_tracker.cc +++ b/components/page_load_metrics/browser/page_load_tracker.cc
@@ -47,18 +47,6 @@ const char kPageLoadPrerender2VisibilityAtActivation[] = "PageLoad.Internal.Prerender2.VisibilityAtActivation"; const char kPageLoadTrackerPageType[] = "PageLoad.Internal.PageType"; -const char kImageLoadStartLessThanDocumentTTFB[] = - "PageLoad.PaintTiming.NavigationToLargestContentfulPaint." - "ImageLoadStartLessThanDocumentTTFB"; -const char kImageLoadEndLessThanLoadStart[] = - "PageLoad.PaintTiming.NavigationToLargestContentfulPaint." - "ImageLoadEndLessThanLoadStart"; -const char kImageLCPLessThanLoadEnd[] = - "PageLoad.PaintTiming.NavigationToLargestContentfulPaint." - "ImageLCPLessThanLoadEnd"; -const char kImageLoadStartLessThanDocumentTtfbCause[] = - "PageLoad.PaintTiming.NavigationToLargestContentfulPaint." - "ImageLoadStartLessThanDocumentTtfbCauses"; } // namespace internal void RecordInternalError(InternalErrorLoadEvent event) { @@ -69,67 +57,6 @@ base::UmaHistogramEnumeration(internal::kPageLoadTrackerPageType, type); } -void RecordImageLoadStartLessThanDocumentTtfbCause( - page_load_metrics::internal::ImageLoadStartLessThanDocumentTtfbCause - sample) { - base::UmaHistogramEnumeration( - internal::kImageLoadStartLessThanDocumentTtfbCause, sample); -} - -void RecordLargestContentfulPaintImageLoadTiming( - const page_load_metrics::mojom::LargestContentfulPaintTiming& - largest_contentful_paint, - base::TimeDelta document_ttfb) { - if (largest_contentful_paint.resource_load_timings->load_start.has_value()) { - UMA_HISTOGRAM_BOOLEAN( - internal::kImageLoadStartLessThanDocumentTTFB, - largest_contentful_paint.resource_load_timings->load_start < - document_ttfb); - } - - if (largest_contentful_paint.resource_load_timings->load_start.has_value() && - largest_contentful_paint.resource_load_timings->load_end.has_value()) { - UMA_HISTOGRAM_BOOLEAN( - internal::kImageLoadEndLessThanLoadStart, - largest_contentful_paint.resource_load_timings->load_end < - largest_contentful_paint.resource_load_timings->load_start); - } - - if (largest_contentful_paint.resource_load_timings->load_end.has_value() && - largest_contentful_paint.largest_image_paint.has_value()) { - UMA_HISTOGRAM_BOOLEAN( - internal::kImageLCPLessThanLoadEnd, - largest_contentful_paint.largest_image_paint < - largest_contentful_paint.resource_load_timings->load_end); - } - - // If the images load_start is less than document_ttfb, then something may be - // wrong with the metric. Attempt to diagnose the cause and record it to UMA, - // or report 'Unknown' if no cause is identified. This code may be removed - // when https://crbug.com/1431906 is resolved. - if (largest_contentful_paint.resource_load_timings->load_start.has_value() && - largest_contentful_paint.resource_load_timings->load_start < - document_ttfb) { - if (largest_contentful_paint.is_loaded_from_memory_cache && - largest_contentful_paint.is_preloaded_with_early_hints) { - RecordImageLoadStartLessThanDocumentTtfbCause( - internal::ImageLoadStartLessThanDocumentTtfbCause:: - kLoadedFromMemoryCacheAndPreloadedWithEarlyHints); - } else if (largest_contentful_paint.is_loaded_from_memory_cache) { - RecordImageLoadStartLessThanDocumentTtfbCause( - internal::ImageLoadStartLessThanDocumentTtfbCause:: - kLoadedFromMemoryCache); - } else if (largest_contentful_paint.is_preloaded_with_early_hints) { - RecordImageLoadStartLessThanDocumentTtfbCause( - internal::ImageLoadStartLessThanDocumentTtfbCause:: - kPreloadedWithEarlyHints); - } else { - RecordImageLoadStartLessThanDocumentTtfbCause( - internal::ImageLoadStartLessThanDocumentTtfbCause::kUnknown); - } - } -} - // TODO(csharrison): Add a case for client side redirects, which is what JS // initiated window.location / window.history navigations get set to. PageEndReason EndReasonForPageTransition(ui::PageTransition transition) { @@ -817,15 +744,6 @@ void PageLoadTracker::OnLoadedResource( const ExtraRequestCompleteInfo& extra_request_complete_info) { - // The main_frame_receive_headers_start_ should be only set once during a - // page load. A new page load would have a new PageLoadTracker object. - if (extra_request_complete_info.request_destination == - network::mojom::RequestDestination::kDocument && - !main_frame_receive_headers_start_.has_value()) { - main_frame_receive_headers_start_ = - extra_request_complete_info.load_timing_info->receive_headers_start; - } - for (const auto& observer : observers_) { observer->OnLoadedResource(extra_request_complete_info); } @@ -1070,31 +988,6 @@ const mojom::PaintTimingPtr& paint_timing = metrics_update_dispatcher_.timing().paint_timing; - // Record UMA if the LCP candidate changes. - - // TODO(crbug.com/40902605): This is to track irregularities in the LCP timing - // values in the UKM recording. We would remove this code once we have - // identified all of the conditions where these irregularities happen. - bool largest_contentful_image_changed = - !largest_contentful_paint_handler_.GetImageContentfulPaintTimingInfo() - .Time() - .has_value() || - (paint_timing->largest_contentful_paint->largest_image_paint - .has_value() && - paint_timing->largest_contentful_paint->largest_image_paint.value() != - largest_contentful_paint_handler_.GetImageContentfulPaintTimingInfo() - .Time() - .value()); - - if (largest_contentful_image_changed) { - if (main_frame_receive_headers_start_.has_value() && - !GetNavigationStart().is_null()) { - RecordLargestContentfulPaintImageLoadTiming( - *paint_timing->largest_contentful_paint, - main_frame_receive_headers_start_.value() - GetNavigationStart()); - } - } - largest_contentful_paint_handler_.RecordMainFrameTiming( *paint_timing->largest_contentful_paint, paint_timing->first_input_or_scroll_notified_timestamp);
diff --git a/components/page_load_metrics/browser/page_load_tracker.h b/components/page_load_metrics/browser/page_load_tracker.h index 6592acc..5c36e16 100644 --- a/components/page_load_metrics/browser/page_load_tracker.h +++ b/components/page_load_metrics/browser/page_load_tracker.h
@@ -80,18 +80,6 @@ kMaxValue = kVisible }; -// These values are recorded into a UMA histogram as causes of irregular LCP -// image load timings. These entries should not be renumbered and the numeric -// values should not be reused. These entries should be kept in sync with the -// definition in tools/metrics/histograms/enums.xml -enum class ImageLoadStartLessThanDocumentTtfbCause { - kUnknown = 0, - kLoadedFromMemoryCache = 1, - kPreloadedWithEarlyHints = 2, - kLoadedFromMemoryCacheAndPreloadedWithEarlyHints = 3, - kMaxValue = kLoadedFromMemoryCacheAndPreloadedWithEarlyHints -}; - } // namespace internal // These errors are internal to the page_load_metrics subsystem and do not @@ -621,8 +609,6 @@ ukm::SourceId potential_soft_navigation_source_id_ = ukm::kInvalidSourceId; ukm::SourceId previous_soft_navigation_source_id_ = ukm::kInvalidSourceId; - std::optional<base::TimeTicks> main_frame_receive_headers_start_; - const internal::PageLoadTrackerPageType page_type_; const base::WeakPtr<PageLoadTracker> parent_tracker_;
diff --git a/components/page_load_metrics/browser/page_load_tracker_unittest.cc b/components/page_load_metrics/browser/page_load_tracker_unittest.cc index 243e890..a6b4e86 100644 --- a/components/page_load_metrics/browser/page_load_tracker_unittest.cc +++ b/components/page_load_metrics/browser/page_load_tracker_unittest.cc
@@ -12,7 +12,6 @@ #include "content/public/test/prerender_test_util.h" #include "content/public/test/test_renderer_host.h" #include "content/public/test/web_contents_tester.h" -#include "net/base/load_timing_info.h" #include "services/metrics/public/cpp/ukm_source_id.h" namespace page_load_metrics { @@ -507,233 +506,6 @@ EXPECT_TRUE(GetEvents().was_prerendered_page_activated); } - -TEST_F(PageLoadTrackerTest, LargestImageIncorrectLoadTimings) { - // Construct page load timing to be used in SimulateTimingUpdate. - page_load_metrics::mojom::PageLoadTiming timing; - page_load_metrics::InitPageLoadTimingForTest(&timing); - timing.navigation_start = base::Time::Now(); - - timing.paint_timing->largest_contentful_paint->resource_load_timings - ->load_start = base::Milliseconds(56); - timing.paint_timing->largest_contentful_paint->resource_load_timings - ->load_end = base::Milliseconds(45); - timing.paint_timing->largest_contentful_paint->largest_image_paint = - base::Milliseconds(34); - - SetTargetUrl(kTestUrl); - auto navigation_simulator = - content::NavigationSimulator::CreateBrowserInitiated(GURL(kTestUrl), - web_contents()); - ASSERT_NE(nullptr, navigation_simulator); - - navigation_simulator->Commit(); - - base::TimeTicks reference_time = - tester()->GetDelegateForCommittedLoad().GetNavigationStart(); - - // Construct ExtraRequestCompleteInfo object to be used in - // SimulateLoadedResource. - net::LoadTimingInfo load_timing_info; - load_timing_info.receive_headers_start = - reference_time + base::Milliseconds(65); - - ExtraRequestCompleteInfo request_info( - /*final_url=*/url::SchemeHostPort(GURL(kTestUrl)), - /*remote_endpoint=*/net::IPEndPoint(), - /*frame_tree_node_id=*/-1, /*was_cached=*/false, /*raw_body_bytes=*/0, - /*original_network_content_length=*/0, - /*request_destination=*/network::mojom::RequestDestination::kDocument, - /*net_error=*/0, - /*load_timing_info=*/ - std::make_unique<net::LoadTimingInfo>(load_timing_info)); - - // Set main frame document receive_headers_start. This field should be set - // only once. - const auto request_id = navigation_simulator->GetGlobalRequestID(); - tester()->SimulateLoadedResource(request_info, request_id); - - // Simulate the invocation of PageLoadTracker::OnLoadedResource() again with - // a ttfb earlier than the image load start and a request destination that is - // not of type Document. This should not overwrite the - // receive_headers_start that is already set. - load_timing_info.receive_headers_start = - reference_time + base::Milliseconds(29); - - ExtraRequestCompleteInfo request_info1( - /*final_url=*/url::SchemeHostPort(GURL(kTestUrl)), - /*remote_endpoint=*/net::IPEndPoint(), - /*frame_tree_node_id=*/-1, /*was_cached=*/false, /*raw_body_bytes=*/0, - /*original_network_content_length=*/0, - /*request_destination=*/network::mojom::RequestDestination::kFrame, - /*net_error=*/0, - /*load_timing_info=*/ - std::make_unique<net::LoadTimingInfo>(load_timing_info)); - - tester()->SimulateLoadedResource(request_info1, request_id); - - // Set largest contentful paint timings. - tester()->SimulateTimingUpdate(timing); - - EXPECT_THAT(tester()->histogram_tester().GetAllSamples( - "PageLoad.PaintTiming.NavigationToLargestContentfulPaint." - "ImageLoadStartLessThanDocumentTTFB"), - testing::ElementsAre(base::Bucket(true, 1))); - - EXPECT_THAT(tester()->histogram_tester().GetAllSamples( - "PageLoad.PaintTiming.NavigationToLargestContentfulPaint." - "ImageLoadEndLessThanLoadStart"), - testing::ElementsAre(base::Bucket(true, 1))); - - EXPECT_THAT(tester()->histogram_tester().GetAllSamples( - "PageLoad.PaintTiming.NavigationToLargestContentfulPaint." - "ImageLCPLessThanLoadEnd"), - testing::ElementsAre(base::Bucket(true, 1))); - EXPECT_THAT( - tester()->histogram_tester().GetAllSamples( - "PageLoad.PaintTiming.NavigationToLargestContentfulPaint." - "ImageLoadStartLessThanDocumentTtfbCauses"), - testing::ElementsAre(base::Bucket( - internal::ImageLoadStartLessThanDocumentTtfbCause::kUnknown, 1))); -} - -class IrregularLcpPageLoadTrackerTest - : public PageLoadTrackerTest, - public testing::WithParamInterface< - internal::ImageLoadStartLessThanDocumentTtfbCause> { - public: - void SetUp() override { - PageLoadMetricsObserverContentTestHarness::SetUp(); - cause_ = GetParam(); - } - // Construct page load timing to be used in SimulateTimingUpdate based on the - // params. - page_load_metrics::mojom::PageLoadTimingPtr CreatePageLoadTiming() { - page_load_metrics::mojom::PageLoadTiming timing; - page_load_metrics::InitPageLoadTimingForTest(&timing); - timing.navigation_start = base::Time::Now(); - - timing.paint_timing->largest_contentful_paint->resource_load_timings - ->load_start = base::Milliseconds(56); - timing.paint_timing->largest_contentful_paint->resource_load_timings - ->load_end = base::Milliseconds(45); - timing.paint_timing->largest_contentful_paint->largest_image_paint = - base::Milliseconds(34); - - switch (cause_) { - case internal::ImageLoadStartLessThanDocumentTtfbCause:: - kLoadedFromMemoryCache: - timing.paint_timing->largest_contentful_paint - ->is_loaded_from_memory_cache = true; - break; - - case internal::ImageLoadStartLessThanDocumentTtfbCause:: - kPreloadedWithEarlyHints: - timing.paint_timing->largest_contentful_paint - ->is_preloaded_with_early_hints = true; - break; - - case internal::ImageLoadStartLessThanDocumentTtfbCause:: - kLoadedFromMemoryCacheAndPreloadedWithEarlyHints: - timing.paint_timing->largest_contentful_paint - ->is_loaded_from_memory_cache = true; - timing.paint_timing->largest_contentful_paint - ->is_preloaded_with_early_hints = true; - break; - - case internal::ImageLoadStartLessThanDocumentTtfbCause::kUnknown: - break; - } - return timing.Clone(); - } - - protected: - internal::ImageLoadStartLessThanDocumentTtfbCause GetCause() { - return cause_; - } - - private: - internal::ImageLoadStartLessThanDocumentTtfbCause cause_; -}; - -TEST_P(IrregularLcpPageLoadTrackerTest, LargestImageIncorrectLoadTimingCauses) { - auto timing = CreatePageLoadTiming(); - - SetTargetUrl(kTestUrl); - auto navigation_simulator = - content::NavigationSimulator::CreateBrowserInitiated(GURL(kTestUrl), - web_contents()); - ASSERT_NE(nullptr, navigation_simulator); - - navigation_simulator->Commit(); - - // Construct ExtraRequestCompleteInfo object to be used in - // SimulateLoadedResource. - base::TimeTicks reference_time = - tester()->GetDelegateForCommittedLoad().GetNavigationStart(); - - net::LoadTimingInfo load_timing_info; - load_timing_info.receive_headers_start = - reference_time + base::Milliseconds(65); - - ExtraRequestCompleteInfo request_info( - /*final_url=*/url::SchemeHostPort(GURL(kTestUrl)), - /*remote_endpoint=*/net::IPEndPoint(), - /*frame_tree_node_id=*/-1, - /*was_cached=*/false, - /*raw_body_bytes=*/0, - /*original_network_content_length=*/0, - /*request_destination=*/network::mojom::RequestDestination::kDocument, - /*net_error=*/0, - /*load_timing_info=*/ - std::make_unique<net::LoadTimingInfo>(load_timing_info)); - - // Set document receive_headers_start. - const auto request_id = navigation_simulator->GetGlobalRequestID(); - tester()->SimulateLoadedResource(request_info, request_id); - - // Set largest contentful paint timings. - tester()->SimulateTimingUpdate(*timing); - - EXPECT_THAT(tester()->histogram_tester().GetAllSamples( - "PageLoad.PaintTiming.NavigationToLargestContentfulPaint." - "ImageLoadStartLessThanDocumentTtfbCauses"), - testing::ElementsAre(base::Bucket(GetCause(), 1))); -} - -std::string PrintImageLoadStartLessThanDocumentTtfbCause( - ::testing::TestParamInfo<internal::ImageLoadStartLessThanDocumentTtfbCause> - info) { - switch (info.param) { - case internal::ImageLoadStartLessThanDocumentTtfbCause:: - kLoadedFromMemoryCache: - return "is_loaded_from_memory_cache"; - - case internal::ImageLoadStartLessThanDocumentTtfbCause:: - kPreloadedWithEarlyHints: - return "is_preloaded_with_early_hints"; - - case internal::ImageLoadStartLessThanDocumentTtfbCause:: - kLoadedFromMemoryCacheAndPreloadedWithEarlyHints: - return "is_loaded_from_memory_cache_and_is_preloaded_with_early_hints"; - - case internal::ImageLoadStartLessThanDocumentTtfbCause::kUnknown: - return "unknown"; - } -} - -INSTANTIATE_TEST_SUITE_P( - , - IrregularLcpPageLoadTrackerTest, - ::testing::Values( - internal::ImageLoadStartLessThanDocumentTtfbCause:: - kLoadedFromMemoryCache, - internal::ImageLoadStartLessThanDocumentTtfbCause:: - kLoadedFromMemoryCacheAndPreloadedWithEarlyHints, - internal::ImageLoadStartLessThanDocumentTtfbCause:: - kPreloadedWithEarlyHints, - internal::ImageLoadStartLessThanDocumentTtfbCause::kUnknown), - PrintImageLoadStartLessThanDocumentTtfbCause); } // namespace } // namespace page_load_metrics
diff --git a/components/page_load_metrics/common/page_load_metrics.mojom b/components/page_load_metrics/common/page_load_metrics.mojom index 0246273..c11d0623 100644 --- a/components/page_load_metrics/common/page_load_metrics.mojom +++ b/components/page_load_metrics/common/page_load_metrics.mojom
@@ -64,10 +64,6 @@ // TODO(crbug.com/40489779): Use an optional enum. bool image_request_priority_valid = false; network.mojom.RequestPriority image_request_priority_value; - - bool is_loaded_from_memory_cache = false; - - bool is_preloaded_with_early_hints = false; }; // TimeDeltas below relative to navigation start.
diff --git a/components/page_load_metrics/renderer/metrics_render_frame_observer.cc b/components/page_load_metrics/renderer/metrics_render_frame_observer.cc index 0483018..ffa22b1 100644 --- a/components/page_load_metrics/renderer/metrics_render_frame_observer.cc +++ b/components/page_load_metrics/renderer/metrics_render_frame_observer.cc
@@ -835,14 +835,6 @@ .InSecondsF(), start); } - - timing->paint_timing->largest_contentful_paint - ->is_loaded_from_memory_cache = - largest_contentful_paint_details.is_loaded_from_memory_cache; - - timing->paint_timing->largest_contentful_paint - ->is_preloaded_with_early_hints = - largest_contentful_paint_details.is_preloaded_with_early_hints; } if (largest_contentful_paint_details.text_paint_size > 0) { // LargestTextPaint and LargestTextPaintSize should be available at the
diff --git a/components/plus_addresses/plus_address_service_unittest.cc b/components/plus_addresses/plus_address_service_unittest.cc index f05490b..ccf86f7 100644 --- a/components/plus_addresses/plus_address_service_unittest.cc +++ b/components/plus_addresses/plus_address_service_unittest.cc
@@ -777,7 +777,7 @@ webdatabase_service_->AddTable(std::make_unique<PlusAddressTable>()); webdatabase_service_->LoadDatabase(); plus_webdata_service_ = base::MakeRefCounted<PlusAddressWebDataService>( - webdatabase_service_, base::SingleThreadTaskRunner::GetCurrentDefault(), + webdatabase_service_, base::SingleThreadTaskRunner::GetCurrentDefault()); plus_webdata_service_->Init(base::DoNothing()); // Even though `PlusAddressTable` operates on the UI sequence in this test,
diff --git a/components/plus_addresses/webdata/plus_address_webdata_service.cc b/components/plus_addresses/webdata/plus_address_webdata_service.cc index 1643788..3315c1c 100644 --- a/components/plus_addresses/webdata/plus_address_webdata_service.cc +++ b/components/plus_addresses/webdata/plus_address_webdata_service.cc
@@ -31,18 +31,16 @@ PlusAddressWebDataService::PlusAddressWebDataService( scoped_refptr<WebDatabaseService> wdbs, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner) + scoped_refptr<base::SequencedTaskRunner> ui_task_runner) : WebDataServiceBase(wdbs, ui_task_runner), - ui_task_runner_(std::move(ui_task_runner)), - db_task_runner_(std::move(db_task_runner)) { + ui_task_runner_(std::move(ui_task_runner)) { sync_bridge_wrapper_ = - base::MakeRefCounted<SyncBridgeDBSequenceWrapper>(db_task_runner_); + base::MakeRefCounted<SyncBridgeDBSequenceWrapper>(wdbs->GetDbSequence()); // When sync changes `PlusAddressTable`, observers on the `ui_task_runner_` - // are notified. To avoid round trips to the `db_task_runner_`, this - // notification includes the set of addition and removal operations - // committed to the database from the sync bridge. + // are notified. To avoid round trips to the WebDatabaseService's db task + // runner, this notification includes the set of addition and removal + // operations committed to the database from the sync bridge. PlusAddressSyncBridge::DataChangedBySyncCallback notify_sync_observers = base::BindPostTask( ui_task_runner_, @@ -51,8 +49,9 @@ weak_factory_.GetWeakPtr())); // The `state->sync_bridge` can only be used on the sequence that it - // was constructed on. Ensure it is created on the `db_task_runner_`. - db_task_runner_->PostTask( + // was constructed on. Ensure it is created on the WebDatabaseService's db + // task runner. + wdbs->GetDbSequence()->PostTask( FROM_HERE, base::BindOnce( [](scoped_refptr<WebDatabaseBackend> db_backend, @@ -119,18 +118,18 @@ std::unique_ptr<syncer::DataTypeControllerDelegate> PlusAddressWebDataService::GetSyncControllerDelegate() { CHECK(ui_task_runner_->RunsTasksInCurrentSequence()); - // `sync_bridge` operates on the `db_task_runner_` - use a + // `sync_bridge` operates on the WebDatabaseService's DB sequence - use a // `ProxyDataTypeControllerDelegate` to forward calls to that sequence. - // Because `db_task_runner_` is a `SequencedTaskRunner`, the `sync_bridge` - // will already be initialized in the callback by the task posted in the - // constructor. + // Because this is a `SequencedTaskRunner`, the `sync_bridge` will already be + // initialized in the callback by the task posted in the constructor. return std::make_unique<syncer::ProxyDataTypeControllerDelegate>( - db_task_runner_, base::BindRepeating( - [](SyncBridgeDBSequenceWrapper* wrapper) { - return wrapper->sync_bridge->change_processor() - ->GetControllerDelegate(); - }, - base::RetainedRef(sync_bridge_wrapper_))); + wdbs_->GetDbSequence(), base::BindRepeating( + [](SyncBridgeDBSequenceWrapper* wrapper) { + return wrapper->sync_bridge + ->change_processor() + ->GetControllerDelegate(); + }, + base::RetainedRef(sync_bridge_wrapper_))); } void PlusAddressWebDataService::NotifyOnWebDataChangedBySync(
diff --git a/components/plus_addresses/webdata/plus_address_webdata_service.h b/components/plus_addresses/webdata/plus_address_webdata_service.h index 8827926..8490e78 100644 --- a/components/plus_addresses/webdata/plus_address_webdata_service.h +++ b/components/plus_addresses/webdata/plus_address_webdata_service.h
@@ -54,8 +54,7 @@ PlusAddressWebDataService( scoped_refptr<WebDatabaseService> wdbs, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner); + scoped_refptr<base::SequencedTaskRunner> ui_task_runner); void AddObserver(Observer* o) { observers_.AddObserver(o); } void RemoveObserver(Observer* o) { observers_.RemoveObserver(o); } @@ -99,7 +98,6 @@ void NotifyOnWebDataChangedBySync(std::vector<PlusAddressDataChange> changes); scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; - scoped_refptr<base::SequencedTaskRunner> db_task_runner_; // `scoped_refptr<>`, because the destruction order of // `PlusAddressWebDataService` and `db_task_runner_` is unclear.
diff --git a/components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser.cc b/components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser.cc index d0aea59e..76f497da 100644 --- a/components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser.cc +++ b/components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser.cc
@@ -3,13 +3,15 @@ // found in the LICENSE file. #include "components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser.h" -#include "components/privacy_sandbox/privacy_sandbox_attestations/proto/privacy_sandbox_attestations.pb.h" #include <string> #include "base/containers/enum_set.h" #include "base/containers/flat_map.h" +#include "base/feature_list.h" +#include "components/privacy_sandbox/privacy_sandbox_attestations/proto/privacy_sandbox_attestations.pb.h" #include "net/base/schemeful_site.h" +#include "third_party/blink/public/common/features.h" #include "url/gurl.h" namespace { @@ -44,6 +46,15 @@ privacy_sandbox::PrivacySandboxAttestationsGatedAPI::kSharedStorage); return; } + case privacy_sandbox::LOCAL_UNPARTITIONED_DATA_ACCESS: { + if (base::FeatureList::IsEnabled( + blink::features::kFencedFramesLocalUnpartitionedDataAccess)) { + allowed_api_set.Put( + privacy_sandbox::PrivacySandboxAttestationsGatedAPI:: + kLocalUnpartitionedDataAccess); + } + return; + } case privacy_sandbox::UNKNOWN: { return; }
diff --git a/components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser_unittest.cc b/components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser_unittest.cc index 39060bde..5963ff4 100644 --- a/components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser_unittest.cc +++ b/components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser_unittest.cc
@@ -3,16 +3,18 @@ // found in the LICENSE file. #include "components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations_parser.h" -#include "components/privacy_sandbox/privacy_sandbox_attestations/proto/privacy_sandbox_attestations.pb.h" + +#include <string> #include "base/containers/enum_set.h" #include "base/containers/flat_map.h" +#include "base/test/with_feature_override.h" +#include "components/privacy_sandbox/privacy_sandbox_attestations/proto/privacy_sandbox_attestations.pb.h" #include "net/base/schemeful_site.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/public/common/features.h" #include "url/gurl.h" -#include <string> - namespace privacy_sandbox { class PrivacySandboxAttestationsParserTest : public testing::Test {}; @@ -295,4 +297,150 @@ ASSERT_TRUE(site1apis.size() == 5UL); } +// When 'FencedFramesLocalUnpartitionedDataAccess' feature is enabled, there +// will be a new attestation API `LOCAL_UNPARTITIONED_DATA_ACCESS`. +class FencedFramesLocalUnpartitionedDataAccessAttestationTest + : public base::test::WithFeatureOverride, + public PrivacySandboxAttestationsParserTest { + public: + FencedFramesLocalUnpartitionedDataAccessAttestationTest() + : base::test::WithFeatureOverride( + blink::features::kFencedFramesLocalUnpartitionedDataAccess) {} +}; + +TEST_P(FencedFramesLocalUnpartitionedDataAccessAttestationTest, + LocalUnpartitionedDataAccessAttestationEnum) { + PrivacySandboxAttestationsProto proto; + ASSERT_EQ(proto.site_attestations_size(), 0); + + std::string site1 = "https://a.com"; + std::string site2 = "https://b.com"; + + PrivacySandboxAttestationsProto::PrivacySandboxAttestedAPIsProto attestation1; + attestation1.add_attested_apis(LOCAL_UNPARTITIONED_DATA_ACCESS); + + PrivacySandboxAttestationsProto::PrivacySandboxAttestedAPIsProto attestation2; + attestation2.add_attested_apis(SHARED_STORAGE); + attestation2.add_attested_apis(LOCAL_UNPARTITIONED_DATA_ACCESS); + + (*proto.mutable_site_attestations())[site1] = attestation1; + (*proto.mutable_site_attestations())[site2] = attestation2; + + std::string serialized_proto; + proto.SerializeToString(&serialized_proto); + + std::optional<PrivacySandboxAttestationsMap> optional_map = + ParseAttestationsFromString(serialized_proto); + ASSERT_TRUE(optional_map.has_value()); + ASSERT_EQ(optional_map->size(), 2UL); + + const PrivacySandboxAttestationsGatedAPISet& site1apis = + (*optional_map)[net::SchemefulSite(GURL(site1))]; + EXPECT_EQ( + site1apis.Has( + PrivacySandboxAttestationsGatedAPI::kLocalUnpartitionedDataAccess), + IsParamFeatureEnabled()); + EXPECT_EQ(site1apis.size(), IsParamFeatureEnabled() ? 1UL : 0UL); + + const PrivacySandboxAttestationsGatedAPISet& site2apis = + (*optional_map)[net::SchemefulSite(GURL(site2))]; + ASSERT_TRUE( + site2apis.Has(PrivacySandboxAttestationsGatedAPI::kSharedStorage)); + EXPECT_EQ( + site2apis.Has( + PrivacySandboxAttestationsGatedAPI::kLocalUnpartitionedDataAccess), + IsParamFeatureEnabled()); + EXPECT_EQ(site2apis.size(), IsParamFeatureEnabled() ? 2UL : 1UL); +} + +TEST_P(FencedFramesLocalUnpartitionedDataAccessAttestationTest, AllAPIs) { + PrivacySandboxAttestationsProto proto; + ASSERT_EQ(proto.site_attestations_size(), 0); + + // There were 5 attestation enums before the local unpartitioned data access + // change. + proto.add_all_apis(TOPICS); + proto.add_all_apis(PROTECTED_AUDIENCE); + proto.add_all_apis(PRIVATE_AGGREGATION); + proto.add_all_apis(ATTRIBUTION_REPORTING); + proto.add_all_apis(SHARED_STORAGE); + + std::string site1 = "https://a.com"; + proto.add_sites_attested_for_all_apis(site1); + + std::string serialized_proto; + proto.SerializeToString(&serialized_proto); + + std::optional<PrivacySandboxAttestationsMap> optional_map = + ParseAttestationsFromString(serialized_proto); + ASSERT_TRUE(optional_map.has_value()); + ASSERT_EQ(optional_map->size(), 1UL); + + // The parsed attestation map should have the site attested for the 5 APIs, + // regardless of the feature status. + const PrivacySandboxAttestationsGatedAPISet& site1apis = + (*optional_map)[net::SchemefulSite(GURL(site1))]; + ASSERT_TRUE(site1apis.Has(PrivacySandboxAttestationsGatedAPI::kTopics)); + ASSERT_TRUE( + site1apis.Has(PrivacySandboxAttestationsGatedAPI::kProtectedAudience)); + ASSERT_TRUE( + site1apis.Has(PrivacySandboxAttestationsGatedAPI::kPrivateAggregation)); + ASSERT_TRUE( + site1apis.Has(PrivacySandboxAttestationsGatedAPI::kAttributionReporting)); + ASSERT_TRUE( + site1apis.Has(PrivacySandboxAttestationsGatedAPI::kSharedStorage)); + ASSERT_FALSE(site1apis.Has( + PrivacySandboxAttestationsGatedAPI::kLocalUnpartitionedDataAccess)); + ASSERT_EQ(site1apis.size(), 5UL); +} + +TEST_P(FencedFramesLocalUnpartitionedDataAccessAttestationTest, + AllAPIsWithLocalUnpartitionedDataAccess) { + PrivacySandboxAttestationsProto proto; + ASSERT_EQ(proto.site_attestations_size(), 0); + + // With the local unpartitioned data access change, all APIs will include the + // new attestation enum. + proto.add_all_apis(TOPICS); + proto.add_all_apis(PROTECTED_AUDIENCE); + proto.add_all_apis(PRIVATE_AGGREGATION); + proto.add_all_apis(ATTRIBUTION_REPORTING); + proto.add_all_apis(SHARED_STORAGE); + proto.add_all_apis(LOCAL_UNPARTITIONED_DATA_ACCESS); + + std::string site1 = "https://a.com"; + proto.add_sites_attested_for_all_apis(site1); + + std::string serialized_proto; + proto.SerializeToString(&serialized_proto); + + std::optional<PrivacySandboxAttestationsMap> optional_map = + ParseAttestationsFromString(serialized_proto); + ASSERT_TRUE(optional_map.has_value()); + ASSERT_EQ(optional_map->size(), 1UL); + + // If feature enabled, the attestation map should have the site attested for + // all 6 APIs. Otherwise, the site is attested for the 5 pre-existing APIs, + // excluding `LOCAL_UNPARTITIONED_DATA_ACCESS`. + const PrivacySandboxAttestationsGatedAPISet& site1apis = + (*optional_map)[net::SchemefulSite(GURL(site1))]; + ASSERT_TRUE(site1apis.Has(PrivacySandboxAttestationsGatedAPI::kTopics)); + ASSERT_TRUE( + site1apis.Has(PrivacySandboxAttestationsGatedAPI::kProtectedAudience)); + ASSERT_TRUE( + site1apis.Has(PrivacySandboxAttestationsGatedAPI::kPrivateAggregation)); + ASSERT_TRUE( + site1apis.Has(PrivacySandboxAttestationsGatedAPI::kAttributionReporting)); + ASSERT_TRUE( + site1apis.Has(PrivacySandboxAttestationsGatedAPI::kSharedStorage)); + ASSERT_EQ( + site1apis.Has( + PrivacySandboxAttestationsGatedAPI::kLocalUnpartitionedDataAccess), + IsParamFeatureEnabled()); + ASSERT_EQ(site1apis.size(), IsParamFeatureEnabled() ? 6UL : 5UL); +} + +INSTANTIATE_FEATURE_OVERRIDE_TEST_SUITE( + FencedFramesLocalUnpartitionedDataAccessAttestationTest); + } // namespace privacy_sandbox
diff --git a/components/privacy_sandbox/privacy_sandbox_attestations/proto/privacy_sandbox_attestations.proto b/components/privacy_sandbox/privacy_sandbox_attestations/proto/privacy_sandbox_attestations.proto index 6bae63f..7e807da 100644 --- a/components/privacy_sandbox/privacy_sandbox_attestations/proto/privacy_sandbox_attestations.proto +++ b/components/privacy_sandbox/privacy_sandbox_attestations/proto/privacy_sandbox_attestations.proto
@@ -16,6 +16,7 @@ PRIVATE_AGGREGATION = 3; ATTRIBUTION_REPORTING = 4; SHARED_STORAGE = 5; + LOCAL_UNPARTITIONED_DATA_ACCESS = 6; } message PrivacySandboxAttestationsProto {
diff --git a/components/privacy_sandbox/privacy_sandbox_features.cc b/components/privacy_sandbox/privacy_sandbox_features.cc index 71f02c4..269bd01c 100644 --- a/components/privacy_sandbox/privacy_sandbox_features.cc +++ b/components/privacy_sandbox/privacy_sandbox_features.cc
@@ -130,10 +130,6 @@ "RelatedWebsiteSetsDevUI", base::FEATURE_DISABLED_BY_DEFAULT); -BASE_FEATURE(kFingerprintingProtectionSetting, - "FingerprintingProtectionSetting", - base::FEATURE_DISABLED_BY_DEFAULT); - BASE_FEATURE(kFingerprintingProtectionUx, "FingerprintingProtectionUx", base::FEATURE_DISABLED_BY_DEFAULT);
diff --git a/components/privacy_sandbox/privacy_sandbox_features.h b/components/privacy_sandbox/privacy_sandbox_features.h index 6c0c6f2..d731319 100644 --- a/components/privacy_sandbox/privacy_sandbox_features.h +++ b/components/privacy_sandbox/privacy_sandbox_features.h
@@ -158,10 +158,6 @@ COMPONENT_EXPORT(PRIVACY_SANDBOX_FEATURES) BASE_DECLARE_FEATURE(kRelatedWebsiteSetsDevUI); -// Enables fingerprinting protection setting behavior. -COMPONENT_EXPORT(PRIVACY_SANDBOX_FEATURES) -BASE_DECLARE_FEATURE(kFingerprintingProtectionSetting); - // Enables fingerprinting protection setting UX. COMPONENT_EXPORT(PRIVACY_SANDBOX_FEATURES) BASE_DECLARE_FEATURE(kFingerprintingProtectionUx);
diff --git a/components/privacy_sandbox/privacy_sandbox_settings.h b/components/privacy_sandbox/privacy_sandbox_settings.h index b49ce43..9212a50 100644 --- a/components/privacy_sandbox/privacy_sandbox_settings.h +++ b/components/privacy_sandbox/privacy_sandbox_settings.h
@@ -30,15 +30,16 @@ // 1. Update kMaxValue to match it. // 2. Update `PrivacySandboxAttestationsGatedAPIProto` in // `privacy_sandbox_attestations.proto`. -// 3. Update `AllowAPI` in `privacy_sandbox_attestations_parser.cc`. +// 3. Update `InsertAPI` in `privacy_sandbox_attestations_parser.cc`. enum class PrivacySandboxAttestationsGatedAPI { kTopics, kProtectedAudience, kPrivateAggregation, kAttributionReporting, kSharedStorage, + kLocalUnpartitionedDataAccess, - kMaxValue = kSharedStorage, + kMaxValue = kLocalUnpartitionedDataAccess, }; // A service which acts as a intermediary between Privacy Sandbox APIs and the
diff --git a/components/privacy_sandbox/tracking_protection_settings_observer.h b/components/privacy_sandbox/tracking_protection_settings_observer.h index 5f2184e..ee4192e 100644 --- a/components/privacy_sandbox/tracking_protection_settings_observer.h +++ b/components/privacy_sandbox/tracking_protection_settings_observer.h
@@ -22,9 +22,6 @@ // For observation of DNT. virtual void OnDoNotTrackEnabledChanged() {} - // For observation of anti-fingerprinting. - virtual void OnFingerprintingProtectionEnabledChanged() {} - // For observation of IP protection. virtual void OnIpProtectionEnabledChanged() {}
diff --git a/components/safe_browsing/content/browser/client_side_detection_service.cc b/components/safe_browsing/content/browser/client_side_detection_service.cc index 077973b2..365948f 100644 --- a/components/safe_browsing/content/browser/client_side_detection_service.cc +++ b/components/safe_browsing/content/browser/client_side_detection_service.cc
@@ -445,6 +445,14 @@ return true; } + // Clear the expired timestamps + const auto cutoff = base::Time::Now() - base::Days(kReportsIntervalDays); + // Erase items older than cutoff because we will never care about them again. + while (!phishing_report_times_.empty() && + phishing_report_times_.front() < cutoff) { + phishing_report_times_.pop_front(); + } + // `delegate_` and prefs can be null in unit tests. if (base::FeatureList::IsEnabled(kSafeBrowsingDailyPhishingReportsLimit) && (delegate_ && delegate_->GetPrefs()) && @@ -460,14 +468,6 @@ } bool ClientSideDetectionService::AddPhishingReport(base::Time timestamp) { - base::Time cutoff = base::Time::Now() - base::Days(kReportsIntervalDays); - - // Erase items older than cutoff because we will never care about them again. - while (!phishing_report_times_.empty() && - phishing_report_times_.front() < cutoff) { - phishing_report_times_.pop_front(); - } - // We should not be adding a report when we are at the limit when this // function calls, but in case it does, we want to track how far back the // last report was prior to the current report and exit the function early.
diff --git a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc index 27ba76b..ab5d2c5 100644 --- a/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc +++ b/components/signin/internal/identity_manager/mutable_profile_oauth2_token_service_delegate_unittest.cc
@@ -109,8 +109,7 @@ web_database->AddTable(std::make_unique<TokenServiceTable>()); web_database->LoadDatabase(); token_web_data_ = new TokenWebData( - web_database, base::SingleThreadTaskRunner::GetCurrentDefault(), - base::SingleThreadTaskRunner::GetCurrentDefault()); + web_database, base::SingleThreadTaskRunner::GetCurrentDefault()); token_web_data_->Init(base::NullCallback()); }
diff --git a/components/signin/public/webdata/token_web_data.cc b/components/signin/public/webdata/token_web_data.cc index c1080a5..b4c7be7 100644 --- a/components/signin/public/webdata/token_web_data.cc +++ b/components/signin/public/webdata/token_web_data.cc
@@ -72,10 +72,9 @@ TokenWebData::TokenWebData( scoped_refptr<WebDatabaseService> wdbs, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner) + scoped_refptr<base::SequencedTaskRunner> ui_task_runner) : WebDataServiceBase(wdbs, std::move(ui_task_runner)), - token_backend_(new TokenWebDataBackend(std::move(db_task_runner))) {} + token_backend_(new TokenWebDataBackend(wdbs->GetDbSequence())) {} void TokenWebData::SetTokenForService( const std::string& service, @@ -106,10 +105,4 @@ consumer); } -TokenWebData::TokenWebData( - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner) - : WebDataServiceBase(nullptr, std::move(ui_task_runner)), - token_backend_(new TokenWebDataBackend(std::move(db_task_runner))) {} - TokenWebData::~TokenWebData() {}
diff --git a/components/signin/public/webdata/token_web_data.h b/components/signin/public/webdata/token_web_data.h index 4df56569..6f2a478e 100644 --- a/components/signin/public/webdata/token_web_data.h +++ b/components/signin/public/webdata/token_web_data.h
@@ -45,11 +45,7 @@ class TokenWebData : public WebDataServiceBase { public: TokenWebData(scoped_refptr<WebDatabaseService> wdbs, - scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner); - - TokenWebData(scoped_refptr<base::SequencedTaskRunner> ui_task_runner, - scoped_refptr<base::SequencedTaskRunner> db_task_runner); + scoped_refptr<base::SequencedTaskRunner> ui_task_runner); TokenWebData(const TokenWebData&) = delete; TokenWebData& operator=(const TokenWebData&) = delete;
diff --git a/components/visited_url_ranking/DEPS b/components/visited_url_ranking/DEPS index 02637b4..ec98efc1 100644 --- a/components/visited_url_ranking/DEPS +++ b/components/visited_url_ranking/DEPS
@@ -6,7 +6,9 @@ "+components/segmentation_platform/public", "+components/segmentation_platform/embedder/default_model", "+components/segmentation_platform/internal/metadata", + "+components/strings", "+components/sessions/core", "+components/sync_device_info", "+components/sync_sessions", + "+ui/base", ]
diff --git a/components/visited_url_ranking/internal/BUILD.gn b/components/visited_url_ranking/internal/BUILD.gn index 10b8928..37abfee 100644 --- a/components/visited_url_ranking/internal/BUILD.gn +++ b/components/visited_url_ranking/internal/BUILD.gn
@@ -44,9 +44,11 @@ "//components/segmentation_platform/internal:internal", "//components/segmentation_platform/public", "//components/sessions", + "//components/strings", "//components/sync_sessions", "//components/url_deduplication", "//components/visited_url_ranking/public", + "//ui/base", "//url", ] }
diff --git a/components/visited_url_ranking/internal/visited_url_ranking_service_impl.cc b/components/visited_url_ranking/internal/visited_url_ranking_service_impl.cc index 9e8ca46..7ced49a 100644 --- a/components/visited_url_ranking/internal/visited_url_ranking_service_impl.cc +++ b/components/visited_url_ranking/internal/visited_url_ranking_service_impl.cc
@@ -34,6 +34,7 @@ #include "components/segmentation_platform/public/result.h" #include "components/segmentation_platform/public/segmentation_platform_service.h" #include "components/segmentation_platform/public/types/processed_value.h" +#include "components/strings/grit/components_strings.h" #include "components/sync_sessions/session_sync_service.h" #include "components/url_deduplication/url_deduplication_helper.h" #include "components/visited_url_ranking/internal/history_url_visit_data_fetcher.h" @@ -48,6 +49,8 @@ #include "components/visited_url_ranking/public/url_visit_schema.h" #include "components/visited_url_ranking/public/url_visit_util.h" #include "components/visited_url_ranking/public/visited_url_ranking_service.h" +#include "ui/base/l10n/l10n_util.h" +#include "ui/base/l10n/time_format.h" using segmentation_platform::AnnotatedNumericResult; using segmentation_platform::InputContext; @@ -192,6 +195,33 @@ scored_visits.size()); std::move(callback).Run(ResultStatus::kSuccess, std::move(scored_visits)); } +#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS) +std::u16string FormatRelativeTime(const base::Time& time) { + // Return a time like "1 hour ago", "2 days ago", etc. + base::Time now = base::Time::Now(); + // TimeFormat does not support negative TimeDelta values, so then we use 0. + return ui::TimeFormat::Simple(ui::TimeFormat::FORMAT_ELAPSED, + ui::TimeFormat::LENGTH_SHORT, + now < time ? base::TimeDelta() : now - time); +} +#endif + +std::u16string GetStringForDecoration(DecorationType type) { + switch (type) { + case DecorationType::kMostRecent: + return l10n_util::GetStringUTF16(IDS_TAB_RESUME_DECORATORS_MOST_RECENT); + case DecorationType::kFrequentlyVisitedAtTime: + return l10n_util::GetStringUTF16( + IDS_TAB_RESUME_DECORATORS_FREQUENTLY_VISITED); + case DecorationType::kFrequentlyVisited: + return l10n_util::GetStringUTF16( + IDS_TAB_RESUME_DECORATORS_FREQUENTLY_VISITED); + case DecorationType::kVisitedXAgo: + return l10n_util::GetStringUTF16(IDS_TAB_RESUME_DECORATORS_VISITED_X_AGO); + case DecorationType::kUnknown: + return l10n_util::GetStringUTF16(IDS_TAB_RESUME_DECORATORS_VISITED_X_AGO); + } +} void AddMostRecentDecoration(URLVisitAggregate& url_visit_aggregate, URLVisitAggregate* curr_most_recent_aggregate, @@ -202,7 +232,8 @@ } if (last_visit) { curr_most_recent_aggregate->decorations.emplace_back( - DecorationType::kMostRecent); + DecorationType::kMostRecent, + GetStringForDecoration(DecorationType::kMostRecent)); } } @@ -230,7 +261,8 @@ if (total_visits > features::kVisitedURLRankingFrequentlyVisitedThreshold.Get()) { url_visit_aggregate.decorations.emplace_back( - DecorationType::kFrequentlyVisited); + DecorationType::kFrequentlyVisited, + GetStringForDecoration(DecorationType::kFrequentlyVisited)); } } @@ -245,12 +277,27 @@ if (static_cast<int>(history_data->same_time_group_visit_count) > features::kVisitedURLRankingDecorationTimeOfDay.Get()) { url_visit_aggregate.decorations.emplace_back( - DecorationType::kFrequentlyVisitedAtTime); + DecorationType::kFrequentlyVisitedAtTime, + GetStringForDecoration(DecorationType::kFrequentlyVisitedAtTime)); } } } } +void AddVisitedXAgoDecoration(URLVisitAggregate& url_visit_aggregate) { +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) + // TODO(crbug/329243415): Implement iOS and Android timestamp + url_visit_aggregate.decorations.emplace_back( + DecorationType::kVisitedXAgo, + GetStringForDecoration(DecorationType::kVisitedXAgo)); +#else + url_visit_aggregate.decorations.emplace_back( + DecorationType::kVisitedXAgo, + GetStringForDecoration(DecorationType::kVisitedXAgo) + u" " + + FormatRelativeTime(url_visit_aggregate.GetLastVisitTime())); +#endif +} + } // namespace VisitedURLRankingServiceImpl::VisitedURLRankingServiceImpl( @@ -362,8 +409,8 @@ AddFrequentlyVisitedAtTimeDecoration(url_visit_aggregate); - // Default decoration. - url_visit_aggregate.decorations.emplace_back(DecorationType::kVisitedXAgo); + // Default decoration + AddVisitedXAgoDecoration(url_visit_aggregate); } std::move(callback).Run(ResultStatus::kSuccess, std::move(visit_aggregates));
diff --git a/components/visited_url_ranking/internal/visited_url_ranking_service_impl_unittest.cc b/components/visited_url_ranking/internal/visited_url_ranking_service_impl_unittest.cc index dc87a11..4ec60f20 100644 --- a/components/visited_url_ranking/internal/visited_url_ranking_service_impl_unittest.cc +++ b/components/visited_url_ranking/internal/visited_url_ranking_service_impl_unittest.cc
@@ -570,8 +570,20 @@ EXPECT_EQ(result.second.size(), 1u); EXPECT_EQ(**result.second[0].GetAssociatedURLs().begin(), kSampleUrl); EXPECT_EQ(result.second[0].decorations.size(), 4u); - EXPECT_EQ(GetMostRelevantDecoration(result.second[0]).type, + EXPECT_EQ(GetMostRelevantDecoration(result.second[0]).GetType(), DecorationType::kMostRecent); + EXPECT_EQ(GetMostRelevantDecoration(result.second[0]).GetDisplayString(), + u"Your most recent tab"); + EXPECT_EQ(result.second[0].decorations[1].GetDisplayString(), + u"You visit often"); + EXPECT_EQ(result.second[0].decorations[2].GetDisplayString(), + u"You visit often"); +#if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) + EXPECT_EQ(result.second[0].decorations[3].GetDisplayString(), u"You visited"); +#else + EXPECT_EQ(result.second[0].decorations[3].GetDisplayString(), + u"You visited 0 secs ago"); +#endif } } // namespace visited_url_ranking
diff --git a/components/visited_url_ranking/public/decoration.cc b/components/visited_url_ranking/public/decoration.cc index aec6a50..edb4fd4 100644 --- a/components/visited_url_ranking/public/decoration.cc +++ b/components/visited_url_ranking/public/decoration.cc
@@ -6,8 +6,9 @@ namespace visited_url_ranking { -Decoration::Decoration(DecorationType decoration_type) - : type(decoration_type) {} +Decoration::Decoration(DecorationType decoration_type, + std::u16string display_string) + : type_(decoration_type), display_string_(std::move(display_string)) {} Decoration::Decoration(const Decoration&) = default;
diff --git a/components/visited_url_ranking/public/decoration.h b/components/visited_url_ranking/public/decoration.h index 27e999c..a3f791f 100644 --- a/components/visited_url_ranking/public/decoration.h +++ b/components/visited_url_ranking/public/decoration.h
@@ -5,6 +5,8 @@ #ifndef COMPONENTS_VISITED_URL_RANKING_PUBLIC_DECORATION_H_ #define COMPONENTS_VISITED_URL_RANKING_PUBLIC_DECORATION_H_ +#include <string> + namespace visited_url_ranking { // The currently supported Decorators that may be added to a URL Visit @@ -20,11 +22,17 @@ // Holds the data for one of the decorations for a URL Visit Aggregate. class Decoration { public: - explicit Decoration(DecorationType decoration_type); + explicit Decoration(DecorationType decoration_type, + std::u16string display_string); Decoration(const Decoration&); virtual ~Decoration() = default; - DecorationType type; + DecorationType GetType() const { return type_; } + std::u16string GetDisplayString() const { return display_string_; } + + private: + DecorationType type_; + std::u16string display_string_; }; } // namespace visited_url_ranking
diff --git a/components/visited_url_ranking/public/url_visit.cc b/components/visited_url_ranking/public/url_visit.cc index 9e8d77a..e5105f1 100644 --- a/components/visited_url_ranking/public/url_visit.cc +++ b/components/visited_url_ranking/public/url_visit.cc
@@ -72,28 +72,45 @@ base::Time URLVisitAggregate::GetLastVisitTime() const { std::optional<base::Time> last_visit_time; for (const auto& fetcher_entry : fetcher_data_map) { - // Prefer timestamp from local tabs, if not an active tab then use timestamp - // from the history. switch (fetcher_entry.first) { - case Fetcher::kTabModel: - last_visit_time = + case Fetcher::kTabModel: { + std::optional<base::Time> tab_last_active = std::get<URLVisitAggregate::TabData>(fetcher_entry.second) - .last_active_tab.visit.last_modified; - break; - case Fetcher::kSession: - if (!last_visit_time) { + .last_active; + if (!last_visit_time || + (tab_last_active && last_visit_time < tab_last_active)) { + last_visit_time = tab_last_active; + } else if (!last_visit_time && !tab_last_active) { last_visit_time = std::get<URLVisitAggregate::TabData>(fetcher_entry.second) .last_active_tab.visit.last_modified; } break; - case Fetcher::kHistory: - if (!last_visit_time) { + } + case Fetcher::kSession: { + std::optional<base::Time> session_last_active = + std::get<URLVisitAggregate::TabData>(fetcher_entry.second) + .last_active; + if (!last_visit_time || + (session_last_active && last_visit_time < session_last_active)) { + last_visit_time = session_last_active; + } else if (!last_visit_time && !session_last_active) { last_visit_time = - std::get<URLVisitAggregate::HistoryData>(fetcher_entry.second) - .last_visited.visit_row.visit_time; + std::get<URLVisitAggregate::TabData>(fetcher_entry.second) + .last_active_tab.visit.last_modified; } break; + } + case Fetcher::kHistory: { + std::optional<base::Time> history_last_visit = + std::get<URLVisitAggregate::HistoryData>(fetcher_entry.second) + .last_visited.visit_row.visit_time; + if (!last_visit_time || + (history_last_visit && last_visit_time < history_last_visit)) { + last_visit_time = history_last_visit; + } + break; + } } } return *last_visit_time;
diff --git a/components/visited_url_ranking/public/url_visit_util.cc b/components/visited_url_ranking/public/url_visit_util.cc index 4881f323..62a9dbfe 100644 --- a/components/visited_url_ranking/public/url_visit_util.cc +++ b/components/visited_url_ranking/public/url_visit_util.cc
@@ -358,9 +358,9 @@ const Decoration* result; int max_priority = -1; for (const auto& decoration : url_visit_aggregate.decorations) { - if (GetPriority(decoration.type) > max_priority) { + if (GetPriority(decoration.GetType()) > max_priority) { result = &decoration; - max_priority = GetPriority(decoration.type); + max_priority = GetPriority(decoration.GetType()); } } return *result;
diff --git a/components/viz/service/layers/layer_context_impl.cc b/components/viz/service/layers/layer_context_impl.cc index 32b7b8fd..9da1e9b 100644 --- a/components/viz/service/layers/layer_context_impl.cc +++ b/components/viz/service/layers/layer_context_impl.cc
@@ -261,7 +261,6 @@ layer->SetClipTreeIndex(wire.clip_tree_index); layer->SetEffectTreeIndex(wire.effect_tree_index); layer->SetScrollTreeIndex(wire.scroll_tree_index); - layer->UpdateScrollable(); return base::ok(); }
diff --git a/components/webdata/common/web_database_backend.cc b/components/webdata/common/web_database_backend.cc index 0037d52..a99d6184 100644 --- a/components/webdata/common/web_database_backend.cc +++ b/components/webdata/common/web_database_backend.cc
@@ -22,10 +22,14 @@ const scoped_refptr<base::SequencedTaskRunner>& db_thread) : base::RefCountedDeleteOnSequence<WebDatabaseBackend>(db_thread), db_path_(path), - delegate_(std::move(delegate)) {} + delegate_(std::move(delegate)) { + // WebDatabaseBackend is created on the client sequence then accessed on the + // DB sequence. + DETACH_FROM_SEQUENCE(sequence_checker_); +} void WebDatabaseBackend::AddTable(std::unique_ptr<WebDatabaseTable> table) { - DCHECK(!db_); + CHECK(!init_complete_) << "AddTable must be called before init starts."; tables_.push_back(std::move(table)); } @@ -36,6 +40,7 @@ } void WebDatabaseBackend::ShutdownDatabase() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (db_ && init_status_ == sql::INIT_OK) db_->CommitTransaction(); db_.reset(); @@ -46,15 +51,17 @@ void WebDatabaseBackend::DBWriteTaskWrapper( WebDatabaseService::WriteTask task, std::unique_ptr<WebDataRequest> request) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + CHECK(init_complete_) << "Init must be complete before running a DB task."; if (!request->IsActive()) return; - ExecuteWriteTask(std::move(task)); request_manager_->RequestCompleted(std::move(request), nullptr); } void WebDatabaseBackend::ExecuteWriteTask(WebDatabaseService::WriteTask task) { - LoadDatabaseIfNecessary(); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + CHECK(init_complete_) << "Init must be complete before running a DB task."; if (db_ && init_status_ == sql::INIT_OK) { WebDatabase::State state = std::move(task).Run(db_.get()); if (state == WebDatabase::COMMIT_NEEDED) @@ -65,25 +72,29 @@ void WebDatabaseBackend::DBReadTaskWrapper( WebDatabaseService::ReadTask task, std::unique_ptr<WebDataRequest> request) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + CHECK(init_complete_) << "Init must be complete before running a DB task."; if (!request->IsActive()) return; - std::unique_ptr<WDTypedResult> result = ExecuteReadTask(std::move(task)); request_manager_->RequestCompleted(std::move(request), std::move(result)); } std::unique_ptr<WDTypedResult> WebDatabaseBackend::ExecuteReadTask( WebDatabaseService::ReadTask task) { - LoadDatabaseIfNecessary(); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + CHECK(init_complete_) << "Init must be complete before running a DB task."; return (db_ && init_status_ == sql::INIT_OK) ? std::move(task).Run(db_.get()) : nullptr; } WebDatabaseBackend::~WebDatabaseBackend() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); ShutdownDatabase(); } void WebDatabaseBackend::LoadDatabaseIfNecessary() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (init_complete_ || db_path_.empty()) return; @@ -113,6 +124,7 @@ void WebDatabaseBackend::DatabaseErrorCallback(int error, sql::Statement* statement) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); sql::UmaHistogramSqliteResult("WebDatabase.DatabaseErrors", error); // We ignore any further error callbacks after the first catastrophic error. @@ -126,6 +138,7 @@ } void WebDatabaseBackend::Commit() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(db_); DCHECK_EQ(sql::INIT_OK, init_status_); db_->CommitTransaction();
diff --git a/components/webdata/common/web_database_backend.h b/components/webdata/common/web_database_backend.h index 1cd15f1..8e9770c 100644 --- a/components/webdata/common/web_database_backend.h +++ b/components/webdata/common/web_database_backend.h
@@ -13,6 +13,7 @@ #include "base/functional/callback_forward.h" #include "base/memory/ref_counted.h" #include "base/memory/ref_counted_delete_on_sequence.h" +#include "base/sequence_checker.h" #include "components/webdata/common/web_data_request_manager.h" #include "components/webdata/common/web_database_service.h" #include "components/webdata/common/webdata_export.h" @@ -21,14 +22,15 @@ class WebDatabaseTable; class WebDataRequest; class WebDataRequestManager; +class WebDatabaseService; namespace base { class SequencedTaskRunner; } -// WebDatabaseBackend handles all database tasks posted by -// WebDatabaseService. It is refcounted to allow asynchronous destruction on the -// DB thread. +// `WebDatabaseBackend` handles all database tasks posted by +// `WebDatabaseService`. It is refcounted to allow asynchronous destruction on +// the DB thread. class WEBDATA_EXPORT WebDatabaseBackend : public base::RefCountedDeleteOnSequence<WebDatabaseBackend> { @@ -38,8 +40,8 @@ virtual ~Delegate() {} // Invoked when the backend has finished loading the db. - // |status| is the result of initializing the db. - // |diagnostics| contains diagnostic information about the db, and it will + // `status` is the result of initializing the db. + // `diagnostics` contains diagnostic information about the db, and it will // only be populated when an error occurs. virtual void DBLoaded(sql::InitStatus status, const std::string& diagnostics) = 0; @@ -52,19 +54,36 @@ WebDatabaseBackend(const WebDatabaseBackend&) = delete; WebDatabaseBackend& operator=(const WebDatabaseBackend&) = delete; - // Must call only before InitDatabaseWithCallback. + // Obtains the database. Call on the DB sequence. If you must run tasks on + // this database, make sure you run them on the sequenced task runner returned + // from a call to `GetDbSequence` on the owning `WebDatabaseService`. + WebDatabase* database() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return db_.get(); + } + + protected: + friend class base::RefCountedDeleteOnSequence<WebDatabaseBackend>; + friend class base::DeleteHelper<WebDatabaseBackend>; + + virtual ~WebDatabaseBackend(); + + private: + friend class WebDatabaseService; + + // Must call only before `InitDatabase`. `AddTable` is called on the client + // sequence. void AddTable(std::unique_ptr<WebDatabaseTable> table); - // Initializes the database and notifies caller via callback when complete. - // Callback is called synchronously. + // Initializes the database. void InitDatabase(); // Shuts down the database. void ShutdownDatabase(); - // Task wrappers to update requests and and notify |request_manager_|. These + // Task wrappers to update requests and and notify `request_manager_`. These // are used in cases where the request is being made from the UI thread and an - // asyncronous callback is required to notify the client of |request|'s + // asyncronous callback is required to notify the client of `request`'s // completion. void DBWriteTaskWrapper(WebDatabaseService::WriteTask task, std::unique_ptr<WebDataRequest> request); @@ -80,15 +99,6 @@ return request_manager_; } - WebDatabase* database() { return db_.get(); } - - protected: - friend class base::RefCountedDeleteOnSequence<WebDatabaseBackend>; - friend class base::DeleteHelper<WebDatabaseBackend>; - - virtual ~WebDatabaseBackend(); - - private: // Opens the database file from the profile path if an init has not yet been // attempted. Separated from the constructor to ease construction/destruction // of this object on one thread but database access on the DB thread. @@ -106,14 +116,14 @@ // The tables that participate in managing the database. These are // owned here but other than that this class does nothing with // them. Their initialization is in whatever factory creates - // WebDatabaseService, and lookup by type is provided by the - // WebDatabase class. The tables need to be owned by this refcounted + // `WebDatabaseService`, and lookup by type is provided by the + // `WebDatabase` class. The tables need to be owned by this refcounted // object, or they themselves would need to be refcounted. Owning - // them here rather than having WebDatabase own them makes for - // easier unit testing of WebDatabase. + // them here rather than having `WebDatabase` own them makes for + // easier unit testing of `WebDatabase`. std::vector<std::unique_ptr<WebDatabaseTable>> tables_; - std::unique_ptr<WebDatabase> db_; + std::unique_ptr<WebDatabase> db_ GUARDED_BY_CONTEXT(sequence_checker_); // Keeps track of all pending requests made to the db. scoped_refptr<WebDataRequestManager> request_manager_ = @@ -137,6 +147,8 @@ // Delegate. See the class definition above for more information. std::unique_ptr<Delegate> delegate_; + + SEQUENCE_CHECKER(sequence_checker_); }; #endif // COMPONENTS_WEBDATA_COMMON_WEB_DATABASE_BACKEND_H_
diff --git a/components/webdata/common/web_database_service.cc b/components/webdata/common/web_database_service.cc index 2500aa13..51c3791 100644 --- a/components/webdata/common/web_database_service.cc +++ b/components/webdata/common/web_database_service.cc
@@ -41,7 +41,7 @@ scoped_refptr<base::SequencedTaskRunner> db_task_runner) : base::RefCountedDeleteOnSequence<WebDatabaseService>(ui_task_runner), path_(path), - db_task_runner_(db_task_runner) { + db_task_runner_(std::move(db_task_runner)) { DCHECK(ui_task_runner->RunsTasksInCurrentSequence()); DCHECK(db_task_runner_); } @@ -83,6 +83,10 @@ return web_db_backend_; } +scoped_refptr<base::SequencedTaskRunner> WebDatabaseService::GetDbSequence() { + return db_task_runner_; +} + void WebDatabaseService::ScheduleDBTask(const base::Location& from_here, WriteTask task) { DCHECK(web_db_backend_);
diff --git a/components/webdata/common/web_database_service.h b/components/webdata/common/web_database_service.h index 4875c6b0c..e019ca35 100644 --- a/components/webdata/common/web_database_service.h +++ b/components/webdata/common/web_database_service.h
@@ -51,8 +51,12 @@ using DBLoadErrorCallback = base::OnceCallback<void(sql::InitStatus, const std::string&)>; - // WebDatabaseService lives on the UI sequence and posts tasks to the DB - // sequence. |path| points to the WebDatabase file. + // `WebDatabaseService` lives on the UI sequence and posts tasks to the DB + // sequence. `path` points to the WebDatabase file. Do not run any database + // tasks on DB sequence after passing to this constructor. Instead, call + // `GetDbSequence` to obtain a valid sequenced task runner that ensures that + // tasks run in the correct order i.e. after any internal initialization has + // taken place. WebDatabaseService(const base::FilePath& path, scoped_refptr<base::SequencedTaskRunner> ui_task_runner, scoped_refptr<base::SequencedTaskRunner> db_task_runner); @@ -60,31 +64,38 @@ WebDatabaseService(const WebDatabaseService&) = delete; WebDatabaseService& operator=(const WebDatabaseService&) = delete; - // Adds |table| as a WebDatabaseTable that will participate in + // Adds |table| as a `WebDatabaseTable` that will participate in // managing the database, transferring ownership. All calls to this - // method must be made before |LoadDatabase| is called. - virtual void AddTable(std::unique_ptr<WebDatabaseTable> table); + // method must be made before `LoadDatabase` is called. + void AddTable(std::unique_ptr<WebDatabaseTable> table); // Initializes the web database service. - virtual void LoadDatabase(); + void LoadDatabase(); // Unloads the database and shuts down the service. - virtual void ShutdownDatabase(); + void ShutdownDatabase(); - // Gets a pointer to the WebDatabase (owned by WebDatabaseService). + // Gets a pointer to the `WebDatabase` (owned by `WebDatabaseService`). // TODO(caitkp): remove this method once SyncServices no longer depend on it. - virtual WebDatabase* GetDatabaseOnDB() const; + WebDatabase* GetDatabaseOnDB() const; - // Returns a pointer to the WebDatabaseBackend. + // Returns a pointer to the `WebDatabaseBackend`. scoped_refptr<WebDatabaseBackend> GetBackend() const; + // Obtain the sequence to execute any database tasks on. This should be called + // rather than using the `db_task_runner` passed into the constructor, because + // it might differ from the original `db_task_runner` passed into this class. + // Prefer simply calling one of the Schedule* methods to schedule database + // tasks to the DB sequence. + scoped_refptr<base::SequencedTaskRunner> GetDbSequence(); + // Schedule an update/write task on the DB sequence. - virtual void ScheduleDBTask(const base::Location& from_here, WriteTask task); + void ScheduleDBTask(const base::Location& from_here, WriteTask task); // Schedule a read task on the DB sequence. // Retrieves a WeakPtr to the |consumer| so that |consumer| does not have to - // outlive the WebDatabaseService. - virtual WebDataServiceBase::Handle ScheduleDBTaskWithResult( + // outlive the `WebDatabaseService`. + WebDataServiceBase::Handle ScheduleDBTaskWithResult( const base::Location& from_here, ReadTask task, WebDataServiceConsumer* consumer); @@ -92,7 +103,7 @@ // Cancel an existing request for a task on the DB sequence. // TODO(caitkp): Think about moving the definition of the Handle type to // somewhere else. - virtual void CancelRequest(WebDataServiceBase::Handle h); + void CancelRequest(WebDataServiceBase::Handle h); // Register a callback to be notified that the database has failed to load. // Multiple callbacks may be registered, and each will be called at most once @@ -109,7 +120,7 @@ using ErrorCallbacks = std::vector<DBLoadErrorCallback>; - virtual ~WebDatabaseService(); + ~WebDatabaseService(); void OnDatabaseLoadDone(sql::InitStatus status, const std::string& diagnostics);
diff --git a/components/webdata_services/web_data_service_wrapper.cc b/components/webdata_services/web_data_service_wrapper.cc index ec7ab90..368b9c2d 100644 --- a/components/webdata_services/web_data_service_wrapper.cc +++ b/components/webdata_services/web_data_service_wrapper.cc
@@ -141,8 +141,8 @@ profile_database_->LoadDatabase(); profile_autofill_web_data_ = - base::MakeRefCounted<autofill::AutofillWebDataService>( - profile_database_, ui_task_runner, db_task_runner); + base::MakeRefCounted<autofill::AutofillWebDataService>(profile_database_, + ui_task_runner); profile_autofill_web_data_->Init( base::BindOnce(show_error_callback, ERROR_LOADING_AUTOFILL)); @@ -153,12 +153,12 @@ plus_address_web_data_ = base::MakeRefCounted<plus_addresses::PlusAddressWebDataService>( - profile_database_, ui_task_runner, db_task_runner); + profile_database_, ui_task_runner); plus_address_web_data_->Init( base::BindOnce(show_error_callback, ERROR_LOADING_PLUS_ADDRESS)); - token_web_data_ = base::MakeRefCounted<TokenWebData>( - profile_database_, ui_task_runner, db_task_runner); + token_web_data_ = + base::MakeRefCounted<TokenWebData>(profile_database_, ui_task_runner); token_web_data_->Init( base::BindOnce(show_error_callback, ERROR_LOADING_TOKEN)); @@ -198,6 +198,8 @@ // On other (desktop) platforms, the account storage is in-memory. account_storage_path = base::FilePath(WebDatabase::kInMemoryPath); #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) + // Account database must run backend on same sequence as profile database. See + // comment in ChromeSyncClient::CreateDataTypeControllers. account_database_ = base::MakeRefCounted<WebDatabaseService>( account_storage_path, ui_task_runner, db_task_runner); account_database_->AddTable( @@ -207,8 +209,8 @@ account_database_->LoadDatabase(); account_autofill_web_data_ = - base::MakeRefCounted<autofill::AutofillWebDataService>( - account_database_, ui_task_runner, db_task_runner); + base::MakeRefCounted<autofill::AutofillWebDataService>(account_database_, + ui_task_runner); account_autofill_web_data_->Init( base::BindOnce(show_error_callback, ERROR_LOADING_ACCOUNT_AUTOFILL)); account_autofill_web_data_->GetAutofillBackend(
diff --git a/content/browser/accessibility/browser_accessibility_android.cc b/content/browser/accessibility/browser_accessibility_android.cc index c25ea4bc..f7e9f6a 100644 --- a/content/browser/accessibility/browser_accessibility_android.cc +++ b/content/browser/accessibility/browser_accessibility_android.cc
@@ -217,11 +217,27 @@ } bool BrowserAccessibilityAndroid::IsCollection() const { - return ui::IsTableLike(GetRole()); + switch (GetRole()) { + case ax::mojom::Role::kDescriptionList: + case ax::mojom::Role::kList: + case ax::mojom::Role::kListBox: + case ax::mojom::Role::kTree: + return true; + default: + return ui::IsTableLike(GetRole()); + } } bool BrowserAccessibilityAndroid::IsCollectionItem() const { - return ui::IsTableItem(GetRole()); + switch (GetRole()) { + case ax::mojom::Role::kListBoxOption: + case ax::mojom::Role::kListItem: + case ax::mojom::Role::kTerm: + case ax::mojom::Role::kTreeItem: + return true; + default: + return ui::IsCellOrTableHeader(GetRole()); + } } bool BrowserAccessibilityAndroid::IsContentInvalid() const {
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index 794f28f..9369d758 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -2958,6 +2958,10 @@ RunHtmlTest(FILE_PATH_LITERAL("min-role-tabbable-group.html")); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityMinRoleInGrid) { + RunHtmlTest(FILE_PATH_LITERAL("min-role-in-grid.html")); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityMissingRelationTargetsAddedLater) { RunAriaTest(FILE_PATH_LITERAL("missing-relation-targets-added-later.html"));
diff --git a/content/browser/attribution_reporting/attribution_storage_sql.cc b/content/browser/attribution_reporting/attribution_storage_sql.cc index 4bb04f2..f2cc4d7b 100644 --- a/content/browser/attribution_reporting/attribution_storage_sql.cc +++ b/content/browser/attribution_reporting/attribution_storage_sql.cc
@@ -815,6 +815,38 @@ return set_statement.Run(); } +namespace { + +// At least 1 destination must always be bound. When there are fewer than 3, +// NULL is used as a placeholder . `A IN (B,C,D)` evaluates to true iff A=B or +// A=C or A=D, since A is always non-NULL. Otherwise, it evaluates to NULL if +// any of B, C, or D is NULL, but that is fine, as the JOIN on the destination +// is only satisfied when the ON clause evaluates to true. +// +// https://www.sqlite.org/lang_expr.html#the_in_and_not_in_operators +void PrepareGetMatchingSourcesStatement( + sql::Statement& stmt, + base::span<const net::SchemefulSite> destinations) { + CHECK_GE(destinations.size(), 1u); + CHECK_LE(destinations.size(), 3u); + + stmt.BindString(0, destinations[0].Serialize()); + + if (destinations.size() >= 2) { + stmt.BindString(1, destinations[1].Serialize()); + } else { + stmt.BindNull(1); + } + + if (destinations.size() == 3) { + stmt.BindString(2, destinations[2].Serialize()); + } else { + stmt.BindNull(2); + } +} + +} // namespace + bool AttributionStorageSql::UpdateOrRemoveSourcesWithIncompatibleScopeFields( const StorableSource& pending_source, base::Time source_time) { @@ -833,18 +865,8 @@ 3, pending_source.common_info().reporting_origin().Serialize()); statement.BindTime(4, source_time); - // Bind the destination sites to the query. - int destination_index = 0; - const auto& destinations = registration.destination_set.destinations(); - for (const auto& destination : destinations) { - statement.BindString(destination_index, destination.Serialize()); - destination_index++; - } - // Fill the rest of the query bindings with the first destination. - while (destination_index <= 2) { - statement.BindString(destination_index, destinations.begin()->Serialize()); - destination_index++; - } + PrepareGetMatchingSourcesStatement( + statement, registration.destination_set.destinations()); const std::optional<AttributionScopesData>& pending_scopes_data = registration.attribution_scopes_data; @@ -931,12 +953,8 @@ std::vector<StoredSource::Id> source_ids_to_deactivate; std::vector<Record> records; - // We need to process one destination at a time, so we bind it to all 3 - // destination slots. - const std::string serialized_dest = destination.Serialize(); - statement.BindString(0, serialized_dest); - statement.BindString(1, serialized_dest); - statement.BindString(2, serialized_dest); + PrepareGetMatchingSourcesStatement(statement, + base::span_from_ref(destination)); while (statement.Step()) { ASSIGN_OR_RETURN(std::optional<AttributionScopesData> scopes_data, @@ -990,8 +1008,6 @@ std::vector<StoredSource::Id>& source_ids_to_delete, std::vector<StoredSource::Id>& source_ids_to_deactivate) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - const SuitableOrigin& destination_origin = trigger.destination_origin(); - const SuitableOrigin& reporting_origin = trigger.reporting_origin(); SCOPED_UMA_HISTOGRAM_TIMER("Conversions.Storage.FindMatchingSourceTime"); @@ -1003,12 +1019,11 @@ sql::Statement statement(db_.GetCachedStatement( SQL_FROM_HERE, attribution_queries::kGetMatchingSourcesSql)); - const std::string serialized_dest = - net::SchemefulSite(destination_origin).Serialize(); - statement.BindString(0, serialized_dest); - statement.BindString(1, serialized_dest); - statement.BindString(2, serialized_dest); - statement.BindString(3, reporting_origin.Serialize()); + const net::SchemefulSite destination(trigger.destination_origin()); + PrepareGetMatchingSourcesStatement(statement, + base::span_from_ref(destination)); + + statement.BindString(3, trigger.reporting_origin().Serialize()); statement.BindTime(4, trigger_time); // The highest-priority source with at least one matching scope will be
diff --git a/content/browser/bluetooth/bluetooth_metrics.h b/content/browser/bluetooth/bluetooth_metrics.h index f2baf6ae..e4b08f9 100644 --- a/content/browser/bluetooth/bluetooth_metrics.h +++ b/content/browser/bluetooth/bluetooth_metrics.h
@@ -58,9 +58,11 @@ JNI_ENVIRONMENT = 18, JNI_THREAD_ATTACH = 19, WAKELOCK = 20, + UNEXPECTED_STATE = 21, + SOCKET_ERROR = 22, // Note: Add new ConnectGATT outcomes immediately above this line. Make sure - // to update the enum list in tools/metrics/histograms/histograms.xml - // accordingly. + // to update the enum list in + // tools/metrics/histograms/metadata/bluetooth/enums.xml accordingly. COUNT };
diff --git a/content/browser/bluetooth/web_bluetooth_service_impl.cc b/content/browser/bluetooth/web_bluetooth_service_impl.cc index 2b0a61b..21b1fba 100644 --- a/content/browser/bluetooth/web_bluetooth_service_impl.cc +++ b/content/browser/bluetooth/web_bluetooth_service_impl.cc
@@ -277,6 +277,12 @@ case device::BluetoothDevice::ERROR_WAKELOCK: RecordConnectGATTOutcome(UMAConnectGATTOutcome::WAKELOCK); return blink::mojom::WebBluetoothResult::CONNECT_WAKELOCK; + case device::BluetoothDevice::ERROR_UNEXPECTED_STATE: + RecordConnectGATTOutcome(UMAConnectGATTOutcome::UNEXPECTED_STATE); + return blink::mojom::WebBluetoothResult::CONNECT_UNEXPECTED_STATE; + case device::BluetoothDevice::ERROR_SOCKET: + RecordConnectGATTOutcome(UMAConnectGATTOutcome::SOCKET_ERROR); + return blink::mojom::WebBluetoothResult::CONNECT_SOCKET_ERROR; case BluetoothDevice::NUM_CONNECT_ERROR_CODES: NOTREACHED_IN_MIGRATION(); return blink::mojom::WebBluetoothResult::CONNECT_UNKNOWN_FAILURE;
diff --git a/content/browser/child_process_launcher.cc b/content/browser/child_process_launcher.cc index e3add3d..cc173ad1 100644 --- a/content/browser/child_process_launcher.cc +++ b/content/browser/child_process_launcher.cc
@@ -16,6 +16,7 @@ #include "base/memory/unsafe_shared_memory_region.h" #include "base/process/launch.h" #include "base/time/time.h" +#include "base/trace_event/trace_event.h" #include "base/tracing/protos/chrome_track_event.pbzero.h" #include "base/types/expected.h" #include "base/types/optional_util.h" @@ -111,6 +112,7 @@ #endif { DCHECK_CURRENTLY_ON(BrowserThread::UI); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("startup", "ChildProcessLauncher", this); #if BUILDFLAG(IS_WIN) should_launch_elevated_ = delegate->ShouldLaunchElevated(); @@ -167,6 +169,8 @@ #endif int error_code) { DCHECK_CURRENTLY_ON(BrowserThread::UI); + TRACE_EVENT_NESTABLE_ASYNC_END0("startup", "ChildProcessLauncher", this); + starting_ = false; process_ = std::move(process);
diff --git a/content/browser/child_process_launcher_helper.cc b/content/browser/child_process_launcher_helper.cc index b455f0c..e01e1e7d 100644 --- a/content/browser/child_process_launcher_helper.cc +++ b/content/browser/child_process_launcher_helper.cc
@@ -339,17 +339,23 @@ } if (is_synchronous_launch) { - PostLaunchOnLauncherThread(std::move(process), launch_result); + // The LastError is set on the launcher thread, but needs to be transferred + // to the Client thread. + PostLaunchOnLauncherThread(std::move(process), +#if BUILDFLAG(IS_WIN) + ::GetLastError(), +#endif + launch_result); } } void ChildProcessLauncherHelper::PostLaunchOnLauncherThread( ChildProcessLauncherHelper::Process process, +#if BUILDFLAG(IS_WIN) + DWORD last_error, +#endif int launch_result) { #if BUILDFLAG(IS_WIN) - // The LastError is set on the launcher thread, but needs to be transferred to - // the Client thread. - DWORD last_error = ::GetLastError(); const bool launch_elevated = delegate_->ShouldLaunchElevated(); #else const bool launch_elevated = false;
diff --git a/content/browser/child_process_launcher_helper.h b/content/browser/child_process_launcher_helper.h index 6577400b..8f503a9 100644 --- a/content/browser/child_process_launcher_helper.h +++ b/content/browser/child_process_launcher_helper.h
@@ -186,6 +186,14 @@ bool* is_synchronous_launch, int* launch_result); +#if BUILDFLAG(IS_WIN) + // This is the callback target that handles the result from + // StartSandboxedProcess(). + void FinishStartSandboxedProcessOnLauncherThread(base::Process process, + DWORD last_error, + int launch_result); +#endif + // Called right after the process has been launched, whether it was created // successfully or not. If the process launch is asynchronous, the process may // not yet be created. Platform specific. @@ -195,6 +203,9 @@ // Called once the process has been created, successfully or not. void PostLaunchOnLauncherThread(ChildProcessLauncherHelper::Process process, +#if BUILDFLAG(IS_WIN) + DWORD last_error, +#endif int launch_result); // Posted by PostLaunchOnLauncherThread onto the client thread.
diff --git a/content/browser/child_process_launcher_helper_win.cc b/content/browser/child_process_launcher_helper_win.cc index 2a01487..cb0e7d5 100644 --- a/content/browser/child_process_launcher_helper_win.cc +++ b/content/browser/child_process_launcher_helper_win.cc
@@ -156,11 +156,24 @@ : LAUNCH_RESULT_FAILURE; return process; } - ChildProcessLauncherHelper::Process process; - *launch_result = - StartSandboxedProcess(delegate_.get(), *command_line(), - options->handles_to_inherit, &process.process); - return process; + *is_synchronous_launch = false; + *launch_result = StartSandboxedProcess( + delegate_.get(), *command_line(), options->handles_to_inherit, + base::BindOnce(&ChildProcessLauncherHelper:: + FinishStartSandboxedProcessOnLauncherThread, + this)); + return ChildProcessLauncherHelper::Process(); +} + +void ChildProcessLauncherHelper::FinishStartSandboxedProcessOnLauncherThread( + base::Process process, + DWORD last_error, + int launch_result) { + DCHECK(CurrentlyOnProcessLauncherTaskRunner()); + ChildProcessLauncherHelper::Process process_wrapper; + process_wrapper.process = std::move(process); + PostLaunchOnLauncherThread(std::move(process_wrapper), last_error, + launch_result); } void ChildProcessLauncherHelper::AfterLaunchOnLauncherThread(
diff --git a/content/browser/file_system_access/file_path_watcher/file_path_watcher_fsevents.cc b/content/browser/file_system_access/file_path_watcher/file_path_watcher_fsevents.cc index 2c21393..143fcc0 100644 --- a/content/browser/file_system_access/file_path_watcher/file_path_watcher_fsevents.cc +++ b/content/browser/file_system_access/file_path_watcher/file_path_watcher_fsevents.cc
@@ -315,7 +315,9 @@ std::vector<FSEventStreamEventId> coalesced_event_ids; bool coalesce_target_deletion = coalesce_next_target_deletion_; + bool coalesce_target_creation = coalesce_next_target_creation_; coalesce_next_target_deletion_ = false; + coalesce_next_target_creation_ = false; for (const auto& [event_id, event] : events) { const auto& [event_flags, event_path, event_inode] = event; @@ -331,8 +333,16 @@ // The `kFSEventStreamEventFlagRootChanged` flag signals that there has been // a change along the root path. - if ((event_flags & kFSEventStreamEventFlagRootChanged) && - event_path == target) { + if (event_flags & kFSEventStreamEventFlagRootChanged) { + // The event path should always be the same path as the target for a root + // changed event. In the case that it's not, skip processing the event. + if (event_path != target) { + // TODO(b/362494756): Cleanup usage of this macro once the File System + // Change Observers feature is rolled out. + DUMP_WILL_BE_NOTREACHED(); + continue; + } + // If the target path does not exist, either the target or one of its // parent directories have been deleted or renamed. struct stat buffer; @@ -341,24 +351,20 @@ // the following, duplicate delete event. coalesce_next_target_deletion_ = true; FilePathWatcher::ChangeInfo change_info = { - file_path_type, FilePathWatcher::ChangeType::kDeleted, event_path}; - callback_.Run(std::move(change_info), - report_modified_path_ ? event_path : target, + file_path_type, FilePathWatcher::ChangeType::kDeleted, target}; + callback_.Run(std::move(change_info), target, /*error=*/false); continue; } - // TODO(b/357118831): Add handling for rename events along the dir path to - // `target`, and report the change type accordingly depending on the move - // type. According to FSEvents, this occurs when the - // `kFSEventStreamEventFlagRootChanged` flag is present and the event id - // is equal to 0. Differentiate between a true rename along the path to - // target and the target itself being created initially by checking if the - // next event is a 'create' event on the target path. - // - // Otherwise, if the target has been created, ignore the "root change" - // event and fall through to report only the following create event on the - // next call to `DispatchEvents`. + // Otherwise, a rename has occurred on the target path (which represents a + // move into-scope), or the target has been created initially. Both + // scenarios are reported as 'create' events. + coalesce_next_target_creation_ = true; + FilePathWatcher::ChangeInfo change_info = { + file_path_type, FilePathWatcher::ChangeType::kCreated, target}; + callback_.Run(std::move(change_info), target, + /*error=*/false); continue; } @@ -382,6 +388,7 @@ /*error=*/false); continue; } + // Based on testing, moves within-scope for FSEvents will have // consecutive event ids that differ by 1, and the event with the higher // event id represents the "moved to" part of a move event. This allows @@ -452,6 +459,15 @@ bool exists = (stat(event_path.value().c_str(), &file_stat) == 0) && (file_stat.st_ino == event_inode.value_or(0)); + // If we've already reported a create event resulting from a move + // into-scope for the target path, skip reporting a duplicate create + // event which has already been reported as a result of the previous root + // changed event. + if (exists && event_path == target && coalesce_target_creation) { + coalesce_next_target_creation_ = false; + continue; + } + // If the current event's inode exists, the underlying file or // directory exists. This signals a move into-scope and is reported as // a 'created event. Otherwise, the event is reported as a 'deleted' @@ -478,7 +494,7 @@ if (event_flags & kFSEventStreamEventFlagItemRemoved) { // Skip over coalesced delete events, that have already been reported for // a delete event on the target path. - if (coalesce_target_deletion) { + if (coalesce_target_deletion && event_path == target) { coalesce_next_target_deletion_ = false; continue; } @@ -515,6 +531,13 @@ // `kFSEventStreamEventFlagItemModified` flag are present in the same batch // of `event_flags`. if (event_flags & kFSEventStreamEventFlagItemCreated) { + // If the current event is for the target path, skip reporting a duplicate + // create event, since we've already reported one earlier as a result of + // the previous root changed event. + if (coalesce_target_creation && event_path == target) { + coalesce_next_target_creation_ = false; + continue; + } FilePathWatcher::ChangeInfo change_info = { file_path_type, FilePathWatcher::ChangeType::kCreated, event_path}; callback_.Run(std::move(change_info),
diff --git a/content/browser/file_system_access/file_path_watcher/file_path_watcher_fsevents.h b/content/browser/file_system_access/file_path_watcher/file_path_watcher_fsevents.h index ce4922ba..092a7d6 100644 --- a/content/browser/file_system_access/file_path_watcher/file_path_watcher_fsevents.h +++ b/content/browser/file_system_access/file_path_watcher/file_path_watcher_fsevents.h
@@ -104,9 +104,10 @@ // (Only accessed from the libdispatch queue.) base::FilePath resolved_target_; - // Signals whether to check for a target deletion event, and coalesce the - // event if needed. + // Signals whether to check for a target deletion or creation event, and + // coalesce the event if needed. bool coalesce_next_target_deletion_ = false; + bool coalesce_next_target_creation_ = false; // Backend stream we receive event callbacks from (strong reference). // (Only accessed from the libdispatch queue.)
diff --git a/content/browser/file_system_access/file_path_watcher/file_path_watcher_unittest.cc b/content/browser/file_system_access/file_path_watcher/file_path_watcher_unittest.cc index 7f0b6bd3..fe81b53c 100644 --- a/content/browser/file_system_access/file_path_watcher/file_path_watcher_unittest.cc +++ b/content/browser/file_system_access/file_path_watcher/file_path_watcher_unittest.cc
@@ -183,6 +183,7 @@ testing::Field(&FilePathWatcher::ChangeInfo::change_type, change_type)); }; + #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_ANDROID) || \ BUILDFLAG(IS_WIN) inline constexpr auto IsFile = []() { @@ -2567,8 +2568,13 @@ delegate.RunUntilEventsMatch(matcher); } -// TODO(b/357118831): Re-enable once implementation for handling a rename on -// the root dir path is complete. +// TODO(crbug.com/362715979): This test is disabled on Mac due to unexpected, +// test-specific behavior - we receive no FSEvents events when the ancestor dir +// of the watched target is moved out-of-scope. Since we never receive events +// from FSEvents, it's impossible for us to report the expected 'delete' event. +// This behavior does not repro in manual testing. In manual tests of this use +// case, we receive all events as expected, including the equivalent 'delete' +// event that never arrives in the unittest. #if !BUILDFLAG(IS_MAC) TEST_P(FilePathWatcherWithChangeInfoTest, MoveParent) { base::FilePath dir(temp_dir_.GetPath().AppendASCII("dir")); @@ -2625,9 +2631,8 @@ file_delegate.RunUntilEventsMatch(file_delegate_matcher); subdir_delegate.RunUntilEventsMatch(subdir_delegate_matcher); } +#endif // !BUILDFLAG(IS_MAC) -// TODO(b/357118831): Re-enable once implementation for handling a rename on -// the root dir path is complete. TEST_P(FilePathWatcherWithChangeInfoTest, MoveChild) { base::FilePath source_dir(temp_dir_.GetPath().AppendASCII("source")); base::FilePath source_subdir(source_dir.AppendASCII("subdir")); @@ -2641,16 +2646,19 @@ const auto each_event_matcher = testing::Each(testing::AllOf( testing::Not(HasErrored()), IsType(FilePathWatcher::ChangeType::kCreated), HasNoMovedFromPath())); - const auto file_delegate_sequence_matcher = - testing::ElementsAre(testing::AllOf(HasPath(dest_file), IsMovedFile(), - HasModifiedPath(dest_file))); #if BUILDFLAG(IS_MAC) // Events for changes on the root path are always reported as 'unknown' by // FSEvents. + const auto file_delegate_sequence_matcher = + testing::ElementsAre(testing::AllOf( + HasPath(dest_file), IsUnknownPathType(), HasModifiedPath(dest_file))); const auto subdir_delegate_sequence_matcher = testing::ElementsAre( testing::AllOf(HasPath(dest_subdir), IsUnknownPathType(), HasModifiedPath(dest_subdir))); #else + const auto file_delegate_sequence_matcher = + testing::ElementsAre(testing::AllOf(HasPath(dest_file), IsMovedFile(), + HasModifiedPath(dest_file))); const auto subdir_delegate_sequence_matcher = testing::ElementsAre(testing::AllOf(HasPath(dest_subdir), IsDirectory(), HasModifiedPath(dest_subdir))); @@ -2677,7 +2685,6 @@ file_delegate.RunUntilEventsMatch(file_delegate_matcher); subdir_delegate.RunUntilEventsMatch(subdir_delegate_matcher); } -#endif // !BUILDFLAG(IS_MAC) TEST_P(FilePathWatcherWithChangeInfoTest, MoveChildWithinWatchedScope) { base::FilePath dir(temp_dir_.GetPath().AppendASCII("dir")); @@ -3330,7 +3337,7 @@ ASSERT_TRUE(CreateDirectory(test_file())); delegate.RunUntilEventsMatch(matcher); } -#endif +#endif // !BUILDFLAG(IS_MAC) #endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_WIN)
diff --git a/content/browser/navigation_browsertest.cc b/content/browser/navigation_browsertest.cc index 9b3aea2..914ce5d 100644 --- a/content/browser/navigation_browsertest.cc +++ b/content/browser/navigation_browsertest.cc
@@ -9521,8 +9521,14 @@ // Verify that when a cross-origin subframe initiates a top-level navigation to // a same-origin (with respect to itself) URL, that the visual properties // are invalidated correctly. +// TODO(https://crbug.com/361299696): Flaky on Fuchsia and ChromeOS Ash. +#if BUILDFLAG(IS_FUCHSIA) || BUILDFLAG(IS_CHROMEOS_ASH) +#define MAYBE_RemoteToLocalTransition DISABLED_RemoteToLocalTransition +#else +#define MAYBE_RemoteToLocalTransition RemoteToLocalTransition +#endif IN_PROC_BROWSER_TEST_F(VisualPropertiesSynchronization, - RemoteToLocalTransition) { + MAYBE_RemoteToLocalTransition) { GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html")); GURL url_b_top_level(embedded_test_server()->GetURL("b.com", "/title1.html")); GURL url_b_iframe(embedded_test_server()->GetURL("b.com", "/title2.html"));
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc index 89a510a..1528945 100644 --- a/content/browser/web_contents/web_contents_impl.cc +++ b/content/browser/web_contents/web_contents_impl.cc
@@ -4833,18 +4833,23 @@ this, std::move(new_contents), params.target_url, params.disposition, *params.features, has_user_gesture, &was_blocked); - // The delegate may delete |new_contents_impl| during AddNewContents(). - // If that occurs and there isn't a replacement contents returned, exit. - // Otherwise, use the replacement web contents that was navigated in. - if (web_contents_navigated != nullptr && weak_new_contents) { - CHECK(web_contents_navigated == weak_new_contents.get()); - } - - if (!weak_new_contents) { - if (web_contents_navigated == nullptr) { - return nullptr; + if (base::FeatureList::IsEnabled(features::kPwaNavigationCapturing)) { + // The delegate may delete |new_contents_impl| during AddNewContents(). + // If that occurs and there isn't a replacement contents returned, exit. + // Otherwise, use the replacement web contents that was navigated in. + if (web_contents_navigated != nullptr && weak_new_contents) { + CHECK(web_contents_navigated == weak_new_contents.get()); } - contents_to_load = static_cast<WebContentsImpl*>(web_contents_navigated); + + if (!weak_new_contents) { + if (web_contents_navigated == nullptr) { + return nullptr; + } + contents_to_load = + static_cast<WebContentsImpl*>(web_contents_navigated); + } + } else if (!weak_new_contents) { + return nullptr; } }
diff --git a/content/browser/webid/digital_credentials/digital_identity_request_impl.cc b/content/browser/webid/digital_credentials/digital_identity_request_impl.cc index 5217d8f..9e9fd97 100644 --- a/content/browser/webid/digital_credentials/digital_identity_request_impl.cc +++ b/content/browser/webid/digital_credentials/digital_identity_request_impl.cc
@@ -4,9 +4,10 @@ #include "content/browser/webid/digital_credentials/digital_identity_request_impl.h" +#include <memory> + #include "base/functional/callback.h" #include "base/functional/callback_forward.h" -#include "base/json/json_writer.h" #include "base/metrics/histogram_functions.h" #include "base/types/optional_util.h" #include "base/values.h" @@ -267,23 +268,23 @@ std::move(callback_).Run(status, base::OptionalFromExpected(response)); } -std::string BuildRequest(blink::mojom::DigitalCredentialProviderPtr provider) { +std::optional<base::Value> BuildRequest( + blink::mojom::DigitalCredentialProviderPtr provider) { auto result = Value::Dict(); if (!provider->protocol) { - return ""; + return std::nullopt; } result.Set("protocol", *provider->protocol); if (!provider->request) { - return ""; + return std::nullopt; } result.Set("request", *provider->request); base::Value::Dict out = Value::Dict().Set("providers", Value::List().Append(std::move(result))); - return WriteJsonWithOptions(out, base::JSONWriter::OPTIONS_PRETTY_PRINT) - .value_or(""); + return base::Value(std::move(out)); } void DigitalIdentityRequestImpl::Request( @@ -326,11 +327,9 @@ Protocol protocol = GetProtocol(digital_credential_provider->protocol); std::optional<std::string> request_json_string = digital_credential_provider->request; - - std::string request_to_send = + std::optional<base::Value> request_to_send = BuildRequest(std::move(digital_credential_provider)); - - if (!request_json_string || request_to_send.empty()) { + if (!request_json_string || !request_to_send) { CompleteRequest(base::unexpected(RequestStatusForMetrics::kErrorOther)); return; } @@ -339,7 +338,7 @@ *request_json_string, base::BindOnce(&DigitalIdentityRequestImpl::OnRequestJsonParsed, weak_ptr_factory_.GetWeakPtr(), protocol, - std::move(request_to_send))); + std::move(*request_to_send))); } void DigitalIdentityRequestImpl::Abort() { @@ -354,7 +353,7 @@ void DigitalIdentityRequestImpl::OnRequestJsonParsed( Protocol protocol, - std::string request_to_send, + base::Value request_to_send, data_decoder::DataDecoder::ValueOrError parsed_result) { if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kUseFakeUIForDigitalIdentity)) { @@ -385,7 +384,8 @@ provider_.get(), protocol, parsed_result); if (!interstitial_type) { - OnInterstitialDone(request_to_send, RequestStatusForMetrics::kSuccess); + OnInterstitialDone(std::move(request_to_send), + RequestStatusForMetrics::kSuccess); return; } @@ -394,11 +394,12 @@ *WebContents::FromRenderFrameHost(&render_frame_host()), origin(), *interstitial_type, base::BindOnce(&DigitalIdentityRequestImpl::OnInterstitialDone, - weak_ptr_factory_.GetWeakPtr(), request_to_send)); + weak_ptr_factory_.GetWeakPtr(), + std::move(request_to_send))); } void DigitalIdentityRequestImpl::OnInterstitialDone( - const std::string& request_to_send, + base::Value request_to_send, RequestStatusForMetrics status_after_interstitial) { if (status_after_interstitial != RequestStatusForMetrics::kSuccess) { CompleteRequest(base::unexpected(status_after_interstitial)); @@ -407,7 +408,7 @@ provider_->Request( WebContents::FromRenderFrameHost(&render_frame_host()), origin(), - request_to_send, + std::move(request_to_send), base::BindOnce(&DigitalIdentityRequestImpl::CompleteRequest, weak_ptr_factory_.GetWeakPtr())); }
diff --git a/content/browser/webid/digital_credentials/digital_identity_request_impl.h b/content/browser/webid/digital_credentials/digital_identity_request_impl.h index 49bb88f..45a2ec6 100644 --- a/content/browser/webid/digital_credentials/digital_identity_request_impl.h +++ b/content/browser/webid/digital_credentials/digital_identity_request_impl.h
@@ -67,7 +67,7 @@ // Called when the request JSON has been parsed. void OnRequestJsonParsed( Protocol protocol, - std::string request_to_send, + base::Value request_to_send, data_decoder::DataDecoder::ValueOrError parsed_result); // Called after fetching the user's identity. Shows an interstitial if needed. @@ -80,7 +80,7 @@ // Called when the user has fulfilled the interstitial requirement. Will be // called immediately after OnRequestJsonParsed() if no interstitial is // needed. - void OnInterstitialDone(const std::string& request_to_send, + void OnInterstitialDone(base::Value request_to_send, DigitalIdentityProvider::RequestStatusForMetrics status_after_interstitial);
diff --git a/content/browser/webid/test/mock_digital_identity_provider.h b/content/browser/webid/test/mock_digital_identity_provider.h index edc245c..4cad236 100644 --- a/content/browser/webid/test/mock_digital_identity_provider.h +++ b/content/browser/webid/test/mock_digital_identity_provider.h
@@ -36,7 +36,7 @@ Request, (WebContents*, const url::Origin& origin, - const std::string& request, + const base::Value request, DigitalIdentityCallback), (override)); };
diff --git a/content/browser/webid/test/stub_digital_identity_provider.cc b/content/browser/webid/test/stub_digital_identity_provider.cc index 67bd082..6c93a17 100644 --- a/content/browser/webid/test/stub_digital_identity_provider.cc +++ b/content/browser/webid/test/stub_digital_identity_provider.cc
@@ -30,7 +30,7 @@ void StubDigitalIdentityProvider::Request(WebContents*, const url::Origin& origin, - const std::string& request, + base::Value request, DigitalIdentityCallback) {} } // namespace content
diff --git a/content/browser/webid/test/stub_digital_identity_provider.h b/content/browser/webid/test/stub_digital_identity_provider.h index e46011b..ab38a4b8 100644 --- a/content/browser/webid/test/stub_digital_identity_provider.h +++ b/content/browser/webid/test/stub_digital_identity_provider.h
@@ -26,7 +26,7 @@ DigitalIdentityInterstitialCallback callback) override; void Request(WebContents*, const url::Origin& origin, - const std::string& request, + base::Value request, DigitalIdentityCallback) override; };
diff --git a/content/browser/webid/webid_browsertest.cc b/content/browser/webid/webid_browsertest.cc index cd44d4a..213d333 100644 --- a/content/browser/webid/webid_browsertest.cc +++ b/content/browser/webid/webid_browsertest.cc
@@ -136,11 +136,13 @@ std::unique_ptr<HttpResponse> HandleRequest(const HttpRequest& request) { // RP files are fetched from the /test base directory. Assume anything // to other paths is directed to the IdP. - if (request.relative_url.rfind("/test", 0) == 0) + if (request.relative_url.rfind("/test", 0) == 0) { return nullptr; + } - if (request.relative_url.rfind("/header/", 0) == 0) + if (request.relative_url.rfind("/header/", 0) == 0) { return BuildIdpHeaderResponse(request); + } if (request.all_headers.find(kIdpForbiddenHeader) != std::string::npos) { EXPECT_EQ(request.headers.at(kIdpForbiddenHeader), "?1"); @@ -1231,17 +1233,15 @@ return EvalJsAndReturnToken(execution_target, script); } -// Leniently parses string as JSON and compares parsed JSON. -MATCHER_P(JsonMatchesLenient, ref, "") { +// Leniently parses the input string as JSON and compares it to already-parsed +// JSON. +MATCHER_P(JsonMatches, ref, "") { int json_parsing_options = base::JSONParserOptions::JSON_PARSE_CHROMIUM_EXTENSIONS | base::JSONParserOptions::JSON_ALLOW_TRAILING_COMMAS; auto ref_json = base::JSONReader::ReadAndReturnValueWithError(ref, json_parsing_options); - auto arg_json = - base::JSONReader::ReadAndReturnValueWithError(arg, json_parsing_options); - return ref_json.has_value() && arg_json.has_value() && - (ref_json.value() == arg_json.value()); + return ref_json.has_value() && (ref_json.value() == arg); } // Test that a Verifiable Credential can be requested via the navigator.identity @@ -1277,8 +1277,7 @@ // JSON comparison in IsJson below. base::RemoveChars(request, "\n ", &json); - EXPECT_CALL(*digital_identity_provider, - Request(_, _, JsonMatchesLenient(json), _)) + EXPECT_CALL(*digital_identity_provider, Request(_, _, JsonMatches(json), _)) .WillOnce(WithArg<3>( [kIdentityProviderResponse]( DigitalIdentityProvider::DigitalIdentityCallback callback) {
diff --git a/content/common/sandbox_init_win.cc b/content/common/sandbox_init_win.cc index b96d6a87..38733269 100644 --- a/content/common/sandbox_init_win.cc +++ b/content/common/sandbox_init_win.cc
@@ -24,7 +24,7 @@ SandboxedProcessLauncherDelegate* delegate, const base::CommandLine& target_command_line, const base::HandlesToInheritVector& handles_to_inherit, - base::Process* process) { + sandbox::StartSandboxedProcessCallback result_callback) { std::string type_str = target_command_line.GetSwitchValueASCII(switches::kProcessType); TRACE_EVENT1("startup", "StartProcessWithAccess", "type", type_str); @@ -45,7 +45,8 @@ } return sandbox::policy::SandboxWin::StartSandboxedProcess( - full_command_line, handles_to_inherit, delegate, process); + full_command_line, handles_to_inherit, delegate, + std::move(result_callback)); } } // namespace content
diff --git a/content/public/browser/digital_identity_provider.h b/content/public/browser/digital_identity_provider.h index 2ae14a0..8f2eb87 100644 --- a/content/public/browser/digital_identity_provider.h +++ b/content/public/browser/digital_identity_provider.h
@@ -69,7 +69,7 @@ const base::expected<std::string, RequestStatusForMetrics>&)>; virtual void Request(WebContents* web_contents, const url::Origin& origin, - const std::string& request, + base::Value request, DigitalIdentityCallback callback) = 0; protected:
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 09ce04e36..955455a 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -210,7 +210,7 @@ // go/cdm-storage-migration-details for more details. BASE_FEATURE(kCdmStorageDatabaseMigration, "CdmStorageDatabaseMigration", - base::FEATURE_ENABLED_BY_DEFAULT); + base::FEATURE_DISABLED_BY_DEFAULT); // Clear the window.name property for the top-level cross-site navigations that // swap BrowsingContextGroups(BrowsingInstances). @@ -1342,6 +1342,24 @@ base::FEATURE_ENABLED_BY_DEFAULT); #endif // defined(WEBRTC_USE_PIPEWIRE) +// Default amount of days after which the global navigation capturing IPH +// guardrails are cleared from storage. +const base::FeatureParam<int> kNavigationCapturingIPHGuardrailStorageDuration{ + &kPwaNavigationCapturing, "link_capturing_guardrail_storage_duration", 30}; + +BASE_FEATURE(kPwaNavigationCapturing, + "PwaNavigationCapturing", + base::FEATURE_DISABLED_BY_DEFAULT); +const base::FeatureParam<CapturingState>::Option kNavigationCapturingParams[] = + {{CapturingState::kDefaultOn, "on_by_default"}, + {CapturingState::kDefaultOff, "off_by_default"}, + {CapturingState::kReimplDefaultOn, "reimpl_default_on"}, + {CapturingState::kReimplDefaultOff, "reimpl_default_off"}}; + +const base::FeatureParam<CapturingState> kNavigationCapturingDefaultState{ + &kPwaNavigationCapturing, "link_capturing_state", + CapturingState::kDefaultOn, &kNavigationCapturingParams}; + namespace { enum class VideoCaptureServiceConfiguration { kEnabledForOutOfProcess,
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index 35664c0..1bd4d33 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -301,6 +301,23 @@ CONTENT_EXPORT BASE_DECLARE_FEATURE(kWebRtcPipeWireCapturer); #endif // defined(WEBRTC_USE_PIPEWIRE) +// Number of days to "store" IPH guardrails for navigation captured app launches +// till they are cleared. +CONTENT_EXPORT extern const base::FeatureParam<int> + kNavigationCapturingIPHGuardrailStorageDuration; + +// Enables user link capturing on all desktop platforms. +CONTENT_EXPORT BASE_DECLARE_FEATURE(kPwaNavigationCapturing); +enum class CapturingState { + kDefaultOn = 0, + kDefaultOff = 1, + kReimplDefaultOn = 2, + kReimplDefaultOff = 3 +}; +// If links should be captured by apps by default. +CONTENT_EXPORT extern const base::FeatureParam<CapturingState> + kNavigationCapturingDefaultState; + // DON'T ADD RANDOM STUFF HERE. Put it in the main section above in // alphabetical order, or in one of the ifdefs (also in order in each section).
diff --git a/content/public/common/sandbox_init_win.h b/content/public/common/sandbox_init_win.h index 9bb4b30..5c24090 100644 --- a/content/public/common/sandbox_init_win.h +++ b/content/public/common/sandbox_init_win.h
@@ -6,12 +6,12 @@ #define CONTENT_PUBLIC_COMMON_SANDBOX_INIT_WIN_H_ #include "base/process/launch.h" +#include "base/process/process.h" #include "content/common/content_export.h" #include "sandbox/win/src/sandbox_types.h" namespace base { class CommandLine; -class Process; } // namespace base namespace content { @@ -30,7 +30,7 @@ SandboxedProcessLauncherDelegate* delegate, const base::CommandLine& target_command_line, const base::HandlesToInheritVector& handles_to_inherit, - base::Process* process); + sandbox::StartSandboxedProcessCallback result_callback); } // namespace content
diff --git a/content/test/content_test_bundle_data.filelist b/content/test/content_test_bundle_data.filelist index c5ac671..4473c92 100644 --- a/content/test/content_test_bundle_data.filelist +++ b/content/test/content_test_bundle_data.filelist
@@ -4380,6 +4380,8 @@ data/accessibility/html/micro-clearfix-hack-expected-blink.txt data/accessibility/html/micro-clearfix-hack.html data/accessibility/html/min-role-expected-blink.txt +data/accessibility/html/min-role-in-grid-expected-blink.txt +data/accessibility/html/min-role-in-grid.html data/accessibility/html/min-role-tabbable-group-expected-blink.txt data/accessibility/html/min-role-tabbable-group.html data/accessibility/html/min-role.html
diff --git a/content/test/data/accessibility/html/min-role-in-grid-expected-blink.txt b/content/test/data/accessibility/html/min-role-in-grid-expected-blink.txt new file mode 100644 index 0000000..73323df --- /dev/null +++ b/content/test/data/accessibility/html/min-role-in-grid-expected-blink.txt
@@ -0,0 +1,13 @@ +rootWebArea +++genericContainer ignored +++++genericContainer ignored +++++++grid +++++++++genericContainer ignored +++++++++++group +++++++++++++row name='55 Cats' +++++++++++++++gridCell name='55' +++++++++++++++++staticText name='55' +++++++++++++++++++inlineTextBox name='55' +++++++++++++++gridCell name='Cats' +++++++++++++++++staticText name='Cats' +++++++++++++++++++inlineTextBox name='Cats'
diff --git a/content/test/data/accessibility/html/min-role-in-grid.html b/content/test/data/accessibility/html/min-role-in-grid.html new file mode 100644 index 0000000..1f0643e5 --- /dev/null +++ b/content/test/data/accessibility/html/min-role-in-grid.html
@@ -0,0 +1,17 @@ +<!DOCTYPE html> +<!-- This tests that a minimum role from https://github.com/w3c/html-aam/pull/454 + will not affect the naming of rows in a grid. --> +<div role="grid"> + <div> + <div draggable="true" onclick="doSomething()"> <!-- onlick -> unignored --> + <div role="row"> + <div role="gridcell"> + 55 + </div> + <div role="gridcell"> + Cats + </div> + </div> + </div> + </div> +</div>
diff --git a/content/test/gpu/gpu_tests/pixel_test_pages.py b/content/test/gpu/gpu_tests/pixel_test_pages.py index d9dc44e..37dd3ba9 100644 --- a/content/test/gpu/gpu_tests/pixel_test_pages.py +++ b/content/test/gpu/gpu_tests/pixel_test_pages.py
@@ -1612,21 +1612,6 @@ browser_args=['--force-color-profile=hdr10']), ] - # TODO(crbug.com/337737554): Move this to trace_test_pages.py - # Check that the root swap chain claims to be opaque. A root swap chain with a - # premultiplied alpha mode has a large negative battery impact (even if all - # the pixels are opaque). - @staticmethod - def RootSwapChainPages(base_name: str) -> List[PixelTestPage]: - return [ - PixelTestPage('wait_for_compositing.html', - base_name + '_IsOpaque', - crop_action=ca.NoOpCropAction(), - other_args={ - 'has_alpha': False, - }), - ] - # This should only be used with the cast_streaming suite. @staticmethod def CastStreamingReceiverPages(base_name) -> List[PixelTestPage]: @@ -1637,18 +1622,3 @@ crop_action=ca.NoOpCropAction(), ), ] - - # TODO(crbug.com/337737554): Move this to trace_test_pages.py - # Check what MediaFoundationD3D11VideoCapture works - @staticmethod - def MediaFoundationD3D11VideoCapturePages( - base_name: str) -> List[PixelTestPage]: - return [ - PixelTestPage('media_foundation_d3d11_video_capture.html', - base_name + '_MediaFoundationD3D11VideoCapture', - crop_action=ca.NoOpCropAction(), - browser_args=[ - '--use-fake-ui-for-media-stream', - '--enable-features=MediaFoundationD3D11VideoCapture' - ]), - ]
diff --git a/content/test/gpu/gpu_tests/trace_integration_test.py b/content/test/gpu/gpu_tests/trace_integration_test.py index af618b3..560d167 100644 --- a/content/test/gpu/gpu_tests/trace_integration_test.py +++ b/content/test/gpu/gpu_tests/trace_integration_test.py
@@ -367,7 +367,7 @@ success_eval_func='CheckSwapChainPath', other_args=p.other_args) ]) - for p in namespace.RootSwapChainPages('SwapChainTraceTest'): + for p in namespace.RootSwapChainTests('SwapChainTraceTest'): yield (p.name, posixpath.join(gpu_data_relative_path, p.url), [ _TraceTestArguments( browser_args=p.browser_args, @@ -377,7 +377,7 @@ success_eval_func='CheckSwapChainHasAlpha', other_args=p.other_args) ]) - for p in namespace.MediaFoundationD3D11VideoCapturePages('TraceTest'): + for p in namespace.MediaFoundationD3D11VideoCaptureTests('TraceTest'): yield (p.name, posixpath.join(gpu_data_relative_path, p.url), [ _TraceTestArguments( browser_args=p.browser_args,
diff --git a/content/test/gpu/gpu_tests/trace_test_pages.py b/content/test/gpu/gpu_tests/trace_test_pages.py index 8c9b1d739..9ca6e41 100644 --- a/content/test/gpu/gpu_tests/trace_test_pages.py +++ b/content/test/gpu/gpu_tests/trace_test_pages.py
@@ -6,9 +6,10 @@ # pylint: disable=too-many-lines import functools -from typing import List +from typing import Any, Dict, List from gpu_tests import common_browser_args as cba +from gpu_tests import common_typing as ct from gpu_tests import pixel_test_pages from gpu_tests.util import host_information @@ -45,6 +46,18 @@ default_factory=_GetWebGpuCacheTestBrowserArgs) +@dataclasses.dataclass +class SimpleTracingTest: + # The name of the test, including the prefix. + name: str + # The URL to load. + url: str + # Additional args to start the browser with. + browser_args: List[str] = ct.EmptyList() + # Additional test harness arguments. + other_args: Dict[str, Any] = ct.EmptyDict() + + # Inherits from PixelTestPages since a number of trace tests are just # re-used pixel tests. class TraceTestPages(pixel_test_pages.PixelTestPages): @@ -218,3 +231,30 @@ cache_pages=TraceTestPages.COMPUTE_CACHE_PAGES, ), ] + + @staticmethod + def RootSwapChainTests(prefix: str) -> List[SimpleTracingTest]: + return [ + # Check that the root swap chain claims to be opaque. A root swap chain + # with a premultiplied alpha mode has a large negative battery impact + # (even if all the pixels are opaque). + SimpleTracingTest(name=f'{prefix}_IsOpaque', + url='wait_for_compositing.html', + other_args={ + 'has_alpha': False, + }), + ] + + @staticmethod + def MediaFoundationD3D11VideoCaptureTests( + prefix: str) -> List[SimpleTracingTest]: + return [ + # Check what MediaFoundationD3D11VideoCapture works + SimpleTracingTest( + name=f'{prefix}_MediaFoundationD3D11VideoCapture', + url='media_foundation_d3d11_video_capture.html', + browser_args=[ + '--use-fake-ui-for-media-stream', + '--enable-features=MediaFoundationD3D11VideoCapture', + ]), + ]
diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h index 83a9bbc..2b0af33 100644 --- a/device/bluetooth/bluetooth_device.h +++ b/device/bluetooth/bluetooth_device.h
@@ -93,7 +93,7 @@ // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. This enum should be kept in sync // with the BluetoothDeviceConnectErrorCode enum in - // src/tools/metrics/histograms/enums.xml. + // src/tools/metrics/histograms/metadata/bluetooth/enums.xml. enum ConnectErrorCode { ERROR_AUTH_CANCELED = 0, ERROR_AUTH_FAILED = 1, @@ -114,6 +114,8 @@ ERROR_JNI_ENVIRONMENT = 16, ERROR_JNI_THREAD_ATTACH = 17, ERROR_WAKELOCK = 18, + ERROR_UNEXPECTED_STATE = 19, + ERROR_SOCKET = 20, NUM_CONNECT_ERROR_CODES, // Keep as last enum. };
diff --git a/device/bluetooth/chromeos/bluetooth_utils.cc b/device/bluetooth/chromeos/bluetooth_utils.cc index c6080b2..75aecd51 100644 --- a/device/bluetooth/chromeos/bluetooth_utils.cc +++ b/device/bluetooth/chromeos/bluetooth_utils.cc
@@ -212,6 +212,10 @@ case ConnectionFailureReason::kJniThreadAttach: [[fallthrough]]; case ConnectionFailureReason::kWakelock: + [[fallthrough]]; + case ConnectionFailureReason::kUnexpectedState: + [[fallthrough]]; + case ConnectionFailureReason::kSocketError: return false; } NOTREACHED_IN_MIGRATION(); @@ -263,6 +267,10 @@ case ConnectionFailureReason::kJniThreadAttach: [[fallthrough]]; case ConnectionFailureReason::kWakelock: + [[fallthrough]]; + case ConnectionFailureReason::kUnexpectedState: + [[fallthrough]]; + case ConnectionFailureReason::kSocketError: const std::string result_histogram_name_prefix = "Bluetooth.ChromeOS.Pairing.Result"; base::UmaHistogramEnumeration( @@ -357,6 +365,10 @@ return device::ConnectionFailureReason::kJniThreadAttach; case device::BluetoothDevice::ConnectErrorCode::ERROR_WAKELOCK: return device::ConnectionFailureReason::kWakelock; + case device::BluetoothDevice::ConnectErrorCode::ERROR_UNEXPECTED_STATE: + return device::ConnectionFailureReason::kUnexpectedState; + case device::BluetoothDevice::ConnectErrorCode::ERROR_SOCKET: + return device::ConnectionFailureReason::kSocketError; case device::BluetoothDevice::ConnectErrorCode::NUM_CONNECT_ERROR_CODES: NOTREACHED(); }
diff --git a/device/bluetooth/chromeos/bluetooth_utils.h b/device/bluetooth/chromeos/bluetooth_utils.h index dc9597da..a7650fb58 100644 --- a/device/bluetooth/chromeos/bluetooth_utils.h +++ b/device/bluetooth/chromeos/bluetooth_utils.h
@@ -43,8 +43,8 @@ kSystemTray, }; // This enum is tied directly to a UMA enum defined in -// //tools/metrics/histograms/enums.xml, and should always reflect it (do not -// change one without changing the other). +// //tools/metrics/histograms/metadata/bluetooth/enums.xml, and should always +// reflect it (do not change one without changing the other). enum class ConnectionFailureReason { kUnknownError = 0, kSystemError = 1, @@ -68,7 +68,9 @@ kJniEnvironment = 19, kJniThreadAttach = 20, kWakelock = 21, - kMaxValue = kWakelock + kUnexpectedState = 22, + kSocketError = 23, + kMaxValue = kSocketError }; // This enum is tied directly to a UMA enum defined in
diff --git a/device/bluetooth/floss/floss_dbus_client.cc b/device/bluetooth/floss/floss_dbus_client.cc index 292f668..19bba3f 100644 --- a/device/bluetooth/floss/floss_dbus_client.cc +++ b/device/bluetooth/floss/floss_dbus_client.cc
@@ -236,8 +236,11 @@ case BtifStatus::kTimeout: return device::BluetoothDevice::ConnectErrorCode::ERROR_NON_AUTH_TIMEOUT; case BtifStatus::kDeviceNotFound: + return device::BluetoothDevice::ConnectErrorCode::ERROR_DOES_NOT_EXIST; case BtifStatus::kUnexpectedState: + return device::BluetoothDevice::ConnectErrorCode::ERROR_UNEXPECTED_STATE; case BtifStatus::kSocketError: + return device::BluetoothDevice::ConnectErrorCode::ERROR_SOCKET; default: return device::BluetoothDevice::ConnectErrorCode::ERROR_FAILED; }
diff --git a/device/bluetooth/public/mojom/adapter.mojom b/device/bluetooth/public/mojom/adapter.mojom index bf0b3ce..e324a0f 100644 --- a/device/bluetooth/public/mojom/adapter.mojom +++ b/device/bluetooth/public/mojom/adapter.mojom
@@ -15,7 +15,7 @@ // These values are persisted to logs. Entries should not be renumbered and // numeric values should never be reused. This enum should be kept in sync // with the NearbyConnectionsConnectResult enum in -// src/tools/metrics/metadata/nearby/enums.xml. +// src/tools/metrics/histograms/metadata/nearby/enums.xml. enum ConnectResult { SUCCESS, AUTH_CANCELED, @@ -38,6 +38,8 @@ JNI_ENVIRONMENT, JNI_THREAD_ATTACH, WAKELOCK, + UNEXPECTED_STATE, + SOCKET, }; union LocalCharacteristicReadResult {
diff --git a/device/bluetooth/public/mojom/connect_result_type_converter.h b/device/bluetooth/public/mojom/connect_result_type_converter.h index 8056ee4..1f618ce 100644 --- a/device/bluetooth/public/mojom/connect_result_type_converter.h +++ b/device/bluetooth/public/mojom/connect_result_type_converter.h
@@ -60,6 +60,10 @@ return bluetooth::mojom::ConnectResult::JNI_THREAD_ATTACH; case device::BluetoothDevice::ConnectErrorCode::ERROR_WAKELOCK: return bluetooth::mojom::ConnectResult::WAKELOCK; + case device::BluetoothDevice::ConnectErrorCode::ERROR_UNEXPECTED_STATE: + return bluetooth::mojom::ConnectResult::UNEXPECTED_STATE; + case device::BluetoothDevice::ConnectErrorCode::ERROR_SOCKET: + return bluetooth::mojom::ConnectResult::SOCKET; case device::BluetoothDevice::ConnectErrorCode::NUM_CONNECT_ERROR_CODES: NOTREACHED_IN_MIGRATION(); return bluetooth::mojom::ConnectResult::FAILED;
diff --git a/device/fido/BUILD.gn b/device/fido/BUILD.gn index a013e21..44da370 100644 --- a/device/fido/BUILD.gn +++ b/device/fido/BUILD.gn
@@ -163,8 +163,6 @@ "device_operation.h", "device_response_converter.cc", "device_response_converter.h", - "digital_identity_request_handler.cc", - "digital_identity_request_handler.h", "enclave/constants.cc", "enclave/constants.h", "enclave/enclave_authenticator.cc",
diff --git a/device/fido/digital_identity_request_handler.cc b/device/fido/digital_identity_request_handler.cc deleted file mode 100644 index 0462f70..0000000 --- a/device/fido/digital_identity_request_handler.cc +++ /dev/null
@@ -1,33 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "device/fido/digital_identity_request_handler.h" - -#include "base/functional/bind.h" -#include "components/device_event_log/device_event_log.h" -#include "device/fido/fido_authenticator.h" -#include "device/fido/fido_types.h" - -namespace device { - -DigitalIdentityRequestHandler::DigitalIdentityRequestHandler( - FidoDiscoveryFactory* fido_discovery_factory) { - transport_availability_info().request_type = FidoRequestType::kMakeCredential; - base::flat_set<FidoTransportProtocol> allowed_transports; - allowed_transports.insert(FidoTransportProtocol::kHybrid); - - InitDiscoveries(fido_discovery_factory, /*additional_discoveries=*/{}, - allowed_transports, - /*consider_enclave=*/false); - Start(); -} - -DigitalIdentityRequestHandler::~DigitalIdentityRequestHandler() = default; - -void DigitalIdentityRequestHandler::DispatchRequest( - FidoAuthenticator* authenticator) { - // TODO(crbug.com/332562244): Implement -} - -} // namespace device
diff --git a/device/fido/digital_identity_request_handler.h b/device/fido/digital_identity_request_handler.h deleted file mode 100644 index cb7ab1e..0000000 --- a/device/fido/digital_identity_request_handler.h +++ /dev/null
@@ -1,38 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef DEVICE_FIDO_DIGITAL_IDENTITY_REQUEST_HANDLER_H_ -#define DEVICE_FIDO_DIGITAL_IDENTITY_REQUEST_HANDLER_H_ - -#include "base/component_export.h" -#include "base/functional/callback.h" -#include "base/memory/weak_ptr.h" -#include "device/fido/fido_request_handler_base.h" - -namespace device { - -class FidoAuthenticator; -class FidoDiscoveryFactory; - -// Handles discovery for digital credentials API. -class COMPONENT_EXPORT(DEVICE_FIDO) DigitalIdentityRequestHandler - : public FidoRequestHandlerBase { - public: - explicit DigitalIdentityRequestHandler( - FidoDiscoveryFactory* fido_discovery_factory); - - DigitalIdentityRequestHandler(const DigitalIdentityRequestHandler&) = delete; - DigitalIdentityRequestHandler& operator=( - const DigitalIdentityRequestHandler&) = delete; - - ~DigitalIdentityRequestHandler() override; - - private: - // FidoRequestHandlerBase: - void DispatchRequest(FidoAuthenticator* authenticator) override; -}; - -} // namespace device - -#endif // DEVICE_FIDO_DIGITAL_IDENTITY_REQUEST_HANDLER_H_
diff --git a/device/fido/enclave/verify/utils.cc b/device/fido/enclave/verify/utils.cc index 3a60378..64b7f7f 100644 --- a/device/fido/enclave/verify/utils.cc +++ b/device/fido/enclave/verify/utils.cc
@@ -99,9 +99,8 @@ uint8_t digest[SHA256_DIGEST_LENGTH]; SHA256(reinterpret_cast<const unsigned char*>(contents.data()), contents.size(), digest); - bssl::UniquePtr<ECDSA_SIG> sig( - ECDSA_SIG_from_bytes(signature.data(), signature.size())); - if (!ECDSA_do_verify(digest, sizeof(digest), sig.get(), ec_key.get())) { + if (!ECDSA_verify(/*type=*/0, digest, sizeof(digest), signature.data(), + signature.size(), ec_key.get())) { return base::unexpected("Could not verify the signature"); } return base::expected<void, std::string>();
diff --git a/device/fido/features.cc b/device/fido/features.cc index 992f6a6e..1e35918 100644 --- a/device/fido/features.cc +++ b/device/fido/features.cc
@@ -132,15 +132,15 @@ "WebAuthenticationCredProtectWin10BugWorkaround", base::FEATURE_ENABLED_BY_DEFAULT); -// Default disabled as it was found to be buggy in M129. +// Default enabled in M130. Remove in or after M133. BASE_FEATURE(kWebAuthnICloudRecoveryKey, "WebAuthenticationICloudRecoveryKey", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); -// Not yet enabled by default. +// Default enabled in M130. Remove in or after M133. BASE_FEATURE(kWebAuthnRecoverFromICloudRecoveryKey, "WebAuthenticationRecoverFromICloudRecoveryKey", - base::FEATURE_DISABLED_BY_DEFAULT); + base::FEATURE_ENABLED_BY_DEFAULT); // Not yet default enabled and not intended to be. Remove after M128 is Stable. BASE_FEATURE(kWebAuthnCacheSecurityDomain,
diff --git a/docs/testing/run_web_platform_tests.md b/docs/testing/run_web_platform_tests.md index 3f60722..3e2617f0 100644 --- a/docs/testing/run_web_platform_tests.md +++ b/docs/testing/run_web_platform_tests.md
@@ -1,77 +1,110 @@ # Running Web Platform Tests with run_wpt_tests.py -`run_web_tests.py` runs web tests with content shell through [protocol mode]. See -[web_tests.md](./web_tests.md) for details. `run_wpt_tests.py` instead can run web -platform tests with Chrome, Chrome Android and WebView. This document explains how -to use `run_wpt_tests.py` in these scenarios. +`run_web_tests.py` runs web tests with content shell through [protocol mode]. +See [web_tests.md](web_tests.md) for details. +`run_wpt_tests.py` is a WebDriver-based alternative that can run [web platform +tests] with [Chrome], [headless shell], Chrome Android, and WebView. +This document explains how to use `run_wpt_tests.py` in these scenarios. + +[web platform tests]: web_platform_tests.md +[Chrome]: /chrome +[headless shell]: /headless [TOC] -## Difference and Similarity with run_web_tests.py +## Running Web Platform Tests for Desktop Platforms -`run_wpt_tests.py` can run with different browsers. To specify which browser to -run tests with, you should use `--product` or `-p`. Supported parameters are `chrome`, -`chrome_android` (or `clank`), and `android_webview` (or `webview`). The default -value is `chrome` if not specified. +On Linux, macOS, and Windows, `run_wpt_tests.py` supports testing with [Chrome] +or [headless shell]. +Chrome is closer to the binary Google ships to end users, but is generally +slower. +Headless shell is a lightweight alternative that suffices for testing features +implemented entirely in Blink. -The CLI is mostly kept the same between run_web_tests.py and run_wpt_tests.py. To -see a complete list of arguments supported in run_wpt_tests.py, run: +### Running Tests Locally + +First, you will need to build one of the following targets to get all needed +binaries: ```bash -third_party/blink/tools/run_wpt_tests.py --help +autoninja -C out/Default chrome_wpt_tests # For testing with `chrome` +autoninja -C out/Default headless_shell_wpt # For testing with `headless_shell` ``` -## Running Web Platform Tests with Chrome - -Note: Internal testing APIs, e.g. `window.internals` or `window.testRunner`, are not available in Chrome. [Internal web -platform tests](../../third_party/blink/web_tests/wpt_internal) using those APIs should be skipped through [NeverFixTests](../../third_party/blink/web_tests/NeverFixTests). - -### Supported Platforms - -* Linux - -Test expectations and baselines are only actively maintained for Linux due to -resource constraints. -It's not yet possible to run tests for Chrome on non-Linux platforms; follow -https://crbug.com/1512219 for status. - -### Initial Setup - -Before you can run the web platform tests, you need to build the `chrome_wpt_tests` -target to get `chrome`, `chromedriver` and all of the other needed binaries. +Once the build is done, running tests is very similar to how you would run +tests with `run_web_tests.py`. +For example, to run all tests under `external/wpt/html/dom`, run: ```bash -autoninja -C out/Default chrome_wpt_tests +third_party/blink/tools/run_wpt_tests.py --target=Default --product=headless_shell external/wpt/html/dom ``` -### Running the Tests +`--product` (or `-p`) selects which browser to test with. +Supported values are: -Once you have `chrome` and `chromedriver` built, running tests is very much similar -to how you run tests with `run_web_tests.py`. For example, to run tests in `external/wpt/html/dom`, -you should run: +* `headless_shell` (default if `--product` is not specified) +* `chrome` +* `chrome_android` (aliased as `clank`; see + [additional instructions](#Running-Web-Platform-Tests-with-Chrome-Android)) +* `android_webview` (aliased as `webview`; see + [additional instructions](#Running-Web-Platform-Tests-with-WebView)) -```bash -third_party/blink/tools/run_wpt_tests.py --release -p chrome third_party/blink/web_tests/external/wpt/html/dom -``` +Also, consider using `-v` to get browser logs. +It can be provided multiple times to increase verbosity. -Note: consider using `-v` to get browser logs. It can be provided multiple times to -increase verbosity. +`run_wpt_tests.py --help` shows a full description of `run_wpt_tests.py`'s CLI, +which resembles that of `run_web_tests.py`. -### Test expectations and Baselines +### Running Tests in CQ/CI + +To satisfy different testing requirements, WPT coverage in CQ/CI is partitioned +between suites that target different `//content` embedders: + +Suite Name | Browser Under Test | Harness | Tests Run +--- | --- | --- | --- +`blink_wpt_tests` | `content_shell --run-web-tests` | `run_web_tests.py` | Tests that depend on web test-specific features (e.g., [internal WPTs] that depend on [nonstandard `window.internals` or `window.testRunner` APIs][3]). +`chrome_wpt_tests` | `chrome --headless=new` | `run_wpt_tests.py` | Tests that depend on the `//chrome` layer. Can be slow, so prefer `headless_shell` testing if possible. +`headless_shell_wpt_tests` | `headless_shell` | `run_wpt_tests.py` | All other tests. Most WPTs should eventually run here. + +To avoid redundant coverage, each WPT should run in exactly one suite listed +above. +The [`chrome.filter`][1] file lists tests that `chrome_wpt_tests` should run, +and that `headless_shell_wpt_tests` and `blink_wpt_tests` should skip. +[`headless_shell.filter`][2] works similarly. +Tests not listed in either file run in `blink_wpt_tests` by default. + +*** note +Running tests in `blink_wpt_tests` is discouraged because `run_web_tests.py` +doesn't drive tests through standard WebDriver endpoints. +This can cause `blink_wpt_tests` results to diverge from the Chrome results +published to [wpt.fyi]. +You can help unblock the eventual deprecation of `blink_wpt_tests` by adding +tests that you own to either filter file. +*** + +[internal WPTs]: /third_party/blink/web_tests/wpt_internal + +### Test Expectations and Baselines To suppress failures, `run_wpt_tests.py` uses the [same `*-expected.txt` and TestExpectations files](web_test_expectations.md) that `run_web_tests.py` uses. ### Running webdriver tests with Chrome -Webdriver tests are one type (wdspec) of web platform tests. Due to this you can run webdriver tests -the same way as other web platform tests, e.g. +[wdspec tests] are a subset of WPT that verifies conformance to the WebDriver +specification. +`run_wpt_tests.py` can run wdspec tests like any other WPT: ```bash -third_party/blink/tools/run_wpt_tests.py --release -p chrome external/wpt/webdriver/tests/classic/find_element/find.py +third_party/blink/tools/run_wpt_tests.py -t Default -p chrome \ + external/wpt/webdriver/tests/classic/find_element/find.py ``` -The `webdriver_wpt_tests` step of `linux-blink-rel` runs wdspec tests and can provide results for rebaselining. +On the bots, the `webdriver_wpt_tests` suite runs wdspec tests separately from +the other WPT types. +The `linux-blink-rel` builder can provide results for rebaselining. + +[wdspec tests]: https://web-platform-tests.org/writing-tests/wdspec.html ## Running Web Platform Tests with Chrome Android @@ -94,14 +127,6 @@ ## Known Issues -* Chromium's infrastructure currently tests WPTs against `chrome --headless=old` - (i.e., the `//headless` layer, not `//chrome`). This may cause results to - differ from [wpt.fyi] or `content_shell --run-web-tests` incorrectly. Notably, - `//headless` will not apply features listed in - [`fieldtrial_testing_config.json`][1]. See https://crbug.com/1485918 for - updates on switching testing to [`chrome --headless=new`][2] for more useful - results. - Please [file bugs and feature requests](https://crbug.com/new) against [`Blink>Infra` with the `wptrunner` label](https://bugs.chromium.org/p/chromium/issues/list?q=component%3ABlink%3EInfra%20label%3Awptrunner&can=2). @@ -110,5 +135,6 @@ [debug renderer]: /third_party/blink/tools/debug_renderer [wpt.fyi]: https://wpt.fyi/results/?label=experimental&label=master&aligned -[1]: /testing/variations/fieldtrial_testing_config.json -[2]: https://developer.chrome.com/docs/chromium/new-headless +[1]: /third_party/blink/web_tests/TestLists/chrome.filter +[2]: /third_party/blink/web_tests/TestLists/headless_shell.filter +[3]: writing_web_tests.md#Relying-on-Blink_Specific-Testing-APIs
diff --git a/docs/webapps/cdp-integration.md b/docs/webapps/cdp-integration.md index a5eef45..3cd3399f 100644 --- a/docs/webapps/cdp-integration.md +++ b/docs/webapps/cdp-integration.md
@@ -98,7 +98,8 @@ The demo installs a webapp https://developer.chrome.com/, launches it, inspects its states, opens it into its own app window, and uninstalls it. -The source code is at [cdp/demo2.mjs](cdp/demo2.mjs). +The source code is at [cdp/demo2.mjs](cdp/demo2.mjs); run with the command +`nodejs docs/webapps/cdp/demo2.mjs`. A video of running demo2.mjs on chrome canary channel on linux can be found at https://youtu.be/G4wmhSCXhH4.
diff --git a/docs/webapps/cdp/demo.mjs b/docs/webapps/cdp/demo.mjs index ae04201..78162a1 100644 --- a/docs/webapps/cdp/demo.mjs +++ b/docs/webapps/cdp/demo.mjs
@@ -1,22 +1,19 @@ import {stdin as input, stdout as output} from 'node:process'; import * as readline from 'node:readline/promises'; import puppeteer from 'puppeteer'; -import {setTimeout} from 'timers/promises'; import WebSocket from 'ws'; -const AUTO_ATTACH = false; - +// Running this test needs a local build with https://crrev.com/c/5532619. (async () => { - // Launch the browser and open a new blank page + // Launch the browser and open a new blank page const browser = await puppeteer.launch({ - // No need to use unstable once the PWA implementations roll to prod. - executablePath: - '/usr/bin/google-chrome-unstable', + executablePath: 'out/default/chrome' headless: false, slowMo: 100, - // Use pipe to allow executing high priviledge commands. - pipe: true, + // Expected to run via WebSocket. + pipe: false, }); + const ws = new WebSocket(browser.wsEndpoint(), {perMessageDeflate: false}); await new Promise(resolve => ws.once('open', resolve)); const queue = []; @@ -52,13 +49,11 @@ ws.addEventListener('message', e => { console.log(' <<<< Result: ' + e.data); const res = JSON.parse(e.data); - if (!AUTO_ATTACH) { - if (res.result && res.result.targetId) { - queue.unshift(send({ - method: 'Target.attachToTarget', - params: {targetId: res.result.targetId} - })); - } + if (res.result && res.result.targetId) { + queue.unshift(send({ + method: 'Target.attachToTarget', + params: {targetId: res.result.targetId} + })); } if (res.id == id) { id++; @@ -66,18 +61,6 @@ } }); - if (AUTO_ATTACH) { - queue.push(send({ - method: 'Target.setAutoAttach', - params: { - autoAttach: true, - waitForDebuggerOnStart: true, - filter: [{type: 'tab', exclude: false}, {type: 'page', exclude: true}], - flatten: true - } - })); - } - queue.push(send({ method: 'PWA.launch', params: { @@ -115,7 +98,7 @@ } })); - // Does not work. + // Does not work - it needs a WebSocket connecting to the page. queue.push(send({ method: 'Page.getAppManifest', params: {
diff --git a/docs/website b/docs/website index 2860bb8..66de3b3 160000 --- a/docs/website +++ b/docs/website
@@ -1 +1 @@ -Subproject commit 2860bb82fe04cccb9716f89492f7b981144403d8 +Subproject commit 66de3b3613bef02e6d95dc3e2148ff577e8acf67
diff --git a/extensions/browser/api/bluetooth/bluetooth_private_api.cc b/extensions/browser/api/bluetooth/bluetooth_private_api.cc index 7109c738..4022294 100644 --- a/extensions/browser/api/bluetooth/bluetooth_private_api.cc +++ b/extensions/browser/api/bluetooth/bluetooth_private_api.cc
@@ -109,6 +109,10 @@ return device::ConnectionFailureReason::kWakelock; case bt_private::ConnectResultType::kAlreadyConnected: return device::ConnectionFailureReason::kAlreadyConnected; + case bt_private::ConnectResultType::kUnexpectedState: + return device::ConnectionFailureReason::kUnexpectedState; + case bt_private::ConnectResultType::kSocketError: + return device::ConnectionFailureReason::kSocketError; case bt_private::ConnectResultType::kInProgress: [[fallthrough]]; case bt_private::ConnectResultType::kAuthRejected: @@ -167,6 +171,10 @@ return bt_private::ConnectResultType::kJniThreadAttach; case device::BluetoothDevice::ERROR_WAKELOCK: return bt_private::ConnectResultType::kWakelock; + case device::BluetoothDevice::ERROR_UNEXPECTED_STATE: + return bt_private::ConnectResultType::kUnexpectedState; + case device::BluetoothDevice::ERROR_SOCKET: + return bt_private::ConnectResultType::kSocketError; case device::BluetoothDevice::NUM_CONNECT_ERROR_CODES: NOTREACHED_IN_MIGRATION(); break;
diff --git a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc index 837f756..c806659 100644 --- a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc +++ b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.cc
@@ -249,6 +249,11 @@ kStatusErrorJniThreadAttach; case device::BluetoothDevice::ConnectErrorCode::ERROR_WAKELOCK: return extensions::BluetoothLowEnergyEventRouter::kStatusErrorWakelock; + case device::BluetoothDevice::ConnectErrorCode::ERROR_UNEXPECTED_STATE: + return extensions::BluetoothLowEnergyEventRouter:: + kStatusErrorUnexpectedState; + case device::BluetoothDevice::ConnectErrorCode::ERROR_SOCKET: + return extensions::BluetoothLowEnergyEventRouter::kStatusErrorSocket; case BluetoothDevice::NUM_CONNECT_ERROR_CODES: NOTREACHED_IN_MIGRATION(); return extensions::BluetoothLowEnergyEventRouter::
diff --git a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h index b31f39f..dc21830 100644 --- a/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h +++ b/extensions/browser/api/bluetooth_low_energy/bluetooth_low_energy_event_router.h
@@ -118,6 +118,8 @@ kStatusErrorJniEnvironment, kStatusErrorJniThreadAttach, kStatusErrorWakelock, + kStatusErrorUnexpectedState, + kStatusErrorSocket, }; // Error callback is used by asynchronous methods to report failures.
diff --git a/extensions/common/api/bluetooth_private.idl b/extensions/common/api/bluetooth_private.idl index b3afb9e..7c7f58c 100644 --- a/extensions/common/api/bluetooth_private.idl +++ b/extensions/common/api/bluetooth_private.idl
@@ -63,7 +63,9 @@ noMemory, jniEnvironment, jniThreadAttach, - wakelock + wakelock, + unexpectedState, + socketError }; // Valid pairing responses.
diff --git a/gpu/command_buffer/build_cmd_buffer_lib.py b/gpu/command_buffer/build_cmd_buffer_lib.py index a258170..2cedf30 100644 --- a/gpu/command_buffer/build_cmd_buffer_lib.py +++ b/gpu/command_buffer/build_cmd_buffer_lib.py
@@ -7266,43 +7266,7 @@ def WriteCommonUtilsImpl(self, filename): """Writes the gles2 common utility header.""" - enum_re = re.compile(r'\#define\s+(GL_[a-zA-Z0-9_]+)\s+([0-9A-Fa-fx]+)') - define_dict = {} - for fname in ['third_party/khronos/GLES2/gl2.h', - 'third_party/khronos/GLES2/gl2ext.h', - 'third_party/khronos/GLES3/gl3.h', - 'third_party/khronos/GLES3/gl31.h', - 'gpu/GLES2/gl2chromium.h', - 'gpu/GLES2/gl2extchromium.h']: - fname = os.path.join(self.chromium_root_dir, fname) - lines = open(fname).readlines() - for line in lines: - m = enum_re.match(line) - if m: - name = m.group(1) - value = m.group(2) - if len(value) <= 10 and value.startswith('0x'): - if not value in define_dict: - define_dict[value] = name - # check our own _CHROMIUM macro conflicts with khronos GL headers. - elif EnumsConflict(define_dict[value], name): - self.Error("code collision: %s and %s have the same code %s" % - (define_dict[value], name, value)) - with CHeaderWriter(filename, self.year) as f: - f.write("static const %sUtil::EnumToString " - "enum_to_string_table[] = {\n" % _prefix) - for value in sorted(define_dict): - f.write(' { %s, "%s", },\n' % (value, define_dict[value])) - f.write("""}; - -const %(p)sUtil::EnumToString* const %(p)sUtil::enum_to_string_table_ = - enum_to_string_table; -const size_t %(p)sUtil::enum_to_string_table_len_ = - sizeof(enum_to_string_table) / sizeof(enum_to_string_table[0]); - -""" % { 'p' : _prefix}) - enums = sorted(self.named_type_info.keys()) for enum in enums: if self.named_type_info[enum]['type'] == 'GLenum':
diff --git a/gpu/command_buffer/common/BUILD.gn b/gpu/command_buffer/common/BUILD.gn index d55b144..d928bf3 100644 --- a/gpu/command_buffer/common/BUILD.gn +++ b/gpu/command_buffer/common/BUILD.gn
@@ -120,10 +120,6 @@ ] deps = [ "//base" ] - - # TODO(piman): needed for gpu_memory_buffer_support.cc. Split common vs gles2 - # specifics. - configs += [ "//third_party/khronos:khronos_headers" ] } source_set("mailbox_sources") { @@ -226,7 +222,10 @@ defines = [ "GLES2_UTILS_IMPLEMENTATION" ] - deps = [ "//base" ] + deps = [ + "//base", + "//ui/gl:gl_enums", + ] all_dependent_configs = [ "//third_party/khronos:khronos_headers" ] }
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.cc b/gpu/command_buffer/common/gles2_cmd_utils.cc index a00dd019..c1688b2 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.cc +++ b/gpu/command_buffer/common/gles2_cmd_utils.cc
@@ -23,6 +23,7 @@ #include "base/check_op.h" #include "base/notreached.h" #include "base/numerics/safe_math.h" +#include "ui/gl/gl_enums.h" namespace gpu { namespace gles2 { @@ -1531,17 +1532,7 @@ } std::string GLES2Util::GetStringEnum(uint32_t value) { - const EnumToString* entry = enum_to_string_table_; - const EnumToString* end = entry + enum_to_string_table_len_; - for (; entry < end; ++entry) { - if (value == entry->value) - return entry->name; - } - std::stringstream ss; - ss.fill('0'); - ss.width(value < 0x10000 ? 4 : 8); - ss << std::hex << value; - return "0x" + ss.str(); + return gl::GLEnums::GetStringEnum(value); } std::string GLES2Util::GetStringError(uint32_t value) {
diff --git a/gpu/command_buffer/common/gles2_cmd_utils.h b/gpu/command_buffer/common/gles2_cmd_utils.h index 8522491..85975200 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils.h +++ b/gpu/command_buffer/common/gles2_cmd_utils.h
@@ -256,9 +256,6 @@ uint32_t* rt_padded_row_size, uint32_t* rt_padding); - static const EnumToString* const enum_to_string_table_; - static const size_t enum_to_string_table_len_; - int num_compressed_texture_formats_; int num_shader_binary_formats_; };
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h index fa636a0d..84e0007 100644 --- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h +++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -11,6867 +11,6 @@ #ifndef GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_UTILS_IMPLEMENTATION_AUTOGEN_H_ #define GPU_COMMAND_BUFFER_COMMON_GLES2_CMD_UTILS_IMPLEMENTATION_AUTOGEN_H_ -static const GLES2Util::EnumToString enum_to_string_table[] = { - { - 0x00, - "GL_CLOSE_PATH_NV", - }, - { - 0x0000, - "GL_POINTS", - }, - { - 0x00000000, - "GL_PERFQUERY_SINGLE_CONTEXT_INTEL", - }, - { - 0x00000001, - "GL_SUBGROUP_FEATURE_BASIC_BIT_KHR", - }, - { - 0x00000002, - "GL_CONTEXT_FLAG_DEBUG_BIT_KHR", - }, - { - 0x00000004, - "GL_SUBGROUP_FEATURE_ARITHMETIC_BIT_KHR", - }, - { - 0x00000008, - "GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR", - }, - { - 0x00000010, - "GL_SUBGROUP_FEATURE_SHUFFLE_BIT_KHR", - }, - { - 0x00000020, - "GL_SUBGROUP_FEATURE_SHUFFLE_RELATIVE_BIT_KHR", - }, - { - 0x00000040, - "GL_SUBGROUP_FEATURE_CLUSTERED_BIT_KHR", - }, - { - 0x00000080, - "GL_SUBGROUP_FEATURE_QUAD_BIT_KHR", - }, - { - 0x00000100, - "GL_DEPTH_BUFFER_BIT", - }, - { - 0x00000200, - "GL_DEPTH_BUFFER_BIT1_QCOM", - }, - { - 0x00000400, - "GL_STENCIL_BUFFER_BIT", - }, - { - 0x00000800, - "GL_DEPTH_BUFFER_BIT3_QCOM", - }, - { - 0x00001000, - "GL_DEPTH_BUFFER_BIT4_QCOM", - }, - { - 0x00002000, - "GL_DEPTH_BUFFER_BIT5_QCOM", - }, - { - 0x00004000, - "GL_COLOR_BUFFER_BIT", - }, - { - 0x00008000, - "GL_COVERAGE_BUFFER_BIT_NV", - }, - { - 0x0001, - "GL_LINES", - }, - { - 0x00010000, - "GL_FONT_X_MIN_BOUNDS_BIT_NV", - }, - { - 0x0002, - "GL_LINE_LOOP", - }, - { - 0x00020000, - "GL_FONT_Y_MIN_BOUNDS_BIT_NV", - }, - { - 0x0003, - "GL_LINE_STRIP", - }, - { - 0x0004, - "GL_TRIANGLES", - }, - { - 0x00040000, - "GL_FONT_X_MAX_BOUNDS_BIT_NV", - }, - { - 0x0005, - "GL_TRIANGLE_STRIP", - }, - { - 0x0006, - "GL_TRIANGLE_FAN", - }, - { - 0x0007, - "GL_QUADS_OES", - }, - { - 0x0008, - "GL_MAP_INVALIDATE_BUFFER_BIT_EXT", - }, - { - 0x00080000, - "GL_FONT_Y_MAX_BOUNDS_BIT_NV", - }, - { - 0x000A, - "GL_LINES_ADJACENCY_OES", - }, - { - 0x000B, - "GL_LINE_STRIP_ADJACENCY_OES", - }, - { - 0x000C, - "GL_TRIANGLES_ADJACENCY_OES", - }, - { - 0x000D, - "GL_TRIANGLE_STRIP_ADJACENCY_OES", - }, - { - 0x000E, - "GL_PATCHES_OES", - }, - { - 0x0010, - "GL_MAP_FLUSH_EXPLICIT_BIT_EXT", - }, - { - 0x00100000, - "GL_FONT_UNITS_PER_EM_BIT_NV", - }, - { - 0x0020, - "GL_MAP_UNSYNCHRONIZED_BIT_EXT", - }, - { - 0x00200000, - "GL_FONT_ASCENDER_BIT_NV", - }, - { - 0x0040, - "GL_MAP_PERSISTENT_BIT_EXT", - }, - { - 0x00400000, - "GL_FONT_DESCENDER_BIT_NV", - }, - { - 0x0080, - "GL_MAP_COHERENT_BIT_EXT", - }, - { - 0x00800000, - "GL_FONT_HEIGHT_BIT_NV", - }, - { - 0x01, - "GL_BOLD_BIT_NV", - }, - { - 0x0100, - "GL_DYNAMIC_STORAGE_BIT_EXT", - }, - { - 0x01000000, - "GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV", - }, - { - 0x02, - "GL_MOVE_TO_NV", - }, - { - 0x0200, - "GL_NEVER", - }, - { - 0x02000000, - "GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV", - }, - { - 0x0201, - "GL_LESS", - }, - { - 0x0202, - "GL_EQUAL", - }, - { - 0x0203, - "GL_LEQUAL", - }, - { - 0x0204, - "GL_GREATER", - }, - { - 0x0205, - "GL_NOTEQUAL", - }, - { - 0x0206, - "GL_GEQUAL", - }, - { - 0x0207, - "GL_ALWAYS", - }, - { - 0x03, - "GL_RELATIVE_MOVE_TO_NV", - }, - { - 0x0300, - "GL_SRC_COLOR", - }, - { - 0x0301, - "GL_ONE_MINUS_SRC_COLOR", - }, - { - 0x0302, - "GL_SRC_ALPHA", - }, - { - 0x0303, - "GL_ONE_MINUS_SRC_ALPHA", - }, - { - 0x0304, - "GL_DST_ALPHA", - }, - { - 0x0305, - "GL_ONE_MINUS_DST_ALPHA", - }, - { - 0x0306, - "GL_DST_COLOR", - }, - { - 0x0307, - "GL_ONE_MINUS_DST_COLOR", - }, - { - 0x0308, - "GL_SRC_ALPHA_SATURATE", - }, - { - 0x04, - "GL_LINE_TO_NV", - }, - { - 0x04000000, - "GL_FONT_UNDERLINE_POSITION_BIT_NV", - }, - { - 0x0404, - "GL_FRONT", - }, - { - 0x0405, - "GL_BACK", - }, - { - 0x0408, - "GL_FRONT_AND_BACK", - }, - { - 0x05, - "GL_RELATIVE_LINE_TO_NV", - }, - { - 0x0500, - "GL_INVALID_ENUM", - }, - { - 0x0501, - "GL_INVALID_VALUE", - }, - { - 0x0502, - "GL_INVALID_OPERATION", - }, - { - 0x0503, - "GL_STACK_OVERFLOW_KHR", - }, - { - 0x0504, - "GL_STACK_UNDERFLOW_KHR", - }, - { - 0x0505, - "GL_OUT_OF_MEMORY", - }, - { - 0x0506, - "GL_INVALID_FRAMEBUFFER_OPERATION", - }, - { - 0x0507, - "GL_CONTEXT_LOST_KHR", - }, - { - 0x06, - "GL_HORIZONTAL_LINE_TO_NV", - }, - { - 0x07, - "GL_RELATIVE_HORIZONTAL_LINE_TO_NV", - }, - { - 0x08, - "GL_VERTICAL_LINE_TO_NV", - }, - { - 0x08000000, - "GL_FONT_UNDERLINE_THICKNESS_BIT_NV", - }, - { - 0x09, - "GL_RELATIVE_VERTICAL_LINE_TO_NV", - }, - { - 0x0900, - "GL_CW", - }, - { - 0x0901, - "GL_CCW", - }, - { - 0x0A, - "GL_QUADRATIC_CURVE_TO_NV", - }, - { - 0x0B, - "GL_RELATIVE_QUADRATIC_CURVE_TO_NV", - }, - { - 0x0B21, - "GL_LINE_WIDTH", - }, - { - 0x0B40, - "GL_POLYGON_MODE_NV", - }, - { - 0x0B44, - "GL_CULL_FACE", - }, - { - 0x0B45, - "GL_CULL_FACE_MODE", - }, - { - 0x0B46, - "GL_FRONT_FACE", - }, - { - 0x0B70, - "GL_DEPTH_RANGE", - }, - { - 0x0B71, - "GL_DEPTH_TEST", - }, - { - 0x0B72, - "GL_DEPTH_WRITEMASK", - }, - { - 0x0B73, - "GL_DEPTH_CLEAR_VALUE", - }, - { - 0x0B74, - "GL_DEPTH_FUNC", - }, - { - 0x0B90, - "GL_STENCIL_TEST", - }, - { - 0x0B91, - "GL_STENCIL_CLEAR_VALUE", - }, - { - 0x0B92, - "GL_STENCIL_FUNC", - }, - { - 0x0B93, - "GL_STENCIL_VALUE_MASK", - }, - { - 0x0B94, - "GL_STENCIL_FAIL", - }, - { - 0x0B95, - "GL_STENCIL_PASS_DEPTH_FAIL", - }, - { - 0x0B96, - "GL_STENCIL_PASS_DEPTH_PASS", - }, - { - 0x0B97, - "GL_STENCIL_REF", - }, - { - 0x0B98, - "GL_STENCIL_WRITEMASK", - }, - { - 0x0BA2, - "GL_VIEWPORT", - }, - { - 0x0BA3, - "GL_PATH_MODELVIEW_STACK_DEPTH_NV", - }, - { - 0x0BA4, - "GL_PATH_PROJECTION_STACK_DEPTH_NV", - }, - { - 0x0BA6, - "GL_PATH_MODELVIEW_MATRIX_NV", - }, - { - 0x0BA7, - "GL_PATH_PROJECTION_MATRIX_NV", - }, - { - 0x0BC0, - "GL_ALPHA_TEST_QCOM", - }, - { - 0x0BC1, - "GL_ALPHA_TEST_FUNC_QCOM", - }, - { - 0x0BC2, - "GL_ALPHA_TEST_REF_QCOM", - }, - { - 0x0BD0, - "GL_DITHER", - }, - { - 0x0BE2, - "GL_BLEND", - }, - { - 0x0C, - "GL_CUBIC_CURVE_TO_NV", - }, - { - 0x0C01, - "GL_DRAW_BUFFER_EXT", - }, - { - 0x0C02, - "GL_READ_BUFFER_EXT", - }, - { - 0x0C10, - "GL_SCISSOR_BOX", - }, - { - 0x0C11, - "GL_SCISSOR_TEST", - }, - { - 0x0C22, - "GL_COLOR_CLEAR_VALUE", - }, - { - 0x0C23, - "GL_COLOR_WRITEMASK", - }, - { - 0x0CF2, - "GL_UNPACK_ROW_LENGTH_EXT", - }, - { - 0x0CF3, - "GL_UNPACK_SKIP_ROWS_EXT", - }, - { - 0x0CF4, - "GL_UNPACK_SKIP_PIXELS_EXT", - }, - { - 0x0CF5, - "GL_UNPACK_ALIGNMENT", - }, - { - 0x0D, - "GL_RELATIVE_CUBIC_CURVE_TO_NV", - }, - { - 0x0D02, - "GL_PACK_ROW_LENGTH", - }, - { - 0x0D03, - "GL_PACK_SKIP_ROWS", - }, - { - 0x0D04, - "GL_PACK_SKIP_PIXELS", - }, - { - 0x0D05, - "GL_PACK_ALIGNMENT", - }, - { - 0x0D32, - "GL_MAX_CLIP_DISTANCES_APPLE", - }, - { - 0x0D33, - "GL_MAX_TEXTURE_SIZE", - }, - { - 0x0D36, - "GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV", - }, - { - 0x0D38, - "GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV", - }, - { - 0x0D3A, - "GL_MAX_VIEWPORT_DIMS", - }, - { - 0x0D50, - "GL_SUBPIXEL_BITS", - }, - { - 0x0D52, - "GL_RED_BITS", - }, - { - 0x0D53, - "GL_GREEN_BITS", - }, - { - 0x0D54, - "GL_BLUE_BITS", - }, - { - 0x0D55, - "GL_ALPHA_BITS", - }, - { - 0x0D56, - "GL_DEPTH_BITS", - }, - { - 0x0D57, - "GL_STENCIL_BITS", - }, - { - 0x0DE1, - "GL_TEXTURE_2D", - }, - { - 0x0E, - "GL_SMOOTH_QUADRATIC_CURVE_TO_NV", - }, - { - 0x0F, - "GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV", - }, - { - 0x10, - "GL_SMOOTH_CUBIC_CURVE_TO_NV", - }, - { - 0x100, - "GL_GLYPH_HAS_KERNING_BIT_NV", - }, - { - 0x1000, - "GL_TEXTURE_WIDTH", - }, - { - 0x10000000, - "GL_FONT_HAS_KERNING_BIT_NV", - }, - { - 0x1001, - "GL_TEXTURE_HEIGHT", - }, - { - 0x1003, - "GL_TEXTURE_INTERNAL_FORMAT", - }, - { - 0x1004, - "GL_TEXTURE_BORDER_COLOR_OES", - }, - { - 0x11, - "GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV", - }, - { - 0x1100, - "GL_DONT_CARE", - }, - { - 0x1101, - "GL_FASTEST", - }, - { - 0x1102, - "GL_NICEST", - }, - { - 0x12, - "GL_SMALL_CCW_ARC_TO_NV", - }, - { - 0x13, - "GL_RELATIVE_SMALL_CCW_ARC_TO_NV", - }, - { - 0x14, - "GL_SMALL_CW_ARC_TO_NV", - }, - { - 0x1400, - "GL_BYTE", - }, - { - 0x1401, - "GL_UNSIGNED_BYTE", - }, - { - 0x1402, - "GL_SHORT", - }, - { - 0x1403, - "GL_UNSIGNED_SHORT", - }, - { - 0x1404, - "GL_INT", - }, - { - 0x1405, - "GL_UNSIGNED_INT", - }, - { - 0x1406, - "GL_FLOAT", - }, - { - 0x140B, - "GL_HALF_FLOAT", - }, - { - 0x140C, - "GL_FIXED", - }, - { - 0x140E, - "GL_INT64_NV", - }, - { - 0x140F, - "GL_UNSIGNED_INT64_NV", - }, - { - 0x15, - "GL_RELATIVE_SMALL_CW_ARC_TO_NV", - }, - { - 0x1506, - "GL_XOR_NV", - }, - { - 0x150A, - "GL_INVERT", - }, - { - 0x16, - "GL_LARGE_CCW_ARC_TO_NV", - }, - { - 0x17, - "GL_RELATIVE_LARGE_CCW_ARC_TO_NV", - }, - { - 0x1700, - "GL_PATH_MODELVIEW_NV", - }, - { - 0x1701, - "GL_PATH_PROJECTION_NV", - }, - { - 0x1702, - "GL_TEXTURE", - }, - { - 0x18, - "GL_LARGE_CW_ARC_TO_NV", - }, - { - 0x1800, - "GL_COLOR_EXT", - }, - { - 0x1801, - "GL_DEPTH_EXT", - }, - { - 0x1802, - "GL_STENCIL_EXT", - }, - { - 0x19, - "GL_RELATIVE_LARGE_CW_ARC_TO_NV", - }, - { - 0x1901, - "GL_STENCIL_INDEX_OES", - }, - { - 0x1902, - "GL_DEPTH_COMPONENT", - }, - { - 0x1903, - "GL_RED_EXT", - }, - { - 0x1904, - "GL_GREEN_NV", - }, - { - 0x1905, - "GL_BLUE_NV", - }, - { - 0x1906, - "GL_ALPHA", - }, - { - 0x1907, - "GL_RGB", - }, - { - 0x1908, - "GL_RGBA", - }, - { - 0x1909, - "GL_LUMINANCE", - }, - { - 0x190A, - "GL_LUMINANCE_ALPHA", - }, - { - 0x1A, - "GL_CONIC_CURVE_TO_NV", - }, - { - 0x1B, - "GL_RELATIVE_CONIC_CURVE_TO_NV", - }, - { - 0x1B00, - "GL_POINT_NV", - }, - { - 0x1B01, - "GL_LINE_NV", - }, - { - 0x1B02, - "GL_FILL_NV", - }, - { - 0x1E00, - "GL_KEEP", - }, - { - 0x1E01, - "GL_REPLACE", - }, - { - 0x1E02, - "GL_INCR", - }, - { - 0x1E03, - "GL_DECR", - }, - { - 0x1F00, - "GL_VENDOR", - }, - { - 0x1F01, - "GL_RENDERER", - }, - { - 0x1F02, - "GL_VERSION", - }, - { - 0x1F03, - "GL_EXTENSIONS", - }, - { - 0x20, - "GL_GLYPH_VERTICAL_BEARING_X_BIT_NV", - }, - { - 0x20000000, - "GL_FONT_NUM_GLYPH_INDICES_BIT_NV", - }, - { - 0x2600, - "GL_NEAREST", - }, - { - 0x2601, - "GL_LINEAR", - }, - { - 0x2700, - "GL_NEAREST_MIPMAP_NEAREST", - }, - { - 0x2701, - "GL_LINEAR_MIPMAP_NEAREST", - }, - { - 0x2702, - "GL_NEAREST_MIPMAP_LINEAR", - }, - { - 0x2703, - "GL_LINEAR_MIPMAP_LINEAR", - }, - { - 0x2800, - "GL_TEXTURE_MAG_FILTER", - }, - { - 0x2801, - "GL_TEXTURE_MIN_FILTER", - }, - { - 0x2802, - "GL_TEXTURE_WRAP_S", - }, - { - 0x2803, - "GL_TEXTURE_WRAP_T", - }, - { - 0x2901, - "GL_REPEAT", - }, - { - 0x2A00, - "GL_POLYGON_OFFSET_UNITS", - }, - { - 0x2A01, - "GL_POLYGON_OFFSET_POINT_NV", - }, - { - 0x2A02, - "GL_POLYGON_OFFSET_LINE_NV", - }, - { - 0x3000, - "GL_CLIP_DISTANCE0_APPLE", - }, - { - 0x3001, - "GL_CLIP_DISTANCE1_APPLE", - }, - { - 0x3002, - "GL_CLIP_DISTANCE2_APPLE", - }, - { - 0x3003, - "GL_CLIP_DISTANCE3_APPLE", - }, - { - 0x3004, - "GL_CLIP_DISTANCE4_APPLE", - }, - { - 0x3005, - "GL_CLIP_DISTANCE5_APPLE", - }, - { - 0x3006, - "GL_CLIP_DISTANCE6_APPLE", - }, - { - 0x3007, - "GL_CLIP_DISTANCE7_APPLE", - }, - { - 0x300E, - "GL_CONTEXT_LOST", - }, - { - 0x40, - "GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV", - }, - { - 0x40000000, - "GL_MULTISAMPLE_BUFFER_BIT6_QCOM", - }, - { - 0x6003, - "GL_GET_ERROR_QUERY_CHROMIUM", - }, - { - 0x6004, - "GL_COMMANDS_ISSUED_CHROMIUM", - }, - { - 0x6005, - "GL_COMMANDS_ISSUED_TIMESTAMP_CHROMIUM", - }, - { - 0x6006, - "GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM", - }, - { - 0x6009, - "GL_PROGRAM_COMPLETION_QUERY_CHROMIUM", - }, - { - 0x78EC, - "GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM", - }, - { - 0x78ED, - "GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM", - }, - { - 0x78EE, - "GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM", - }, - { - 0x78EF, - "GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM", - }, - { - 0x80, - "GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV", - }, - { - 0x80000000, - "GL_MULTISAMPLE_BUFFER_BIT7_QCOM", - }, - { - 0x8001, - "GL_CONSTANT_COLOR", - }, - { - 0x8002, - "GL_ONE_MINUS_CONSTANT_COLOR", - }, - { - 0x8003, - "GL_CONSTANT_ALPHA", - }, - { - 0x8004, - "GL_ONE_MINUS_CONSTANT_ALPHA", - }, - { - 0x8005, - "GL_BLEND_COLOR", - }, - { - 0x8006, - "GL_FUNC_ADD", - }, - { - 0x8007, - "GL_MIN", - }, - { - 0x8008, - "GL_MAX", - }, - { - 0x8009, - "GL_BLEND_EQUATION", - }, - { - 0x800A, - "GL_FUNC_SUBTRACT", - }, - { - 0x800B, - "GL_FUNC_REVERSE_SUBTRACT", - }, - { - 0x8033, - "GL_UNSIGNED_SHORT_4_4_4_4", - }, - { - 0x8034, - "GL_UNSIGNED_SHORT_5_5_5_1", - }, - { - 0x8037, - "GL_POLYGON_OFFSET_FILL", - }, - { - 0x8038, - "GL_POLYGON_OFFSET_FACTOR", - }, - { - 0x803C, - "GL_ALPHA8_OES", - }, - { - 0x8040, - "GL_LUMINANCE8_OES", - }, - { - 0x8043, - "GL_LUMINANCE4_ALPHA4_OES", - }, - { - 0x8045, - "GL_LUMINANCE8_ALPHA8_OES", - }, - { - 0x8051, - "GL_RGB8_OES", - }, - { - 0x8052, - "GL_RGB10_EXT", - }, - { - 0x8054, - "GL_RGB16_EXT", - }, - { - 0x8056, - "GL_RGBA4", - }, - { - 0x8057, - "GL_RGB5_A1", - }, - { - 0x8058, - "GL_RGBA8_OES", - }, - { - 0x8059, - "GL_RGB10_A2_EXT", - }, - { - 0x805B, - "GL_RGBA16_EXT", - }, - { - 0x805C, - "GL_TEXTURE_RED_SIZE", - }, - { - 0x805D, - "GL_TEXTURE_GREEN_SIZE", - }, - { - 0x805E, - "GL_TEXTURE_BLUE_SIZE", - }, - { - 0x805F, - "GL_TEXTURE_ALPHA_SIZE", - }, - { - 0x8069, - "GL_TEXTURE_BINDING_2D", - }, - { - 0x806A, - "GL_TEXTURE_BINDING_3D_OES", - }, - { - 0x806D, - "GL_UNPACK_SKIP_IMAGES", - }, - { - 0x806E, - "GL_UNPACK_IMAGE_HEIGHT", - }, - { - 0x806F, - "GL_TEXTURE_3D_OES", - }, - { - 0x8071, - "GL_TEXTURE_DEPTH", - }, - { - 0x8072, - "GL_TEXTURE_WRAP_R_OES", - }, - { - 0x8073, - "GL_MAX_3D_TEXTURE_SIZE_OES", - }, - { - 0x8074, - "GL_VERTEX_ARRAY_KHR", - }, - { - 0x809D, - "GL_MULTISAMPLE_EXT", - }, - { - 0x809E, - "GL_SAMPLE_ALPHA_TO_COVERAGE", - }, - { - 0x809F, - "GL_SAMPLE_ALPHA_TO_ONE_EXT", - }, - { - 0x80A0, - "GL_SAMPLE_COVERAGE", - }, - { - 0x80A8, - "GL_SAMPLE_BUFFERS", - }, - { - 0x80A9, - "GL_SAMPLES", - }, - { - 0x80AA, - "GL_SAMPLE_COVERAGE_VALUE", - }, - { - 0x80AB, - "GL_SAMPLE_COVERAGE_INVERT", - }, - { - 0x80C8, - "GL_BLEND_DST_RGB", - }, - { - 0x80C9, - "GL_BLEND_SRC_RGB", - }, - { - 0x80CA, - "GL_BLEND_DST_ALPHA", - }, - { - 0x80CB, - "GL_BLEND_SRC_ALPHA", - }, - { - 0x80E1, - "GL_BGRA_EXT", - }, - { - 0x80E8, - "GL_MAX_ELEMENTS_VERTICES", - }, - { - 0x80E9, - "GL_MAX_ELEMENTS_INDICES", - }, - { - 0x812D, - "GL_CLAMP_TO_BORDER_OES", - }, - { - 0x812F, - "GL_CLAMP_TO_EDGE", - }, - { - 0x813A, - "GL_TEXTURE_MIN_LOD", - }, - { - 0x813B, - "GL_TEXTURE_MAX_LOD", - }, - { - 0x813C, - "GL_TEXTURE_BASE_LEVEL", - }, - { - 0x813D, - "GL_TEXTURE_MAX_LEVEL_APPLE", - }, - { - 0x8192, - "GL_GENERATE_MIPMAP_HINT", - }, - { - 0x81A5, - "GL_DEPTH_COMPONENT16", - }, - { - 0x81A6, - "GL_DEPTH_COMPONENT24_OES", - }, - { - 0x81A7, - "GL_DEPTH_COMPONENT32_OES", - }, - { - 0x8210, - "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT", - }, - { - 0x8211, - "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT", - }, - { - 0x8212, - "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE", - }, - { - 0x8213, - "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE", - }, - { - 0x8214, - "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE", - }, - { - 0x8215, - "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE", - }, - { - 0x8216, - "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE", - }, - { - 0x8217, - "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE", - }, - { - 0x8218, - "GL_FRAMEBUFFER_DEFAULT", - }, - { - 0x8219, - "GL_FRAMEBUFFER_UNDEFINED_OES", - }, - { - 0x821A, - "GL_DEPTH_STENCIL_ATTACHMENT", - }, - { - 0x821B, - "GL_MAJOR_VERSION", - }, - { - 0x821C, - "GL_MINOR_VERSION", - }, - { - 0x821D, - "GL_NUM_EXTENSIONS", - }, - { - 0x821F, - "GL_BUFFER_IMMUTABLE_STORAGE_EXT", - }, - { - 0x8220, - "GL_BUFFER_STORAGE_FLAGS_EXT", - }, - { - 0x8221, - "GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES", - }, - { - 0x8227, - "GL_RG_EXT", - }, - { - 0x8228, - "GL_RG_INTEGER", - }, - { - 0x8229, - "GL_R8_EXT", - }, - { - 0x822A, - "GL_R16_EXT", - }, - { - 0x822B, - "GL_RG8_EXT", - }, - { - 0x822C, - "GL_RG16_EXT", - }, - { - 0x822D, - "GL_R16F_EXT", - }, - { - 0x822E, - "GL_R32F_EXT", - }, - { - 0x822F, - "GL_RG16F_EXT", - }, - { - 0x8230, - "GL_RG32F_EXT", - }, - { - 0x8231, - "GL_R8I", - }, - { - 0x8232, - "GL_R8UI", - }, - { - 0x8233, - "GL_R16I", - }, - { - 0x8234, - "GL_R16UI", - }, - { - 0x8235, - "GL_R32I", - }, - { - 0x8236, - "GL_R32UI", - }, - { - 0x8237, - "GL_RG8I", - }, - { - 0x8238, - "GL_RG8UI", - }, - { - 0x8239, - "GL_RG16I", - }, - { - 0x823A, - "GL_RG16UI", - }, - { - 0x823B, - "GL_RG32I", - }, - { - 0x823C, - "GL_RG32UI", - }, - { - 0x8242, - "GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR", - }, - { - 0x8243, - "GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR", - }, - { - 0x8244, - "GL_DEBUG_CALLBACK_FUNCTION_KHR", - }, - { - 0x8245, - "GL_DEBUG_CALLBACK_USER_PARAM_KHR", - }, - { - 0x8246, - "GL_DEBUG_SOURCE_API_KHR", - }, - { - 0x8247, - "GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR", - }, - { - 0x8248, - "GL_DEBUG_SOURCE_SHADER_COMPILER_KHR", - }, - { - 0x8249, - "GL_DEBUG_SOURCE_THIRD_PARTY_KHR", - }, - { - 0x824A, - "GL_DEBUG_SOURCE_APPLICATION_KHR", - }, - { - 0x824B, - "GL_DEBUG_SOURCE_OTHER_KHR", - }, - { - 0x824C, - "GL_DEBUG_TYPE_ERROR_KHR", - }, - { - 0x824D, - "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR", - }, - { - 0x824E, - "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR", - }, - { - 0x824F, - "GL_DEBUG_TYPE_PORTABILITY_KHR", - }, - { - 0x8250, - "GL_DEBUG_TYPE_PERFORMANCE_KHR", - }, - { - 0x8251, - "GL_DEBUG_TYPE_OTHER_KHR", - }, - { - 0x8252, - "GL_LOSE_CONTEXT_ON_RESET_KHR", - }, - { - 0x8253, - "GL_GUILTY_CONTEXT_RESET_KHR", - }, - { - 0x8254, - "GL_INNOCENT_CONTEXT_RESET_KHR", - }, - { - 0x8255, - "GL_UNKNOWN_CONTEXT_RESET_KHR", - }, - { - 0x8256, - "GL_RESET_NOTIFICATION_STRATEGY_KHR", - }, - { - 0x8257, - "GL_PROGRAM_BINARY_RETRIEVABLE_HINT", - }, - { - 0x8258, - "GL_PROGRAM_SEPARABLE_EXT", - }, - { - 0x8259, - "GL_ACTIVE_PROGRAM_EXT", - }, - { - 0x825A, - "GL_PROGRAM_PIPELINE_BINDING_EXT", - }, - { - 0x825B, - "GL_MAX_VIEWPORTS_OES", - }, - { - 0x825C, - "GL_VIEWPORT_SUBPIXEL_BITS_OES", - }, - { - 0x825D, - "GL_VIEWPORT_BOUNDS_RANGE_OES", - }, - { - 0x825E, - "GL_LAYER_PROVOKING_VERTEX_OES", - }, - { - 0x825F, - "GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES", - }, - { - 0x8260, - "GL_UNDEFINED_VERTEX_OES", - }, - { - 0x8261, - "GL_NO_RESET_NOTIFICATION_KHR", - }, - { - 0x8262, - "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE", - }, - { - 0x8263, - "GL_MAX_COMPUTE_UNIFORM_COMPONENTS", - }, - { - 0x8264, - "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS", - }, - { - 0x8265, - "GL_MAX_COMPUTE_ATOMIC_COUNTERS", - }, - { - 0x8266, - "GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS", - }, - { - 0x8267, - "GL_COMPUTE_WORK_GROUP_SIZE", - }, - { - 0x8268, - "GL_DEBUG_TYPE_MARKER_KHR", - }, - { - 0x8269, - "GL_DEBUG_TYPE_PUSH_GROUP_KHR", - }, - { - 0x826A, - "GL_DEBUG_TYPE_POP_GROUP_KHR", - }, - { - 0x826B, - "GL_DEBUG_SEVERITY_NOTIFICATION_KHR", - }, - { - 0x826C, - "GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR", - }, - { - 0x826D, - "GL_DEBUG_GROUP_STACK_DEPTH_KHR", - }, - { - 0x826E, - "GL_MAX_UNIFORM_LOCATIONS", - }, - { - 0x82D4, - "GL_VERTEX_ATTRIB_BINDING", - }, - { - 0x82D5, - "GL_VERTEX_ATTRIB_RELATIVE_OFFSET", - }, - { - 0x82D6, - "GL_VERTEX_BINDING_DIVISOR", - }, - { - 0x82D7, - "GL_VERTEX_BINDING_OFFSET", - }, - { - 0x82D8, - "GL_VERTEX_BINDING_STRIDE", - }, - { - 0x82D9, - "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET", - }, - { - 0x82DA, - "GL_MAX_VERTEX_ATTRIB_BINDINGS", - }, - { - 0x82DB, - "GL_TEXTURE_VIEW_MIN_LEVEL_OES", - }, - { - 0x82DC, - "GL_TEXTURE_VIEW_NUM_LEVELS_OES", - }, - { - 0x82DD, - "GL_TEXTURE_VIEW_MIN_LAYER_OES", - }, - { - 0x82DE, - "GL_TEXTURE_VIEW_NUM_LAYERS_OES", - }, - { - 0x82DF, - "GL_TEXTURE_IMMUTABLE_LEVELS", - }, - { - 0x82E0, - "GL_BUFFER_KHR", - }, - { - 0x82E1, - "GL_SHADER_KHR", - }, - { - 0x82E2, - "GL_PROGRAM_KHR", - }, - { - 0x82E3, - "GL_QUERY_KHR", - }, - { - 0x82E4, - "GL_PROGRAM_PIPELINE_KHR", - }, - { - 0x82E5, - "GL_MAX_VERTEX_ATTRIB_STRIDE", - }, - { - 0x82E6, - "GL_SAMPLER_KHR", - }, - { - 0x82E8, - "GL_MAX_LABEL_LENGTH_KHR", - }, - { - 0x82F9, - "GL_MAX_CULL_DISTANCES_EXT", - }, - { - 0x82FA, - "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT", - }, - { - 0x82FB, - "GL_CONTEXT_RELEASE_BEHAVIOR_KHR", - }, - { - 0x82FC, - "GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR", - }, - { - 0x8363, - "GL_UNSIGNED_SHORT_5_6_5", - }, - { - 0x8365, - "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT", - }, - { - 0x8366, - "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT", - }, - { - 0x8368, - "GL_UNSIGNED_INT_2_10_10_10_REV_EXT", - }, - { - 0x8370, - "GL_MIRRORED_REPEAT", - }, - { - 0x83F0, - "GL_COMPRESSED_RGB_S3TC_DXT1_EXT", - }, - { - 0x83F1, - "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT", - }, - { - 0x83F2, - "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE", - }, - { - 0x83F3, - "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE", - }, - { - 0x83F9, - "GL_PERFQUERY_DONOT_FLUSH_INTEL", - }, - { - 0x83FA, - "GL_PERFQUERY_FLUSH_INTEL", - }, - { - 0x83FB, - "GL_PERFQUERY_WAIT_INTEL", - }, - { - 0x83FC, - "GL_BLACKHOLE_RENDER_INTEL", - }, - { - 0x83FE, - "GL_CONSERVATIVE_RASTERIZATION_INTEL", - }, - { - 0x846D, - "GL_ALIASED_POINT_SIZE_RANGE", - }, - { - 0x846E, - "GL_ALIASED_LINE_WIDTH_RANGE", - }, - { - 0x84C0, - "GL_TEXTURE0", - }, - { - 0x84C1, - "GL_TEXTURE1", - }, - { - 0x84C2, - "GL_TEXTURE2", - }, - { - 0x84C3, - "GL_TEXTURE3", - }, - { - 0x84C4, - "GL_TEXTURE4", - }, - { - 0x84C5, - "GL_TEXTURE5", - }, - { - 0x84C6, - "GL_TEXTURE6", - }, - { - 0x84C7, - "GL_TEXTURE7", - }, - { - 0x84C8, - "GL_TEXTURE8", - }, - { - 0x84C9, - "GL_TEXTURE9", - }, - { - 0x84CA, - "GL_TEXTURE10", - }, - { - 0x84CB, - "GL_TEXTURE11", - }, - { - 0x84CC, - "GL_TEXTURE12", - }, - { - 0x84CD, - "GL_TEXTURE13", - }, - { - 0x84CE, - "GL_TEXTURE14", - }, - { - 0x84CF, - "GL_TEXTURE15", - }, - { - 0x84D0, - "GL_TEXTURE16", - }, - { - 0x84D1, - "GL_TEXTURE17", - }, - { - 0x84D2, - "GL_TEXTURE18", - }, - { - 0x84D3, - "GL_TEXTURE19", - }, - { - 0x84D4, - "GL_TEXTURE20", - }, - { - 0x84D5, - "GL_TEXTURE21", - }, - { - 0x84D6, - "GL_TEXTURE22", - }, - { - 0x84D7, - "GL_TEXTURE23", - }, - { - 0x84D8, - "GL_TEXTURE24", - }, - { - 0x84D9, - "GL_TEXTURE25", - }, - { - 0x84DA, - "GL_TEXTURE26", - }, - { - 0x84DB, - "GL_TEXTURE27", - }, - { - 0x84DC, - "GL_TEXTURE28", - }, - { - 0x84DD, - "GL_TEXTURE29", - }, - { - 0x84DE, - "GL_TEXTURE30", - }, - { - 0x84DF, - "GL_TEXTURE31", - }, - { - 0x84E0, - "GL_ACTIVE_TEXTURE", - }, - { - 0x84E3, - "GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV", - }, - { - 0x84E4, - "GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV", - }, - { - 0x84E8, - "GL_MAX_RENDERBUFFER_SIZE", - }, - { - 0x84F2, - "GL_ALL_COMPLETED_NV", - }, - { - 0x84F3, - "GL_FENCE_STATUS_NV", - }, - { - 0x84F4, - "GL_FENCE_CONDITION_NV", - }, - { - 0x84F5, - "GL_TEXTURE_RECTANGLE_ARB", - }, - { - 0x84F6, - "GL_TEXTURE_BINDING_RECTANGLE_ARB", - }, - { - 0x84F7, - "GL_COMMANDS_COMPLETED_CHROMIUM", - }, - { - 0x84F8, - "GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM", - }, - { - 0x84F9, - "GL_DEPTH_STENCIL_OES", - }, - { - 0x84FA, - "GL_UNSIGNED_INT_24_8_OES", - }, - { - 0x84FD, - "GL_MAX_TEXTURE_LOD_BIAS", - }, - { - 0x84FE, - "GL_TEXTURE_MAX_ANISOTROPY_EXT", - }, - { - 0x84FF, - "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT", - }, - { - 0x8507, - "GL_INCR_WRAP", - }, - { - 0x8508, - "GL_DECR_WRAP", - }, - { - 0x8513, - "GL_TEXTURE_CUBE_MAP", - }, - { - 0x8514, - "GL_TEXTURE_BINDING_CUBE_MAP", - }, - { - 0x8515, - "GL_TEXTURE_CUBE_MAP_POSITIVE_X", - }, - { - 0x8516, - "GL_TEXTURE_CUBE_MAP_NEGATIVE_X", - }, - { - 0x8517, - "GL_TEXTURE_CUBE_MAP_POSITIVE_Y", - }, - { - 0x8518, - "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y", - }, - { - 0x8519, - "GL_TEXTURE_CUBE_MAP_POSITIVE_Z", - }, - { - 0x851A, - "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z", - }, - { - 0x851C, - "GL_MAX_CUBE_MAP_TEXTURE_SIZE", - }, - { - 0x8589, - "GL_SRC1_ALPHA_EXT", - }, - { - 0x85B5, - "GL_VERTEX_ARRAY_BINDING_OES", - }, - { - 0x85BA, - "GL_UNSIGNED_SHORT_8_8_APPLE", - }, - { - 0x85BB, - "GL_UNSIGNED_SHORT_8_8_REV_APPLE", - }, - { - 0x8622, - "GL_VERTEX_ATTRIB_ARRAY_ENABLED", - }, - { - 0x8623, - "GL_VERTEX_ATTRIB_ARRAY_SIZE", - }, - { - 0x8624, - "GL_VERTEX_ATTRIB_ARRAY_STRIDE", - }, - { - 0x8625, - "GL_VERTEX_ATTRIB_ARRAY_TYPE", - }, - { - 0x8626, - "GL_CURRENT_VERTEX_ATTRIB", - }, - { - 0x8645, - "GL_VERTEX_ATTRIB_ARRAY_POINTER", - }, - { - 0x864F, - "GL_DEPTH_CLAMP_EXT", - }, - { - 0x86A1, - "GL_TEXTURE_COMPRESSED", - }, - { - 0x86A2, - "GL_NUM_COMPRESSED_TEXTURE_FORMATS", - }, - { - 0x86A3, - "GL_COMPRESSED_TEXTURE_FORMATS", - }, - { - 0x8740, - "GL_Z400_BINARY_AMD", - }, - { - 0x8741, - "GL_PROGRAM_BINARY_LENGTH_OES", - }, - { - 0x8743, - "GL_MIRROR_CLAMP_TO_EDGE_EXT", - }, - { - 0x875F, - "GL_PROGRAM_BINARY_FORMAT_MESA", - }, - { - 0x8764, - "GL_BUFFER_SIZE", - }, - { - 0x8765, - "GL_BUFFER_USAGE", - }, - { - 0x87EE, - "GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD", - }, - { - 0x87F9, - "GL_3DC_X_AMD", - }, - { - 0x87FA, - "GL_3DC_XY_AMD", - }, - { - 0x87FE, - "GL_NUM_PROGRAM_BINARY_FORMATS_OES", - }, - { - 0x87FF, - "GL_PROGRAM_BINARY_FORMATS_OES", - }, - { - 0x8800, - "GL_STENCIL_BACK_FUNC", - }, - { - 0x8801, - "GL_STENCIL_BACK_FAIL", - }, - { - 0x8802, - "GL_STENCIL_BACK_PASS_DEPTH_FAIL", - }, - { - 0x8803, - "GL_STENCIL_BACK_PASS_DEPTH_PASS", - }, - { - 0x8814, - "GL_RGBA32F_EXT", - }, - { - 0x8815, - "GL_RGB32F_EXT", - }, - { - 0x8816, - "GL_ALPHA32F_EXT", - }, - { - 0x8818, - "GL_LUMINANCE32F_EXT", - }, - { - 0x8819, - "GL_LUMINANCE_ALPHA32F_EXT", - }, - { - 0x881A, - "GL_RGBA16F_EXT", - }, - { - 0x881B, - "GL_RGB16F_EXT", - }, - { - 0x881C, - "GL_ALPHA16F_EXT", - }, - { - 0x881E, - "GL_LUMINANCE16F_EXT", - }, - { - 0x881F, - "GL_LUMINANCE_ALPHA16F_EXT", - }, - { - 0x8823, - "GL_WRITEONLY_RENDERING_QCOM", - }, - { - 0x8824, - "GL_MAX_DRAW_BUFFERS_EXT", - }, - { - 0x8825, - "GL_DRAW_BUFFER0_EXT", - }, - { - 0x8826, - "GL_DRAW_BUFFER1_EXT", - }, - { - 0x8827, - "GL_DRAW_BUFFER2_EXT", - }, - { - 0x8828, - "GL_DRAW_BUFFER3_EXT", - }, - { - 0x8829, - "GL_DRAW_BUFFER4_EXT", - }, - { - 0x882A, - "GL_DRAW_BUFFER5_EXT", - }, - { - 0x882B, - "GL_DRAW_BUFFER6_EXT", - }, - { - 0x882C, - "GL_DRAW_BUFFER7_EXT", - }, - { - 0x882D, - "GL_DRAW_BUFFER8_EXT", - }, - { - 0x882E, - "GL_DRAW_BUFFER9_EXT", - }, - { - 0x882F, - "GL_DRAW_BUFFER10_EXT", - }, - { - 0x8830, - "GL_DRAW_BUFFER11_EXT", - }, - { - 0x8831, - "GL_DRAW_BUFFER12_EXT", - }, - { - 0x8832, - "GL_DRAW_BUFFER13_EXT", - }, - { - 0x8833, - "GL_DRAW_BUFFER14_EXT", - }, - { - 0x8834, - "GL_DRAW_BUFFER15_EXT", - }, - { - 0x883D, - "GL_BLEND_EQUATION_ALPHA", - }, - { - 0x884A, - "GL_TEXTURE_DEPTH_SIZE", - }, - { - 0x884C, - "GL_TEXTURE_COMPARE_MODE_EXT", - }, - { - 0x884D, - "GL_TEXTURE_COMPARE_FUNC_EXT", - }, - { - 0x884E, - "GL_COMPARE_REF_TO_TEXTURE_EXT", - }, - { - 0x8864, - "GL_QUERY_COUNTER_BITS_EXT", - }, - { - 0x8865, - "GL_CURRENT_QUERY_EXT", - }, - { - 0x8866, - "GL_QUERY_RESULT_EXT", - }, - { - 0x8867, - "GL_QUERY_RESULT_AVAILABLE_EXT", - }, - { - 0x8868, - "GL_QUERY_RESULT_AVAILABLE_NO_FLUSH_CHROMIUM_EXT", - }, - { - 0x8869, - "GL_MAX_VERTEX_ATTRIBS", - }, - { - 0x886A, - "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED", - }, - { - 0x886C, - "GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES", - }, - { - 0x886D, - "GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES", - }, - { - 0x8872, - "GL_MAX_TEXTURE_IMAGE_UNITS", - }, - { - 0x887F, - "GL_GEOMETRY_SHADER_INVOCATIONS_OES", - }, - { - 0x8892, - "GL_ARRAY_BUFFER", - }, - { - 0x8893, - "GL_ELEMENT_ARRAY_BUFFER", - }, - { - 0x8894, - "GL_ARRAY_BUFFER_BINDING", - }, - { - 0x8895, - "GL_ELEMENT_ARRAY_BUFFER_BINDING", - }, - { - 0x889F, - "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING", - }, - { - 0x88B8, - "GL_READ_ONLY", - }, - { - 0x88B9, - "GL_WRITE_ONLY_OES", - }, - { - 0x88BA, - "GL_READ_WRITE", - }, - { - 0x88BB, - "GL_BUFFER_ACCESS_OES", - }, - { - 0x88BC, - "GL_BUFFER_MAPPED_OES", - }, - { - 0x88BD, - "GL_BUFFER_MAP_POINTER_OES", - }, - { - 0x88BF, - "GL_TIME_ELAPSED_EXT", - }, - { - 0x88E0, - "GL_STREAM_DRAW", - }, - { - 0x88E1, - "GL_STREAM_READ", - }, - { - 0x88E2, - "GL_STREAM_COPY", - }, - { - 0x88E4, - "GL_STATIC_DRAW", - }, - { - 0x88E5, - "GL_STATIC_READ", - }, - { - 0x88E6, - "GL_STATIC_COPY", - }, - { - 0x88E8, - "GL_DYNAMIC_DRAW", - }, - { - 0x88E9, - "GL_DYNAMIC_READ", - }, - { - 0x88EA, - "GL_DYNAMIC_COPY", - }, - { - 0x88EB, - "GL_PIXEL_PACK_BUFFER_NV", - }, - { - 0x88EC, - "GL_PIXEL_UNPACK_BUFFER_NV", - }, - { - 0x88ED, - "GL_PIXEL_PACK_BUFFER_BINDING_NV", - }, - { - 0x88EE, - "GL_ETC1_SRGB8_NV", - }, - { - 0x88EF, - "GL_PIXEL_UNPACK_BUFFER_BINDING_NV", - }, - { - 0x88F0, - "GL_DEPTH24_STENCIL8_OES", - }, - { - 0x88F1, - "GL_TEXTURE_STENCIL_SIZE", - }, - { - 0x88F9, - "GL_SRC1_COLOR_EXT", - }, - { - 0x88FA, - "GL_ONE_MINUS_SRC1_COLOR_EXT", - }, - { - 0x88FB, - "GL_ONE_MINUS_SRC1_ALPHA_EXT", - }, - { - 0x88FC, - "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT", - }, - { - 0x88FD, - "GL_VERTEX_ATTRIB_ARRAY_INTEGER", - }, - { - 0x88FE, - "GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE", - }, - { - 0x88FF, - "GL_MAX_ARRAY_TEXTURE_LAYERS", - }, - { - 0x8904, - "GL_MIN_PROGRAM_TEXEL_OFFSET", - }, - { - 0x8905, - "GL_MAX_PROGRAM_TEXEL_OFFSET", - }, - { - 0x8914, - "GL_SAMPLES_PASSED_ARB", - }, - { - 0x8916, - "GL_GEOMETRY_LINKED_VERTICES_OUT_OES", - }, - { - 0x8917, - "GL_GEOMETRY_LINKED_INPUT_TYPE_OES", - }, - { - 0x8918, - "GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES", - }, - { - 0x8919, - "GL_SAMPLER_BINDING", - }, - { - 0x8A11, - "GL_UNIFORM_BUFFER", - }, - { - 0x8A1F, - "GL_RGB_422_APPLE", - }, - { - 0x8A28, - "GL_UNIFORM_BUFFER_BINDING", - }, - { - 0x8A29, - "GL_UNIFORM_BUFFER_START", - }, - { - 0x8A2A, - "GL_UNIFORM_BUFFER_SIZE", - }, - { - 0x8A2B, - "GL_MAX_VERTEX_UNIFORM_BLOCKS", - }, - { - 0x8A2C, - "GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES", - }, - { - 0x8A2D, - "GL_MAX_FRAGMENT_UNIFORM_BLOCKS", - }, - { - 0x8A2E, - "GL_MAX_COMBINED_UNIFORM_BLOCKS", - }, - { - 0x8A2F, - "GL_MAX_UNIFORM_BUFFER_BINDINGS", - }, - { - 0x8A30, - "GL_MAX_UNIFORM_BLOCK_SIZE", - }, - { - 0x8A31, - "GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS", - }, - { - 0x8A32, - "GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES", - }, - { - 0x8A33, - "GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS", - }, - { - 0x8A34, - "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT", - }, - { - 0x8A35, - "GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH", - }, - { - 0x8A36, - "GL_ACTIVE_UNIFORM_BLOCKS", - }, - { - 0x8A37, - "GL_UNIFORM_TYPE", - }, - { - 0x8A38, - "GL_UNIFORM_SIZE", - }, - { - 0x8A39, - "GL_UNIFORM_NAME_LENGTH", - }, - { - 0x8A3A, - "GL_UNIFORM_BLOCK_INDEX", - }, - { - 0x8A3B, - "GL_UNIFORM_OFFSET", - }, - { - 0x8A3C, - "GL_UNIFORM_ARRAY_STRIDE", - }, - { - 0x8A3D, - "GL_UNIFORM_MATRIX_STRIDE", - }, - { - 0x8A3E, - "GL_UNIFORM_IS_ROW_MAJOR", - }, - { - 0x8A3F, - "GL_UNIFORM_BLOCK_BINDING", - }, - { - 0x8A40, - "GL_UNIFORM_BLOCK_DATA_SIZE", - }, - { - 0x8A41, - "GL_UNIFORM_BLOCK_NAME_LENGTH", - }, - { - 0x8A42, - "GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS", - }, - { - 0x8A43, - "GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES", - }, - { - 0x8A44, - "GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER", - }, - { - 0x8A46, - "GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER", - }, - { - 0x8A48, - "GL_TEXTURE_SRGB_DECODE_EXT", - }, - { - 0x8A49, - "GL_DECODE_EXT", - }, - { - 0x8A4A, - "GL_SKIP_DECODE_EXT", - }, - { - 0x8A4F, - "GL_PROGRAM_PIPELINE_OBJECT_EXT", - }, - { - 0x8A51, - "GL_RGB_RAW_422_APPLE", - }, - { - 0x8A52, - "GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT", - }, - { - 0x8A53, - "GL_SYNC_OBJECT_APPLE", - }, - { - 0x8A54, - "GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT", - }, - { - 0x8A55, - "GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT", - }, - { - 0x8A56, - "GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT", - }, - { - 0x8A57, - "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT", - }, - { - 0x8AF6, - "GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM", - }, - { - 0x8AF7, - "GL_SHARED_IMAGE_ACCESS_MODE_READWRITE_CHROMIUM", - }, - { - 0x8B30, - "GL_FRAGMENT_SHADER", - }, - { - 0x8B31, - "GL_VERTEX_SHADER", - }, - { - 0x8B40, - "GL_PROGRAM_OBJECT_EXT", - }, - { - 0x8B48, - "GL_SHADER_OBJECT_EXT", - }, - { - 0x8B49, - "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS", - }, - { - 0x8B4A, - "GL_MAX_VERTEX_UNIFORM_COMPONENTS", - }, - { - 0x8B4B, - "GL_MAX_VARYING_COMPONENTS", - }, - { - 0x8B4C, - "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS", - }, - { - 0x8B4D, - "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS", - }, - { - 0x8B4F, - "GL_SHADER_TYPE", - }, - { - 0x8B50, - "GL_FLOAT_VEC2", - }, - { - 0x8B51, - "GL_FLOAT_VEC3", - }, - { - 0x8B52, - "GL_FLOAT_VEC4", - }, - { - 0x8B53, - "GL_INT_VEC2", - }, - { - 0x8B54, - "GL_INT_VEC3", - }, - { - 0x8B55, - "GL_INT_VEC4", - }, - { - 0x8B56, - "GL_BOOL", - }, - { - 0x8B57, - "GL_BOOL_VEC2", - }, - { - 0x8B58, - "GL_BOOL_VEC3", - }, - { - 0x8B59, - "GL_BOOL_VEC4", - }, - { - 0x8B5A, - "GL_FLOAT_MAT2", - }, - { - 0x8B5B, - "GL_FLOAT_MAT3", - }, - { - 0x8B5C, - "GL_FLOAT_MAT4", - }, - { - 0x8B5E, - "GL_SAMPLER_2D", - }, - { - 0x8B5F, - "GL_SAMPLER_3D_OES", - }, - { - 0x8B60, - "GL_SAMPLER_CUBE", - }, - { - 0x8B62, - "GL_SAMPLER_2D_SHADOW_EXT", - }, - { - 0x8B63, - "GL_SAMPLER_2D_RECT_ARB", - }, - { - 0x8B65, - "GL_FLOAT_MAT2x3_NV", - }, - { - 0x8B66, - "GL_FLOAT_MAT2x4_NV", - }, - { - 0x8B67, - "GL_FLOAT_MAT3x2_NV", - }, - { - 0x8B68, - "GL_FLOAT_MAT3x4_NV", - }, - { - 0x8B69, - "GL_FLOAT_MAT4x2_NV", - }, - { - 0x8B6A, - "GL_FLOAT_MAT4x3_NV", - }, - { - 0x8B80, - "GL_DELETE_STATUS", - }, - { - 0x8B81, - "GL_COMPILE_STATUS", - }, - { - 0x8B82, - "GL_LINK_STATUS", - }, - { - 0x8B83, - "GL_VALIDATE_STATUS", - }, - { - 0x8B84, - "GL_INFO_LOG_LENGTH", - }, - { - 0x8B85, - "GL_ATTACHED_SHADERS", - }, - { - 0x8B86, - "GL_ACTIVE_UNIFORMS", - }, - { - 0x8B87, - "GL_ACTIVE_UNIFORM_MAX_LENGTH", - }, - { - 0x8B88, - "GL_SHADER_SOURCE_LENGTH", - }, - { - 0x8B89, - "GL_ACTIVE_ATTRIBUTES", - }, - { - 0x8B8A, - "GL_ACTIVE_ATTRIBUTE_MAX_LENGTH", - }, - { - 0x8B8B, - "GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES", - }, - { - 0x8B8C, - "GL_SHADING_LANGUAGE_VERSION", - }, - { - 0x8B8D, - "GL_CURRENT_PROGRAM", - }, - { - 0x8B90, - "GL_PALETTE4_RGB8_OES", - }, - { - 0x8B91, - "GL_PALETTE4_RGBA8_OES", - }, - { - 0x8B92, - "GL_PALETTE4_R5_G6_B5_OES", - }, - { - 0x8B93, - "GL_PALETTE4_RGBA4_OES", - }, - { - 0x8B94, - "GL_PALETTE4_RGB5_A1_OES", - }, - { - 0x8B95, - "GL_PALETTE8_RGB8_OES", - }, - { - 0x8B96, - "GL_PALETTE8_RGBA8_OES", - }, - { - 0x8B97, - "GL_PALETTE8_R5_G6_B5_OES", - }, - { - 0x8B98, - "GL_PALETTE8_RGBA4_OES", - }, - { - 0x8B99, - "GL_PALETTE8_RGB5_A1_OES", - }, - { - 0x8B9A, - "GL_IMPLEMENTATION_COLOR_READ_TYPE", - }, - { - 0x8B9B, - "GL_IMPLEMENTATION_COLOR_READ_FORMAT", - }, - { - 0x8BBB, - "GL_FRAMEBUFFER_FLIP_Y_MESA", - }, - { - 0x8BC0, - "GL_COUNTER_TYPE_AMD", - }, - { - 0x8BC1, - "GL_COUNTER_RANGE_AMD", - }, - { - 0x8BC2, - "GL_UNSIGNED_INT64_AMD", - }, - { - 0x8BC3, - "GL_PERCENTAGE_AMD", - }, - { - 0x8BC4, - "GL_PERFMON_RESULT_AVAILABLE_AMD", - }, - { - 0x8BC5, - "GL_PERFMON_RESULT_SIZE_AMD", - }, - { - 0x8BC6, - "GL_PERFMON_RESULT_AMD", - }, - { - 0x8BD2, - "GL_TEXTURE_WIDTH_QCOM", - }, - { - 0x8BD3, - "GL_TEXTURE_HEIGHT_QCOM", - }, - { - 0x8BD4, - "GL_TEXTURE_DEPTH_QCOM", - }, - { - 0x8BD5, - "GL_TEXTURE_INTERNAL_FORMAT_QCOM", - }, - { - 0x8BD6, - "GL_TEXTURE_FORMAT_QCOM", - }, - { - 0x8BD7, - "GL_TEXTURE_TYPE_QCOM", - }, - { - 0x8BD8, - "GL_TEXTURE_IMAGE_VALID_QCOM", - }, - { - 0x8BD9, - "GL_TEXTURE_NUM_LEVELS_QCOM", - }, - { - 0x8BDA, - "GL_TEXTURE_TARGET_QCOM", - }, - { - 0x8BDB, - "GL_TEXTURE_OBJECT_VALID_QCOM", - }, - { - 0x8BDC, - "GL_STATE_RESTORE", - }, - { - 0x8BE7, - "GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT", - }, - { - 0x8BFA, - "GL_TEXTURE_PROTECTED_EXT", - }, - { - 0x8BFB, - "GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM", - }, - { - 0x8BFC, - "GL_TEXTURE_FOVEATED_MIN_PIXEL_DENSITY_QCOM", - }, - { - 0x8BFD, - "GL_TEXTURE_FOVEATED_FEATURE_QUERY_QCOM", - }, - { - 0x8BFE, - "GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM", - }, - { - 0x8BFF, - "GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM", - }, - { - 0x8C00, - "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG", - }, - { - 0x8C01, - "GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG", - }, - { - 0x8C02, - "GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG", - }, - { - 0x8C03, - "GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG", - }, - { - 0x8C0A, - "GL_SGX_BINARY_IMG", - }, - { - 0x8C10, - "GL_TEXTURE_RED_TYPE", - }, - { - 0x8C11, - "GL_TEXTURE_GREEN_TYPE", - }, - { - 0x8C12, - "GL_TEXTURE_BLUE_TYPE", - }, - { - 0x8C13, - "GL_TEXTURE_ALPHA_TYPE", - }, - { - 0x8C16, - "GL_TEXTURE_DEPTH_TYPE", - }, - { - 0x8C17, - "GL_UNSIGNED_NORMALIZED_EXT", - }, - { - 0x8C1A, - "GL_TEXTURE_2D_ARRAY", - }, - { - 0x8C1D, - "GL_TEXTURE_BINDING_2D_ARRAY", - }, - { - 0x8C29, - "GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES", - }, - { - 0x8C2A, - "GL_TEXTURE_BUFFER_OES", - }, - { - 0x8C2B, - "GL_MAX_TEXTURE_BUFFER_SIZE_OES", - }, - { - 0x8C2C, - "GL_TEXTURE_BINDING_BUFFER_OES", - }, - { - 0x8C2D, - "GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES", - }, - { - 0x8C2F, - "GL_ANY_SAMPLES_PASSED_EXT", - }, - { - 0x8C36, - "GL_SAMPLE_SHADING_OES", - }, - { - 0x8C37, - "GL_MIN_SAMPLE_SHADING_VALUE_OES", - }, - { - 0x8C3A, - "GL_R11F_G11F_B10F_APPLE", - }, - { - 0x8C3B, - "GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE", - }, - { - 0x8C3D, - "GL_RGB9_E5_APPLE", - }, - { - 0x8C3E, - "GL_UNSIGNED_INT_5_9_9_9_REV_APPLE", - }, - { - 0x8C3F, - "GL_TEXTURE_SHARED_SIZE", - }, - { - 0x8C40, - "GL_SRGB_EXT", - }, - { - 0x8C41, - "GL_SRGB8_NV", - }, - { - 0x8C42, - "GL_SRGB_ALPHA_EXT", - }, - { - 0x8C43, - "GL_SRGB8_ALPHA8_EXT", - }, - { - 0x8C44, - "GL_SLUMINANCE_ALPHA_NV", - }, - { - 0x8C45, - "GL_SLUMINANCE8_ALPHA8_NV", - }, - { - 0x8C46, - "GL_SLUMINANCE_NV", - }, - { - 0x8C47, - "GL_SLUMINANCE8_NV", - }, - { - 0x8C4C, - "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT", - }, - { - 0x8C4D, - "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT", - }, - { - 0x8C4E, - "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT", - }, - { - 0x8C4F, - "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT", - }, - { - 0x8C76, - "GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH", - }, - { - 0x8C7F, - "GL_TRANSFORM_FEEDBACK_BUFFER_MODE", - }, - { - 0x8C80, - "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS", - }, - { - 0x8C83, - "GL_TRANSFORM_FEEDBACK_VARYINGS", - }, - { - 0x8C84, - "GL_TRANSFORM_FEEDBACK_BUFFER_START", - }, - { - 0x8C85, - "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE", - }, - { - 0x8C87, - "GL_PRIMITIVES_GENERATED_OES", - }, - { - 0x8C88, - "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN", - }, - { - 0x8C89, - "GL_RASTERIZER_DISCARD", - }, - { - 0x8C8A, - "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS", - }, - { - 0x8C8B, - "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS", - }, - { - 0x8C8C, - "GL_INTERLEAVED_ATTRIBS", - }, - { - 0x8C8D, - "GL_SEPARATE_ATTRIBS", - }, - { - 0x8C8E, - "GL_TRANSFORM_FEEDBACK_BUFFER", - }, - { - 0x8C8F, - "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING", - }, - { - 0x8C92, - "GL_ATC_RGB_AMD", - }, - { - 0x8C93, - "GL_ATC_RGBA_EXPLICIT_ALPHA_AMD", - }, - { - 0x8CA1, - "GL_LOWER_LEFT_EXT", - }, - { - 0x8CA2, - "GL_UPPER_LEFT_EXT", - }, - { - 0x8CA3, - "GL_STENCIL_BACK_REF", - }, - { - 0x8CA4, - "GL_STENCIL_BACK_VALUE_MASK", - }, - { - 0x8CA5, - "GL_STENCIL_BACK_WRITEMASK", - }, - { - 0x8CA6, - "GL_FRAMEBUFFER_BINDING", - }, - { - 0x8CA7, - "GL_RENDERBUFFER_BINDING", - }, - { - 0x8CA8, - "GL_READ_FRAMEBUFFER_ANGLE", - }, - { - 0x8CA9, - "GL_DRAW_FRAMEBUFFER_ANGLE", - }, - { - 0x8CAA, - "GL_READ_FRAMEBUFFER_BINDING_ANGLE", - }, - { - 0x8CAB, - "GL_RENDERBUFFER_SAMPLES_ANGLE", - }, - { - 0x8CAC, - "GL_DEPTH_COMPONENT32F", - }, - { - 0x8CAD, - "GL_DEPTH32F_STENCIL8", - }, - { - 0x8CD0, - "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE", - }, - { - 0x8CD1, - "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME", - }, - { - 0x8CD2, - "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL", - }, - { - 0x8CD3, - "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE", - }, - { - 0x8CD4, - "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES", - }, - { - 0x8CD5, - "GL_FRAMEBUFFER_COMPLETE", - }, - { - 0x8CD6, - "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT", - }, - { - 0x8CD7, - "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT", - }, - { - 0x8CD9, - "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS", - }, - { - 0x8CDD, - "GL_FRAMEBUFFER_UNSUPPORTED", - }, - { - 0x8CDF, - "GL_MAX_COLOR_ATTACHMENTS_EXT", - }, - { - 0x8CE0, - "GL_COLOR_ATTACHMENT0", - }, - { - 0x8CE1, - "GL_COLOR_ATTACHMENT1_EXT", - }, - { - 0x8CE2, - "GL_COLOR_ATTACHMENT2_EXT", - }, - { - 0x8CE3, - "GL_COLOR_ATTACHMENT3_EXT", - }, - { - 0x8CE4, - "GL_COLOR_ATTACHMENT4_EXT", - }, - { - 0x8CE5, - "GL_COLOR_ATTACHMENT5_EXT", - }, - { - 0x8CE6, - "GL_COLOR_ATTACHMENT6_EXT", - }, - { - 0x8CE7, - "GL_COLOR_ATTACHMENT7_EXT", - }, - { - 0x8CE8, - "GL_COLOR_ATTACHMENT8_EXT", - }, - { - 0x8CE9, - "GL_COLOR_ATTACHMENT9_EXT", - }, - { - 0x8CEA, - "GL_COLOR_ATTACHMENT10_EXT", - }, - { - 0x8CEB, - "GL_COLOR_ATTACHMENT11_EXT", - }, - { - 0x8CEC, - "GL_COLOR_ATTACHMENT12_EXT", - }, - { - 0x8CED, - "GL_COLOR_ATTACHMENT13_EXT", - }, - { - 0x8CEE, - "GL_COLOR_ATTACHMENT14_EXT", - }, - { - 0x8CEF, - "GL_COLOR_ATTACHMENT15_EXT", - }, - { - 0x8CF0, - "GL_COLOR_ATTACHMENT16", - }, - { - 0x8CF1, - "GL_COLOR_ATTACHMENT17", - }, - { - 0x8CF2, - "GL_COLOR_ATTACHMENT18", - }, - { - 0x8CF3, - "GL_COLOR_ATTACHMENT19", - }, - { - 0x8CF4, - "GL_COLOR_ATTACHMENT20", - }, - { - 0x8CF5, - "GL_COLOR_ATTACHMENT21", - }, - { - 0x8CF6, - "GL_COLOR_ATTACHMENT22", - }, - { - 0x8CF7, - "GL_COLOR_ATTACHMENT23", - }, - { - 0x8CF8, - "GL_COLOR_ATTACHMENT24", - }, - { - 0x8CF9, - "GL_COLOR_ATTACHMENT25", - }, - { - 0x8CFA, - "GL_COLOR_ATTACHMENT26", - }, - { - 0x8CFB, - "GL_COLOR_ATTACHMENT27", - }, - { - 0x8CFC, - "GL_COLOR_ATTACHMENT28", - }, - { - 0x8CFD, - "GL_COLOR_ATTACHMENT29", - }, - { - 0x8CFE, - "GL_COLOR_ATTACHMENT30", - }, - { - 0x8CFF, - "GL_COLOR_ATTACHMENT31", - }, - { - 0x8D00, - "GL_DEPTH_ATTACHMENT", - }, - { - 0x8D20, - "GL_STENCIL_ATTACHMENT", - }, - { - 0x8D40, - "GL_FRAMEBUFFER", - }, - { - 0x8D41, - "GL_RENDERBUFFER", - }, - { - 0x8D42, - "GL_RENDERBUFFER_WIDTH", - }, - { - 0x8D43, - "GL_RENDERBUFFER_HEIGHT", - }, - { - 0x8D44, - "GL_RENDERBUFFER_INTERNAL_FORMAT", - }, - { - 0x8D46, - "GL_STENCIL_INDEX1_OES", - }, - { - 0x8D47, - "GL_STENCIL_INDEX4_OES", - }, - { - 0x8D48, - "GL_STENCIL_INDEX8", - }, - { - 0x8D50, - "GL_RENDERBUFFER_RED_SIZE", - }, - { - 0x8D51, - "GL_RENDERBUFFER_GREEN_SIZE", - }, - { - 0x8D52, - "GL_RENDERBUFFER_BLUE_SIZE", - }, - { - 0x8D53, - "GL_RENDERBUFFER_ALPHA_SIZE", - }, - { - 0x8D54, - "GL_RENDERBUFFER_DEPTH_SIZE", - }, - { - 0x8D55, - "GL_RENDERBUFFER_STENCIL_SIZE", - }, - { - 0x8D56, - "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE", - }, - { - 0x8D57, - "GL_MAX_SAMPLES_ANGLE", - }, - { - 0x8D61, - "GL_HALF_FLOAT_OES", - }, - { - 0x8D62, - "GL_RGB565", - }, - { - 0x8D64, - "GL_ETC1_RGB8_OES", - }, - { - 0x8D65, - "GL_TEXTURE_EXTERNAL_OES", - }, - { - 0x8D66, - "GL_SAMPLER_EXTERNAL_OES", - }, - { - 0x8D67, - "GL_TEXTURE_BINDING_EXTERNAL_OES", - }, - { - 0x8D68, - "GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES", - }, - { - 0x8D69, - "GL_PRIMITIVE_RESTART_FIXED_INDEX", - }, - { - 0x8D6A, - "GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT", - }, - { - 0x8D6B, - "GL_MAX_ELEMENT_INDEX", - }, - { - 0x8D6C, - "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT", - }, - { - 0x8D70, - "GL_RGBA32UI", - }, - { - 0x8D71, - "GL_RGB32UI", - }, - { - 0x8D76, - "GL_RGBA16UI", - }, - { - 0x8D77, - "GL_RGB16UI", - }, - { - 0x8D7C, - "GL_RGBA8UI", - }, - { - 0x8D7D, - "GL_RGB8UI", - }, - { - 0x8D82, - "GL_RGBA32I", - }, - { - 0x8D83, - "GL_RGB32I", - }, - { - 0x8D88, - "GL_RGBA16I", - }, - { - 0x8D89, - "GL_RGB16I", - }, - { - 0x8D8E, - "GL_RGBA8I", - }, - { - 0x8D8F, - "GL_RGB8I", - }, - { - 0x8D94, - "GL_RED_INTEGER", - }, - { - 0x8D98, - "GL_RGB_INTEGER", - }, - { - 0x8D99, - "GL_RGBA_INTEGER", - }, - { - 0x8D9F, - "GL_INT_2_10_10_10_REV", - }, - { - 0x8DA7, - "GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES", - }, - { - 0x8DA8, - "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES", - }, - { - 0x8DAD, - "GL_FLOAT_32_UNSIGNED_INT_24_8_REV", - }, - { - 0x8DB9, - "GL_FRAMEBUFFER_SRGB_EXT", - }, - { - 0x8DBB, - "GL_COMPRESSED_RED_RGTC1_EXT", - }, - { - 0x8DBC, - "GL_COMPRESSED_SIGNED_RED_RGTC1_EXT", - }, - { - 0x8DBD, - "GL_COMPRESSED_RED_GREEN_RGTC2_EXT", - }, - { - 0x8DBE, - "GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT", - }, - { - 0x8DC1, - "GL_SAMPLER_2D_ARRAY", - }, - { - 0x8DC2, - "GL_SAMPLER_BUFFER_OES", - }, - { - 0x8DC4, - "GL_SAMPLER_2D_ARRAY_SHADOW_NV", - }, - { - 0x8DC5, - "GL_SAMPLER_CUBE_SHADOW_NV", - }, - { - 0x8DC6, - "GL_UNSIGNED_INT_VEC2", - }, - { - 0x8DC7, - "GL_UNSIGNED_INT_VEC3", - }, - { - 0x8DC8, - "GL_UNSIGNED_INT_VEC4", - }, - { - 0x8DCA, - "GL_INT_SAMPLER_2D", - }, - { - 0x8DCB, - "GL_INT_SAMPLER_3D", - }, - { - 0x8DCC, - "GL_INT_SAMPLER_CUBE", - }, - { - 0x8DCF, - "GL_INT_SAMPLER_2D_ARRAY", - }, - { - 0x8DD0, - "GL_INT_SAMPLER_BUFFER_OES", - }, - { - 0x8DD2, - "GL_UNSIGNED_INT_SAMPLER_2D", - }, - { - 0x8DD3, - "GL_UNSIGNED_INT_SAMPLER_3D", - }, - { - 0x8DD4, - "GL_UNSIGNED_INT_SAMPLER_CUBE", - }, - { - 0x8DD7, - "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY", - }, - { - 0x8DD8, - "GL_UNSIGNED_INT_SAMPLER_BUFFER_OES", - }, - { - 0x8DD9, - "GL_GEOMETRY_SHADER_OES", - }, - { - 0x8DDF, - "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES", - }, - { - 0x8DE0, - "GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES", - }, - { - 0x8DE1, - "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES", - }, - { - 0x8DF0, - "GL_LOW_FLOAT", - }, - { - 0x8DF1, - "GL_MEDIUM_FLOAT", - }, - { - 0x8DF2, - "GL_HIGH_FLOAT", - }, - { - 0x8DF3, - "GL_LOW_INT", - }, - { - 0x8DF4, - "GL_MEDIUM_INT", - }, - { - 0x8DF5, - "GL_HIGH_INT", - }, - { - 0x8DF6, - "GL_UNSIGNED_INT_10_10_10_2_OES", - }, - { - 0x8DF7, - "GL_INT_10_10_10_2_OES", - }, - { - 0x8DF8, - "GL_SHADER_BINARY_FORMATS", - }, - { - 0x8DF9, - "GL_NUM_SHADER_BINARY_FORMATS", - }, - { - 0x8DFA, - "GL_SHADER_COMPILER", - }, - { - 0x8DFB, - "GL_MAX_VERTEX_UNIFORM_VECTORS", - }, - { - 0x8DFC, - "GL_MAX_VARYING_VECTORS", - }, - { - 0x8DFD, - "GL_MAX_FRAGMENT_UNIFORM_VECTORS", - }, - { - 0x8E13, - "GL_QUERY_WAIT_NV", - }, - { - 0x8E14, - "GL_QUERY_NO_WAIT_NV", - }, - { - 0x8E15, - "GL_QUERY_BY_REGION_WAIT_NV", - }, - { - 0x8E16, - "GL_QUERY_BY_REGION_NO_WAIT_NV", - }, - { - 0x8E1B, - "GL_POLYGON_OFFSET_CLAMP_EXT", - }, - { - 0x8E1E, - "GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES", - }, - { - 0x8E1F, - "GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES", - }, - { - 0x8E20, - "GL_COLOR_SAMPLES_NV", - }, - { - 0x8E22, - "GL_TRANSFORM_FEEDBACK", - }, - { - 0x8E23, - "GL_TRANSFORM_FEEDBACK_PAUSED", - }, - { - 0x8E24, - "GL_TRANSFORM_FEEDBACK_ACTIVE", - }, - { - 0x8E25, - "GL_TRANSFORM_FEEDBACK_BINDING", - }, - { - 0x8E28, - "GL_TIMESTAMP_EXT", - }, - { - 0x8E2C, - "GL_DEPTH_COMPONENT16_NONLINEAR_NV", - }, - { - 0x8E42, - "GL_TEXTURE_SWIZZLE_R", - }, - { - 0x8E43, - "GL_TEXTURE_SWIZZLE_G", - }, - { - 0x8E44, - "GL_TEXTURE_SWIZZLE_B", - }, - { - 0x8E45, - "GL_TEXTURE_SWIZZLE_A", - }, - { - 0x8E4D, - "GL_FIRST_VERTEX_CONVENTION_OES", - }, - { - 0x8E4E, - "GL_LAST_VERTEX_CONVENTION_OES", - }, - { - 0x8E4F, - "GL_PROVOKING_VERTEX_ANGLE", - }, - { - 0x8E50, - "GL_SAMPLE_LOCATION_NV", - }, - { - 0x8E51, - "GL_SAMPLE_MASK", - }, - { - 0x8E52, - "GL_SAMPLE_MASK_VALUE", - }, - { - 0x8E59, - "GL_MAX_SAMPLE_MASK_WORDS", - }, - { - 0x8E5A, - "GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES", - }, - { - 0x8E5B, - "GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES", - }, - { - 0x8E5C, - "GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES", - }, - { - 0x8E5D, - "GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES", - }, - { - 0x8E5E, - "GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET", - }, - { - 0x8E5F, - "GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET", - }, - { - 0x8E60, - "GL_MAX_MESH_UNIFORM_BLOCKS_NV", - }, - { - 0x8E61, - "GL_MAX_MESH_TEXTURE_IMAGE_UNITS_NV", - }, - { - 0x8E62, - "GL_MAX_MESH_IMAGE_UNIFORMS_NV", - }, - { - 0x8E63, - "GL_MAX_MESH_UNIFORM_COMPONENTS_NV", - }, - { - 0x8E64, - "GL_MAX_MESH_ATOMIC_COUNTER_BUFFERS_NV", - }, - { - 0x8E65, - "GL_MAX_MESH_ATOMIC_COUNTERS_NV", - }, - { - 0x8E66, - "GL_MAX_MESH_SHADER_STORAGE_BLOCKS_NV", - }, - { - 0x8E67, - "GL_MAX_COMBINED_MESH_UNIFORM_COMPONENTS_NV", - }, - { - 0x8E68, - "GL_MAX_TASK_UNIFORM_BLOCKS_NV", - }, - { - 0x8E69, - "GL_MAX_TASK_TEXTURE_IMAGE_UNITS_NV", - }, - { - 0x8E6A, - "GL_MAX_TASK_IMAGE_UNIFORMS_NV", - }, - { - 0x8E6B, - "GL_MAX_TASK_UNIFORM_COMPONENTS_NV", - }, - { - 0x8E6C, - "GL_MAX_TASK_ATOMIC_COUNTER_BUFFERS_NV", - }, - { - 0x8E6D, - "GL_MAX_TASK_ATOMIC_COUNTERS_NV", - }, - { - 0x8E6E, - "GL_MAX_TASK_SHADER_STORAGE_BLOCKS_NV", - }, - { - 0x8E6F, - "GL_MAX_COMBINED_TASK_UNIFORM_COMPONENTS_NV", - }, - { - 0x8E72, - "GL_PATCH_VERTICES_OES", - }, - { - 0x8E75, - "GL_TESS_CONTROL_OUTPUT_VERTICES_OES", - }, - { - 0x8E76, - "GL_TESS_GEN_MODE_OES", - }, - { - 0x8E77, - "GL_TESS_GEN_SPACING_OES", - }, - { - 0x8E78, - "GL_TESS_GEN_VERTEX_ORDER_OES", - }, - { - 0x8E79, - "GL_TESS_GEN_POINT_MODE_OES", - }, - { - 0x8E7A, - "GL_ISOLINES_OES", - }, - { - 0x8E7B, - "GL_FRACTIONAL_ODD_OES", - }, - { - 0x8E7C, - "GL_FRACTIONAL_EVEN_OES", - }, - { - 0x8E7D, - "GL_MAX_PATCH_VERTICES_OES", - }, - { - 0x8E7E, - "GL_MAX_TESS_GEN_LEVEL_OES", - }, - { - 0x8E7F, - "GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES", - }, - { - 0x8E80, - "GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES", - }, - { - 0x8E81, - "GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES", - }, - { - 0x8E82, - "GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES", - }, - { - 0x8E83, - "GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES", - }, - { - 0x8E84, - "GL_MAX_TESS_PATCH_COMPONENTS_OES", - }, - { - 0x8E85, - "GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES", - }, - { - 0x8E86, - "GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES", - }, - { - 0x8E87, - "GL_TESS_EVALUATION_SHADER_OES", - }, - { - 0x8E88, - "GL_TESS_CONTROL_SHADER_OES", - }, - { - 0x8E89, - "GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES", - }, - { - 0x8E8A, - "GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES", - }, - { - 0x8E8C, - "GL_COMPRESSED_RGBA_BPTC_UNORM_EXT", - }, - { - 0x8E8D, - "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT", - }, - { - 0x8E8E, - "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT", - }, - { - 0x8E8F, - "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT", - }, - { - 0x8ED0, - "GL_COVERAGE_COMPONENT_NV", - }, - { - 0x8ED1, - "GL_COVERAGE_COMPONENT4_NV", - }, - { - 0x8ED2, - "GL_COVERAGE_ATTACHMENT_NV", - }, - { - 0x8ED3, - "GL_COVERAGE_BUFFERS_NV", - }, - { - 0x8ED4, - "GL_COVERAGE_SAMPLES_NV", - }, - { - 0x8ED5, - "GL_COVERAGE_ALL_FRAGMENTS_NV", - }, - { - 0x8ED6, - "GL_COVERAGE_EDGE_FRAGMENTS_NV", - }, - { - 0x8ED7, - "GL_COVERAGE_AUTOMATIC_NV", - }, - { - 0x8F10, - "GL_INCLUSIVE_EXT", - }, - { - 0x8F11, - "GL_EXCLUSIVE_EXT", - }, - { - 0x8F12, - "GL_WINDOW_RECTANGLE_EXT", - }, - { - 0x8F13, - "GL_WINDOW_RECTANGLE_MODE_EXT", - }, - { - 0x8F14, - "GL_MAX_WINDOW_RECTANGLES_EXT", - }, - { - 0x8F15, - "GL_NUM_WINDOW_RECTANGLES_EXT", - }, - { - 0x8F36, - "GL_COPY_READ_BUFFER_NV", - }, - { - 0x8F37, - "GL_COPY_WRITE_BUFFER_NV", - }, - { - 0x8F38, - "GL_MAX_IMAGE_UNITS", - }, - { - 0x8F39, - "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES", - }, - { - 0x8F3A, - "GL_IMAGE_BINDING_NAME", - }, - { - 0x8F3B, - "GL_IMAGE_BINDING_LEVEL", - }, - { - 0x8F3C, - "GL_IMAGE_BINDING_LAYERED", - }, - { - 0x8F3D, - "GL_IMAGE_BINDING_LAYER", - }, - { - 0x8F3E, - "GL_IMAGE_BINDING_ACCESS", - }, - { - 0x8F3F, - "GL_DRAW_INDIRECT_BUFFER", - }, - { - 0x8F43, - "GL_DRAW_INDIRECT_BUFFER_BINDING", - }, - { - 0x8F4F, - "GL_VERTEX_BINDING_BUFFER", - }, - { - 0x8F60, - "GL_MALI_SHADER_BINARY_ARM", - }, - { - 0x8F61, - "GL_MALI_PROGRAM_BINARY_ARM", - }, - { - 0x8F63, - "GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT", - }, - { - 0x8F64, - "GL_SHADER_PIXEL_LOCAL_STORAGE_EXT", - }, - { - 0x8F65, - "GL_FETCH_PER_SAMPLE_ARM", - }, - { - 0x8F66, - "GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM", - }, - { - 0x8F67, - "GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT", - }, - { - 0x8F69, - "GL_TEXTURE_ASTC_DECODE_PRECISION_EXT", - }, - { - 0x8F94, - "GL_R8_SNORM", - }, - { - 0x8F95, - "GL_RG8_SNORM", - }, - { - 0x8F96, - "GL_RGB8_SNORM", - }, - { - 0x8F97, - "GL_RGBA8_SNORM", - }, - { - 0x8F98, - "GL_R16_SNORM_EXT", - }, - { - 0x8F99, - "GL_RG16_SNORM_EXT", - }, - { - 0x8F9A, - "GL_RGB16_SNORM_EXT", - }, - { - 0x8F9B, - "GL_RGBA16_SNORM_EXT", - }, - { - 0x8F9C, - "GL_SIGNED_NORMALIZED", - }, - { - 0x8FA0, - "GL_PERFMON_GLOBAL_MODE_QCOM", - }, - { - 0x8FA1, - "GL_MAX_SHADER_SUBSAMPLED_IMAGE_UNITS_QCOM", - }, - { - 0x8FB0, - "GL_BINNING_CONTROL_HINT_QCOM", - }, - { - 0x8FB1, - "GL_CPU_OPTIMIZED_QCOM", - }, - { - 0x8FB2, - "GL_GPU_OPTIMIZED_QCOM", - }, - { - 0x8FB3, - "GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM", - }, - { - 0x8FBB, - "GL_GPU_DISJOINT_EXT", - }, - { - 0x8FBD, - "GL_SR8_EXT", - }, - { - 0x8FBE, - "GL_SRG8_EXT", - }, - { - 0x8FBF, - "GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT", - }, - { - 0x8FC4, - "GL_SHADER_BINARY_VIV", - }, - { - 0x8FE0, - "GL_INT8_NV", - }, - { - 0x8FE1, - "GL_INT8_VEC2_NV", - }, - { - 0x8FE2, - "GL_INT8_VEC3_NV", - }, - { - 0x8FE3, - "GL_INT8_VEC4_NV", - }, - { - 0x8FE4, - "GL_INT16_NV", - }, - { - 0x8FE5, - "GL_INT16_VEC2_NV", - }, - { - 0x8FE6, - "GL_INT16_VEC3_NV", - }, - { - 0x8FE7, - "GL_INT16_VEC4_NV", - }, - { - 0x8FE9, - "GL_INT64_VEC2_NV", - }, - { - 0x8FEA, - "GL_INT64_VEC3_NV", - }, - { - 0x8FEB, - "GL_INT64_VEC4_NV", - }, - { - 0x8FEC, - "GL_UNSIGNED_INT8_NV", - }, - { - 0x8FED, - "GL_UNSIGNED_INT8_VEC2_NV", - }, - { - 0x8FEE, - "GL_UNSIGNED_INT8_VEC3_NV", - }, - { - 0x8FEF, - "GL_UNSIGNED_INT8_VEC4_NV", - }, - { - 0x8FF0, - "GL_UNSIGNED_INT16_NV", - }, - { - 0x8FF1, - "GL_UNSIGNED_INT16_VEC2_NV", - }, - { - 0x8FF2, - "GL_UNSIGNED_INT16_VEC3_NV", - }, - { - 0x8FF3, - "GL_UNSIGNED_INT16_VEC4_NV", - }, - { - 0x8FF5, - "GL_UNSIGNED_INT64_VEC2_NV", - }, - { - 0x8FF6, - "GL_UNSIGNED_INT64_VEC3_NV", - }, - { - 0x8FF7, - "GL_UNSIGNED_INT64_VEC4_NV", - }, - { - 0x8FF8, - "GL_FLOAT16_NV", - }, - { - 0x8FF9, - "GL_FLOAT16_VEC2_NV", - }, - { - 0x8FFA, - "GL_FLOAT16_VEC3_NV", - }, - { - 0x8FFB, - "GL_FLOAT16_VEC4_NV", - }, - { - 0x9009, - "GL_TEXTURE_CUBE_MAP_ARRAY_OES", - }, - { - 0x900A, - "GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES", - }, - { - 0x900C, - "GL_SAMPLER_CUBE_MAP_ARRAY_OES", - }, - { - 0x900D, - "GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES", - }, - { - 0x900E, - "GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES", - }, - { - 0x900F, - "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES", - }, - { - 0x901C, - "GL_FACTOR_MIN_AMD", - }, - { - 0x901D, - "GL_FACTOR_MAX_AMD", - }, - { - 0x904D, - "GL_IMAGE_2D", - }, - { - 0x904E, - "GL_IMAGE_3D", - }, - { - 0x9050, - "GL_IMAGE_CUBE", - }, - { - 0x9051, - "GL_IMAGE_BUFFER_OES", - }, - { - 0x9053, - "GL_IMAGE_2D_ARRAY", - }, - { - 0x9054, - "GL_IMAGE_CUBE_MAP_ARRAY_OES", - }, - { - 0x9058, - "GL_INT_IMAGE_2D", - }, - { - 0x9059, - "GL_INT_IMAGE_3D", - }, - { - 0x905B, - "GL_INT_IMAGE_CUBE", - }, - { - 0x905C, - "GL_INT_IMAGE_BUFFER_OES", - }, - { - 0x905E, - "GL_INT_IMAGE_2D_ARRAY", - }, - { - 0x905F, - "GL_INT_IMAGE_CUBE_MAP_ARRAY_OES", - }, - { - 0x9063, - "GL_UNSIGNED_INT_IMAGE_2D", - }, - { - 0x9064, - "GL_UNSIGNED_INT_IMAGE_3D", - }, - { - 0x9066, - "GL_UNSIGNED_INT_IMAGE_CUBE", - }, - { - 0x9067, - "GL_UNSIGNED_INT_IMAGE_BUFFER_OES", - }, - { - 0x9069, - "GL_UNSIGNED_INT_IMAGE_2D_ARRAY", - }, - { - 0x906A, - "GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES", - }, - { - 0x906E, - "GL_IMAGE_BINDING_FORMAT", - }, - { - 0x906F, - "GL_RGB10_A2UI", - }, - { - 0x9070, - "GL_PATH_FORMAT_SVG_NV", - }, - { - 0x9071, - "GL_PATH_FORMAT_PS_NV", - }, - { - 0x9072, - "GL_STANDARD_FONT_NAME_NV", - }, - { - 0x9073, - "GL_SYSTEM_FONT_NAME_NV", - }, - { - 0x9074, - "GL_FILE_NAME_NV", - }, - { - 0x9075, - "GL_PATH_STROKE_WIDTH_NV", - }, - { - 0x9076, - "GL_PATH_END_CAPS_NV", - }, - { - 0x9077, - "GL_PATH_INITIAL_END_CAP_NV", - }, - { - 0x9078, - "GL_PATH_TERMINAL_END_CAP_NV", - }, - { - 0x9079, - "GL_PATH_JOIN_STYLE_NV", - }, - { - 0x907A, - "GL_PATH_MITER_LIMIT_NV", - }, - { - 0x907B, - "GL_PATH_DASH_CAPS_NV", - }, - { - 0x907C, - "GL_PATH_INITIAL_DASH_CAP_NV", - }, - { - 0x907D, - "GL_PATH_TERMINAL_DASH_CAP_NV", - }, - { - 0x907E, - "GL_PATH_DASH_OFFSET_NV", - }, - { - 0x907F, - "GL_PATH_CLIENT_LENGTH_NV", - }, - { - 0x9080, - "GL_PATH_FILL_MODE_NV", - }, - { - 0x9081, - "GL_PATH_FILL_MASK_NV", - }, - { - 0x9082, - "GL_PATH_FILL_COVER_MODE_NV", - }, - { - 0x9083, - "GL_PATH_STROKE_COVER_MODE_NV", - }, - { - 0x9084, - "GL_PATH_STROKE_MASK_NV", - }, - { - 0x9088, - "GL_COUNT_UP_NV", - }, - { - 0x9089, - "GL_COUNT_DOWN_NV", - }, - { - 0x908A, - "GL_PATH_OBJECT_BOUNDING_BOX_NV", - }, - { - 0x908B, - "GL_CONVEX_HULL_NV", - }, - { - 0x908D, - "GL_BOUNDING_BOX_NV", - }, - { - 0x908E, - "GL_TRANSLATE_X_NV", - }, - { - 0x908F, - "GL_TRANSLATE_Y_NV", - }, - { - 0x9090, - "GL_TRANSLATE_2D_NV", - }, - { - 0x9091, - "GL_TRANSLATE_3D_NV", - }, - { - 0x9092, - "GL_AFFINE_2D_NV", - }, - { - 0x9094, - "GL_AFFINE_3D_NV", - }, - { - 0x9096, - "GL_TRANSPOSE_AFFINE_2D_NV", - }, - { - 0x9098, - "GL_TRANSPOSE_AFFINE_3D_NV", - }, - { - 0x909A, - "GL_UTF8_NV", - }, - { - 0x909B, - "GL_UTF16_NV", - }, - { - 0x909C, - "GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV", - }, - { - 0x909D, - "GL_PATH_COMMAND_COUNT_NV", - }, - { - 0x909E, - "GL_PATH_COORD_COUNT_NV", - }, - { - 0x909F, - "GL_PATH_DASH_ARRAY_COUNT_NV", - }, - { - 0x90A0, - "GL_PATH_COMPUTED_LENGTH_NV", - }, - { - 0x90A1, - "GL_PATH_FILL_BOUNDING_BOX_NV", - }, - { - 0x90A2, - "GL_PATH_STROKE_BOUNDING_BOX_NV", - }, - { - 0x90A3, - "GL_SQUARE_NV", - }, - { - 0x90A4, - "GL_ROUND_NV", - }, - { - 0x90A5, - "GL_TRIANGULAR_NV", - }, - { - 0x90A6, - "GL_BEVEL_NV", - }, - { - 0x90A7, - "GL_MITER_REVERT_NV", - }, - { - 0x90A8, - "GL_MITER_TRUNCATE_NV", - }, - { - 0x90A9, - "GL_SKIP_MISSING_GLYPH_NV", - }, - { - 0x90AA, - "GL_USE_MISSING_GLYPH_NV", - }, - { - 0x90AB, - "GL_PATH_ERROR_POSITION_NV", - }, - { - 0x90AD, - "GL_ACCUM_ADJACENT_PAIRS_NV", - }, - { - 0x90AE, - "GL_ADJACENT_PAIRS_NV", - }, - { - 0x90AF, - "GL_FIRST_TO_REST_NV", - }, - { - 0x90B0, - "GL_PATH_GEN_MODE_NV", - }, - { - 0x90B1, - "GL_PATH_GEN_COEFF_NV", - }, - { - 0x90B3, - "GL_PATH_GEN_COMPONENTS_NV", - }, - { - 0x90B4, - "GL_PATH_DASH_OFFSET_RESET_NV", - }, - { - 0x90B5, - "GL_MOVE_TO_RESETS_NV", - }, - { - 0x90B6, - "GL_MOVE_TO_CONTINUES_NV", - }, - { - 0x90B7, - "GL_PATH_STENCIL_FUNC_NV", - }, - { - 0x90B8, - "GL_PATH_STENCIL_REF_NV", - }, - { - 0x90B9, - "GL_PATH_STENCIL_VALUE_MASK_NV", - }, - { - 0x90BD, - "GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV", - }, - { - 0x90BE, - "GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV", - }, - { - 0x90BF, - "GL_PATH_COVER_DEPTH_FUNC_NV", - }, - { - 0x90C7, - "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE", - }, - { - 0x90C8, - "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE", - }, - { - 0x90C9, - "GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS", - }, - { - 0x90CA, - "GL_MAX_VERTEX_IMAGE_UNIFORMS", - }, - { - 0x90CB, - "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES", - }, - { - 0x90CC, - "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES", - }, - { - 0x90CD, - "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES", - }, - { - 0x90CE, - "GL_MAX_FRAGMENT_IMAGE_UNIFORMS", - }, - { - 0x90CF, - "GL_MAX_COMBINED_IMAGE_UNIFORMS", - }, - { - 0x90D2, - "GL_SHADER_STORAGE_BUFFER", - }, - { - 0x90D3, - "GL_SHADER_STORAGE_BUFFER_BINDING", - }, - { - 0x90D4, - "GL_SHADER_STORAGE_BUFFER_START", - }, - { - 0x90D5, - "GL_SHADER_STORAGE_BUFFER_SIZE", - }, - { - 0x90D6, - "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS", - }, - { - 0x90D7, - "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES", - }, - { - 0x90D8, - "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES", - }, - { - 0x90D9, - "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES", - }, - { - 0x90DA, - "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS", - }, - { - 0x90DB, - "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS", - }, - { - 0x90DC, - "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS", - }, - { - 0x90DD, - "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS", - }, - { - 0x90DE, - "GL_MAX_SHADER_STORAGE_BLOCK_SIZE", - }, - { - 0x90DF, - "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT", - }, - { - 0x90EA, - "GL_DEPTH_STENCIL_TEXTURE_MODE", - }, - { - 0x90EB, - "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS", - }, - { - 0x90EE, - "GL_DISPATCH_INDIRECT_BUFFER", - }, - { - 0x90EF, - "GL_DISPATCH_INDIRECT_BUFFER_BINDING", - }, - { - 0x90F0, - "GL_COLOR_ATTACHMENT_EXT", - }, - { - 0x90F1, - "GL_MULTIVIEW_EXT", - }, - { - 0x90F2, - "GL_MAX_MULTIVIEW_BUFFERS_EXT", - }, - { - 0x90F3, - "GL_CONTEXT_ROBUST_ACCESS_KHR", - }, - { - 0x9100, - "GL_TEXTURE_2D_MULTISAMPLE", - }, - { - 0x9102, - "GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES", - }, - { - 0x9104, - "GL_TEXTURE_BINDING_2D_MULTISAMPLE", - }, - { - 0x9105, - "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES", - }, - { - 0x9106, - "GL_TEXTURE_SAMPLES", - }, - { - 0x9107, - "GL_TEXTURE_FIXED_SAMPLE_LOCATIONS", - }, - { - 0x9108, - "GL_SAMPLER_2D_MULTISAMPLE", - }, - { - 0x9109, - "GL_INT_SAMPLER_2D_MULTISAMPLE", - }, - { - 0x910A, - "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE", - }, - { - 0x910B, - "GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES", - }, - { - 0x910C, - "GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES", - }, - { - 0x910D, - "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES", - }, - { - 0x910E, - "GL_MAX_COLOR_TEXTURE_SAMPLES", - }, - { - 0x910F, - "GL_MAX_DEPTH_TEXTURE_SAMPLES", - }, - { - 0x9110, - "GL_MAX_INTEGER_SAMPLES", - }, - { - 0x9111, - "GL_MAX_SERVER_WAIT_TIMEOUT_APPLE", - }, - { - 0x9112, - "GL_OBJECT_TYPE_APPLE", - }, - { - 0x9113, - "GL_SYNC_CONDITION_APPLE", - }, - { - 0x9114, - "GL_SYNC_STATUS_APPLE", - }, - { - 0x9115, - "GL_SYNC_FLAGS_APPLE", - }, - { - 0x9116, - "GL_SYNC_FENCE_APPLE", - }, - { - 0x9117, - "GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE", - }, - { - 0x9118, - "GL_UNSIGNALED_APPLE", - }, - { - 0x9119, - "GL_SIGNALED_APPLE", - }, - { - 0x911A, - "GL_ALREADY_SIGNALED_APPLE", - }, - { - 0x911B, - "GL_TIMEOUT_EXPIRED_APPLE", - }, - { - 0x911C, - "GL_CONDITION_SATISFIED_APPLE", - }, - { - 0x911D, - "GL_WAIT_FAILED_APPLE", - }, - { - 0x911F, - "GL_BUFFER_ACCESS_FLAGS", - }, - { - 0x9120, - "GL_BUFFER_MAP_LENGTH", - }, - { - 0x9121, - "GL_BUFFER_MAP_OFFSET", - }, - { - 0x9122, - "GL_MAX_VERTEX_OUTPUT_COMPONENTS", - }, - { - 0x9123, - "GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES", - }, - { - 0x9124, - "GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES", - }, - { - 0x9125, - "GL_MAX_FRAGMENT_INPUT_COMPONENTS", - }, - { - 0x912F, - "GL_TEXTURE_IMMUTABLE_FORMAT_EXT", - }, - { - 0x9130, - "GL_SGX_PROGRAM_BINARY_IMG", - }, - { - 0x9133, - "GL_RENDERBUFFER_SAMPLES_IMG", - }, - { - 0x9134, - "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG", - }, - { - 0x9135, - "GL_MAX_SAMPLES_IMG", - }, - { - 0x9136, - "GL_TEXTURE_SAMPLES_IMG", - }, - { - 0x9137, - "GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG", - }, - { - 0x9138, - "GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG", - }, - { - 0x9139, - "GL_CUBIC_IMG", - }, - { - 0x913A, - "GL_CUBIC_MIPMAP_NEAREST_IMG", - }, - { - 0x913B, - "GL_CUBIC_MIPMAP_LINEAR_IMG", - }, - { - 0x913C, - "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG", - }, - { - 0x913D, - "GL_NUM_DOWNSAMPLE_SCALES_IMG", - }, - { - 0x913E, - "GL_DOWNSAMPLE_SCALES_IMG", - }, - { - 0x913F, - "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG", - }, - { - 0x9143, - "GL_MAX_DEBUG_MESSAGE_LENGTH_KHR", - }, - { - 0x9144, - "GL_MAX_DEBUG_LOGGED_MESSAGES_KHR", - }, - { - 0x9145, - "GL_DEBUG_LOGGED_MESSAGES_KHR", - }, - { - 0x9146, - "GL_DEBUG_SEVERITY_HIGH_KHR", - }, - { - 0x9147, - "GL_DEBUG_SEVERITY_MEDIUM_KHR", - }, - { - 0x9148, - "GL_DEBUG_SEVERITY_LOW_KHR", - }, - { - 0x9151, - "GL_BUFFER_OBJECT_EXT", - }, - { - 0x9153, - "GL_QUERY_OBJECT_EXT", - }, - { - 0x9154, - "GL_VERTEX_ARRAY_OBJECT_EXT", - }, - { - 0x9195, - "GL_VIRTUAL_PAGE_SIZE_X_EXT", - }, - { - 0x9196, - "GL_VIRTUAL_PAGE_SIZE_Y_EXT", - }, - { - 0x9197, - "GL_VIRTUAL_PAGE_SIZE_Z_EXT", - }, - { - 0x9198, - "GL_MAX_SPARSE_TEXTURE_SIZE_EXT", - }, - { - 0x9199, - "GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT", - }, - { - 0x919A, - "GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT", - }, - { - 0x919D, - "GL_TEXTURE_BUFFER_OFFSET_OES", - }, - { - 0x919E, - "GL_TEXTURE_BUFFER_SIZE_OES", - }, - { - 0x919F, - "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES", - }, - { - 0x91A6, - "GL_TEXTURE_SPARSE_EXT", - }, - { - 0x91A7, - "GL_VIRTUAL_PAGE_SIZE_INDEX_EXT", - }, - { - 0x91A8, - "GL_NUM_VIRTUAL_PAGE_SIZES_EXT", - }, - { - 0x91A9, - "GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT", - }, - { - 0x91AA, - "GL_NUM_SPARSE_LEVELS_EXT", - }, - { - 0x91B0, - "GL_MAX_SHADER_COMPILER_THREADS_KHR", - }, - { - 0x91B1, - "GL_COMPLETION_STATUS_KHR", - }, - { - 0x91B2, - "GL_RENDERBUFFER_STORAGE_SAMPLES_AMD", - }, - { - 0x91B3, - "GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD", - }, - { - 0x91B4, - "GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD", - }, - { - 0x91B5, - "GL_MAX_DEPTH_STENCIL_FRAMEBUFFER_SAMPLES_AMD", - }, - { - 0x91B6, - "GL_NUM_SUPPORTED_MULTISAMPLE_MODES_AMD", - }, - { - 0x91B7, - "GL_SUPPORTED_MULTISAMPLE_MODES_AMD", - }, - { - 0x91B9, - "GL_COMPUTE_SHADER", - }, - { - 0x91BB, - "GL_MAX_COMPUTE_UNIFORM_BLOCKS", - }, - { - 0x91BC, - "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS", - }, - { - 0x91BD, - "GL_MAX_COMPUTE_IMAGE_UNIFORMS", - }, - { - 0x91BE, - "GL_MAX_COMPUTE_WORK_GROUP_COUNT", - }, - { - 0x91BF, - "GL_MAX_COMPUTE_WORK_GROUP_SIZE", - }, - { - 0x9243, - "GL_UNPACK_COLORSPACE_CONVERSION_CHROMIUM", - }, - { - 0x9244, - "GL_BIND_GENERATES_RESOURCE_CHROMIUM", - }, - { - 0x9250, - "GL_SHADER_BINARY_DMP", - }, - { - 0x9251, - "GL_SMAPHS30_PROGRAM_BINARY_DMP", - }, - { - 0x9252, - "GL_SMAPHS_PROGRAM_BINARY_DMP", - }, - { - 0x9253, - "GL_DMP_PROGRAM_BINARY_DMP", - }, - { - 0x9260, - "GL_GCCSO_SHADER_BINARY_FJ", - }, - { - 0x9270, - "GL_COMPRESSED_R11_EAC", - }, - { - 0x9271, - "GL_COMPRESSED_SIGNED_R11_EAC", - }, - { - 0x9272, - "GL_COMPRESSED_RG11_EAC", - }, - { - 0x9273, - "GL_COMPRESSED_SIGNED_RG11_EAC", - }, - { - 0x9274, - "GL_COMPRESSED_RGB8_ETC2", - }, - { - 0x9275, - "GL_COMPRESSED_SRGB8_ETC2", - }, - { - 0x9276, - "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2", - }, - { - 0x9277, - "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2", - }, - { - 0x9278, - "GL_COMPRESSED_RGBA8_ETC2_EAC", - }, - { - 0x9279, - "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC", - }, - { - 0x9280, - "GL_BLEND_PREMULTIPLIED_SRC_NV", - }, - { - 0x9281, - "GL_BLEND_OVERLAP_NV", - }, - { - 0x9282, - "GL_UNCORRELATED_NV", - }, - { - 0x9283, - "GL_DISJOINT_NV", - }, - { - 0x9284, - "GL_CONJOINT_NV", - }, - { - 0x9285, - "GL_BLEND_ADVANCED_COHERENT_KHR", - }, - { - 0x9286, - "GL_SRC_NV", - }, - { - 0x9287, - "GL_DST_NV", - }, - { - 0x9288, - "GL_SRC_OVER_NV", - }, - { - 0x9289, - "GL_DST_OVER_NV", - }, - { - 0x928A, - "GL_SRC_IN_NV", - }, - { - 0x928B, - "GL_DST_IN_NV", - }, - { - 0x928C, - "GL_SRC_OUT_NV", - }, - { - 0x928D, - "GL_DST_OUT_NV", - }, - { - 0x928E, - "GL_SRC_ATOP_NV", - }, - { - 0x928F, - "GL_DST_ATOP_NV", - }, - { - 0x9291, - "GL_PLUS_NV", - }, - { - 0x9292, - "GL_PLUS_DARKER_NV", - }, - { - 0x9294, - "GL_MULTIPLY_KHR", - }, - { - 0x9295, - "GL_SCREEN_KHR", - }, - { - 0x9296, - "GL_OVERLAY_KHR", - }, - { - 0x9297, - "GL_DARKEN_KHR", - }, - { - 0x9298, - "GL_LIGHTEN_KHR", - }, - { - 0x9299, - "GL_COLORDODGE_KHR", - }, - { - 0x929A, - "GL_COLORBURN_KHR", - }, - { - 0x929B, - "GL_HARDLIGHT_KHR", - }, - { - 0x929C, - "GL_SOFTLIGHT_KHR", - }, - { - 0x929E, - "GL_DIFFERENCE_KHR", - }, - { - 0x929F, - "GL_MINUS_NV", - }, - { - 0x92A0, - "GL_EXCLUSION_KHR", - }, - { - 0x92A1, - "GL_CONTRAST_NV", - }, - { - 0x92A3, - "GL_INVERT_RGB_NV", - }, - { - 0x92A4, - "GL_LINEARDODGE_NV", - }, - { - 0x92A5, - "GL_LINEARBURN_NV", - }, - { - 0x92A6, - "GL_VIVIDLIGHT_NV", - }, - { - 0x92A7, - "GL_LINEARLIGHT_NV", - }, - { - 0x92A8, - "GL_PINLIGHT_NV", - }, - { - 0x92A9, - "GL_HARDMIX_NV", - }, - { - 0x92AD, - "GL_HSL_HUE_KHR", - }, - { - 0x92AE, - "GL_HSL_SATURATION_KHR", - }, - { - 0x92AF, - "GL_HSL_COLOR_KHR", - }, - { - 0x92B0, - "GL_HSL_LUMINOSITY_KHR", - }, - { - 0x92B1, - "GL_PLUS_CLAMPED_NV", - }, - { - 0x92B2, - "GL_PLUS_CLAMPED_ALPHA_NV", - }, - { - 0x92B3, - "GL_MINUS_CLAMPED_NV", - }, - { - 0x92B4, - "GL_INVERT_OVG_NV", - }, - { - 0x92BE, - "GL_PRIMITIVE_BOUNDING_BOX_OES", - }, - { - 0x92C0, - "GL_ATOMIC_COUNTER_BUFFER", - }, - { - 0x92C1, - "GL_ATOMIC_COUNTER_BUFFER_BINDING", - }, - { - 0x92C2, - "GL_ATOMIC_COUNTER_BUFFER_START", - }, - { - 0x92C3, - "GL_ATOMIC_COUNTER_BUFFER_SIZE", - }, - { - 0x92CC, - "GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS", - }, - { - 0x92CD, - "GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES", - }, - { - 0x92CE, - "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES", - }, - { - 0x92CF, - "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES", - }, - { - 0x92D0, - "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS", - }, - { - 0x92D1, - "GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS", - }, - { - 0x92D2, - "GL_MAX_VERTEX_ATOMIC_COUNTERS", - }, - { - 0x92D3, - "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES", - }, - { - 0x92D4, - "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES", - }, - { - 0x92D5, - "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES", - }, - { - 0x92D6, - "GL_MAX_FRAGMENT_ATOMIC_COUNTERS", - }, - { - 0x92D7, - "GL_MAX_COMBINED_ATOMIC_COUNTERS", - }, - { - 0x92D8, - "GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE", - }, - { - 0x92D9, - "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS", - }, - { - 0x92DB, - "GL_UNSIGNED_INT_ATOMIC_COUNTER", - }, - { - 0x92DC, - "GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS", - }, - { - 0x92DD, - "GL_FRAGMENT_COVERAGE_TO_COLOR_NV", - }, - { - 0x92DE, - "GL_FRAGMENT_COVERAGE_COLOR_NV", - }, - { - 0x92DF, - "GL_MESH_OUTPUT_PER_VERTEX_GRANULARITY_NV", - }, - { - 0x92E0, - "GL_DEBUG_OUTPUT_KHR", - }, - { - 0x92E1, - "GL_UNIFORM", - }, - { - 0x92E2, - "GL_UNIFORM_BLOCK", - }, - { - 0x92E3, - "GL_PROGRAM_INPUT", - }, - { - 0x92E4, - "GL_PROGRAM_OUTPUT", - }, - { - 0x92E5, - "GL_BUFFER_VARIABLE", - }, - { - 0x92E6, - "GL_SHADER_STORAGE_BLOCK", - }, - { - 0x92E7, - "GL_IS_PER_PATCH_OES", - }, - { - 0x92F4, - "GL_TRANSFORM_FEEDBACK_VARYING", - }, - { - 0x92F5, - "GL_ACTIVE_RESOURCES", - }, - { - 0x92F6, - "GL_MAX_NAME_LENGTH", - }, - { - 0x92F7, - "GL_MAX_NUM_ACTIVE_VARIABLES", - }, - { - 0x92F9, - "GL_NAME_LENGTH", - }, - { - 0x92FA, - "GL_TYPE", - }, - { - 0x92FB, - "GL_ARRAY_SIZE", - }, - { - 0x92FC, - "GL_OFFSET", - }, - { - 0x92FD, - "GL_BLOCK_INDEX", - }, - { - 0x92FE, - "GL_ARRAY_STRIDE", - }, - { - 0x92FF, - "GL_MATRIX_STRIDE", - }, - { - 0x9300, - "GL_IS_ROW_MAJOR", - }, - { - 0x9301, - "GL_ATOMIC_COUNTER_BUFFER_INDEX", - }, - { - 0x9302, - "GL_BUFFER_BINDING", - }, - { - 0x9303, - "GL_BUFFER_DATA_SIZE", - }, - { - 0x9304, - "GL_NUM_ACTIVE_VARIABLES", - }, - { - 0x9305, - "GL_ACTIVE_VARIABLES", - }, - { - 0x9306, - "GL_REFERENCED_BY_VERTEX_SHADER", - }, - { - 0x9307, - "GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES", - }, - { - 0x9308, - "GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES", - }, - { - 0x9309, - "GL_REFERENCED_BY_GEOMETRY_SHADER_OES", - }, - { - 0x930A, - "GL_REFERENCED_BY_FRAGMENT_SHADER", - }, - { - 0x930B, - "GL_REFERENCED_BY_COMPUTE_SHADER", - }, - { - 0x930C, - "GL_TOP_LEVEL_ARRAY_SIZE", - }, - { - 0x930D, - "GL_TOP_LEVEL_ARRAY_STRIDE", - }, - { - 0x930E, - "GL_LOCATION", - }, - { - 0x930F, - "GL_LOCATION_INDEX_EXT", - }, - { - 0x9310, - "GL_FRAMEBUFFER_DEFAULT_WIDTH", - }, - { - 0x9311, - "GL_FRAMEBUFFER_DEFAULT_HEIGHT", - }, - { - 0x9312, - "GL_FRAMEBUFFER_DEFAULT_LAYERS_OES", - }, - { - 0x9313, - "GL_FRAMEBUFFER_DEFAULT_SAMPLES", - }, - { - 0x9314, - "GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS", - }, - { - 0x9315, - "GL_MAX_FRAMEBUFFER_WIDTH", - }, - { - 0x9316, - "GL_MAX_FRAMEBUFFER_HEIGHT", - }, - { - 0x9317, - "GL_MAX_FRAMEBUFFER_LAYERS_OES", - }, - { - 0x9318, - "GL_MAX_FRAMEBUFFER_SAMPLES", - }, - { - 0x9327, - "GL_RASTER_MULTISAMPLE_EXT", - }, - { - 0x9328, - "GL_RASTER_SAMPLES_EXT", - }, - { - 0x9329, - "GL_MAX_RASTER_SAMPLES_EXT", - }, - { - 0x932A, - "GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT", - }, - { - 0x932B, - "GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT", - }, - { - 0x932C, - "GL_EFFECTIVE_RASTER_SAMPLES_EXT", - }, - { - 0x932D, - "GL_DEPTH_SAMPLES_NV", - }, - { - 0x932E, - "GL_STENCIL_SAMPLES_NV", - }, - { - 0x932F, - "GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV", - }, - { - 0x9330, - "GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV", - }, - { - 0x9331, - "GL_COVERAGE_MODULATION_TABLE_NV", - }, - { - 0x9332, - "GL_COVERAGE_MODULATION_NV", - }, - { - 0x9333, - "GL_COVERAGE_MODULATION_TABLE_SIZE_NV", - }, - { - 0x933C, - "GL_FILL_RECTANGLE_NV", - }, - { - 0x933D, - "GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV", - }, - { - 0x933E, - "GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV", - }, - { - 0x933F, - "GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV", - }, - { - 0x9340, - "GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV", - }, - { - 0x9341, - "GL_PROGRAMMABLE_SAMPLE_LOCATION_NV", - }, - { - 0x9342, - "GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV", - }, - { - 0x9343, - "GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV", - }, - { - 0x9346, - "GL_CONSERVATIVE_RASTERIZATION_NV", - }, - { - 0x9347, - "GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV", - }, - { - 0x9348, - "GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV", - }, - { - 0x9349, - "GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV", - }, - { - 0x9350, - "GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV", - }, - { - 0x9351, - "GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV", - }, - { - 0x9352, - "GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV", - }, - { - 0x9353, - "GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV", - }, - { - 0x9354, - "GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV", - }, - { - 0x9355, - "GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV", - }, - { - 0x9356, - "GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV", - }, - { - 0x9357, - "GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV", - }, - { - 0x9358, - "GL_VIEWPORT_SWIZZLE_X_NV", - }, - { - 0x9359, - "GL_VIEWPORT_SWIZZLE_Y_NV", - }, - { - 0x935A, - "GL_VIEWPORT_SWIZZLE_Z_NV", - }, - { - 0x935B, - "GL_VIEWPORT_SWIZZLE_W_NV", - }, - { - 0x935C, - "GL_CLIP_ORIGIN_EXT", - }, - { - 0x935D, - "GL_CLIP_DEPTH_MODE_EXT", - }, - { - 0x935E, - "GL_NEGATIVE_ONE_TO_ONE_EXT", - }, - { - 0x935F, - "GL_ZERO_TO_ONE_EXT", - }, - { - 0x9366, - "GL_TEXTURE_REDUCTION_MODE_EXT", - }, - { - 0x9367, - "GL_WEIGHTED_AVERAGE_EXT", - }, - { - 0x9368, - "GL_FONT_GLYPHS_AVAILABLE_NV", - }, - { - 0x9369, - "GL_FONT_TARGET_UNAVAILABLE_NV", - }, - { - 0x936A, - "GL_FONT_UNAVAILABLE_NV", - }, - { - 0x936B, - "GL_FONT_UNINTELLIGIBLE_NV", - }, - { - 0x936C, - "GL_STANDARD_FONT_FORMAT_NV", - }, - { - 0x936D, - "GL_FRAGMENT_INPUT_NV", - }, - { - 0x9371, - "GL_MULTISAMPLES_NV", - }, - { - 0x9372, - "GL_SUPERSAMPLE_SCALE_X_NV", - }, - { - 0x9373, - "GL_SUPERSAMPLE_SCALE_Y_NV", - }, - { - 0x9374, - "GL_CONFORMANT_NV", - }, - { - 0x937C, - "GL_VIEWPORT_POSITION_W_SCALE_NV", - }, - { - 0x937D, - "GL_VIEWPORT_POSITION_W_SCALE_X_COEFF_NV", - }, - { - 0x937E, - "GL_VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV", - }, - { - 0x937F, - "GL_REPRESENTATIVE_FRAGMENT_TEST_NV", - }, - { - 0x9380, - "GL_NUM_SAMPLE_COUNTS", - }, - { - 0x93A0, - "GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE", - }, - { - 0x93A1, - "GL_BGRA8_EXT", - }, - { - 0x93A2, - "GL_TEXTURE_USAGE_ANGLE", - }, - { - 0x93A3, - "GL_FRAMEBUFFER_ATTACHMENT_ANGLE", - }, - { - 0x93A4, - "GL_PACK_REVERSE_ROW_ORDER_ANGLE", - }, - { - 0x93A6, - "GL_PROGRAM_BINARY_ANGLE", - }, - { - 0x93B0, - "GL_COMPRESSED_RGBA_ASTC_4x4_KHR", - }, - { - 0x93B1, - "GL_COMPRESSED_RGBA_ASTC_5x4_KHR", - }, - { - 0x93B2, - "GL_COMPRESSED_RGBA_ASTC_5x5_KHR", - }, - { - 0x93B3, - "GL_COMPRESSED_RGBA_ASTC_6x5_KHR", - }, - { - 0x93B4, - "GL_COMPRESSED_RGBA_ASTC_6x6_KHR", - }, - { - 0x93B5, - "GL_COMPRESSED_RGBA_ASTC_8x5_KHR", - }, - { - 0x93B6, - "GL_COMPRESSED_RGBA_ASTC_8x6_KHR", - }, - { - 0x93B7, - "GL_COMPRESSED_RGBA_ASTC_8x8_KHR", - }, - { - 0x93B8, - "GL_COMPRESSED_RGBA_ASTC_10x5_KHR", - }, - { - 0x93B9, - "GL_COMPRESSED_RGBA_ASTC_10x6_KHR", - }, - { - 0x93BA, - "GL_COMPRESSED_RGBA_ASTC_10x8_KHR", - }, - { - 0x93BB, - "GL_COMPRESSED_RGBA_ASTC_10x10_KHR", - }, - { - 0x93BC, - "GL_COMPRESSED_RGBA_ASTC_12x10_KHR", - }, - { - 0x93BD, - "GL_COMPRESSED_RGBA_ASTC_12x12_KHR", - }, - { - 0x93C0, - "GL_COMPRESSED_RGBA_ASTC_3x3x3_OES", - }, - { - 0x93C1, - "GL_COMPRESSED_RGBA_ASTC_4x3x3_OES", - }, - { - 0x93C2, - "GL_COMPRESSED_RGBA_ASTC_4x4x3_OES", - }, - { - 0x93C3, - "GL_COMPRESSED_RGBA_ASTC_4x4x4_OES", - }, - { - 0x93C4, - "GL_COMPRESSED_RGBA_ASTC_5x4x4_OES", - }, - { - 0x93C5, - "GL_COMPRESSED_RGBA_ASTC_5x5x4_OES", - }, - { - 0x93C6, - "GL_COMPRESSED_RGBA_ASTC_5x5x5_OES", - }, - { - 0x93C7, - "GL_COMPRESSED_RGBA_ASTC_6x5x5_OES", - }, - { - 0x93C8, - "GL_COMPRESSED_RGBA_ASTC_6x6x5_OES", - }, - { - 0x93C9, - "GL_COMPRESSED_RGBA_ASTC_6x6x6_OES", - }, - { - 0x93D0, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR", - }, - { - 0x93D1, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR", - }, - { - 0x93D2, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR", - }, - { - 0x93D3, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR", - }, - { - 0x93D4, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR", - }, - { - 0x93D5, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR", - }, - { - 0x93D6, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR", - }, - { - 0x93D7, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR", - }, - { - 0x93D8, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR", - }, - { - 0x93D9, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR", - }, - { - 0x93DA, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR", - }, - { - 0x93DB, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR", - }, - { - 0x93DC, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR", - }, - { - 0x93DD, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR", - }, - { - 0x93E0, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES", - }, - { - 0x93E1, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES", - }, - { - 0x93E2, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES", - }, - { - 0x93E3, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES", - }, - { - 0x93E4, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES", - }, - { - 0x93E5, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES", - }, - { - 0x93E6, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES", - }, - { - 0x93E7, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES", - }, - { - 0x93E8, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES", - }, - { - 0x93E9, - "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES", - }, - { - 0x93F0, - "GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG", - }, - { - 0x93F1, - "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG", - }, - { - 0x94F0, - "GL_PERFQUERY_COUNTER_EVENT_INTEL", - }, - { - 0x94F1, - "GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL", - }, - { - 0x94F2, - "GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL", - }, - { - 0x94F3, - "GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL", - }, - { - 0x94F4, - "GL_PERFQUERY_COUNTER_RAW_INTEL", - }, - { - 0x94F5, - "GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL", - }, - { - 0x94F8, - "GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL", - }, - { - 0x94F9, - "GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL", - }, - { - 0x94FA, - "GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL", - }, - { - 0x94FB, - "GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL", - }, - { - 0x94FC, - "GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL", - }, - { - 0x94FD, - "GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL", - }, - { - 0x94FE, - "GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL", - }, - { - 0x94FF, - "GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL", - }, - { - 0x9500, - "GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL", - }, - { - 0x9530, - "GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT", - }, - { - 0x9531, - "GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT", - }, - { - 0x9532, - "GL_SUBGROUP_SIZE_KHR", - }, - { - 0x9533, - "GL_SUBGROUP_SUPPORTED_STAGES_KHR", - }, - { - 0x9534, - "GL_SUBGROUP_SUPPORTED_FEATURES_KHR", - }, - { - 0x9535, - "GL_SUBGROUP_QUAD_ALL_STAGES_KHR", - }, - { - 0x9536, - "GL_MAX_MESH_TOTAL_MEMORY_SIZE_NV", - }, - { - 0x9537, - "GL_MAX_TASK_TOTAL_MEMORY_SIZE_NV", - }, - { - 0x9538, - "GL_MAX_MESH_OUTPUT_VERTICES_NV", - }, - { - 0x9539, - "GL_MAX_MESH_OUTPUT_PRIMITIVES_NV", - }, - { - 0x953A, - "GL_MAX_TASK_OUTPUT_COUNT_NV", - }, - { - 0x953B, - "GL_MAX_MESH_WORK_GROUP_SIZE_NV", - }, - { - 0x953C, - "GL_MAX_TASK_WORK_GROUP_SIZE_NV", - }, - { - 0x953D, - "GL_MAX_DRAW_MESH_TASKS_COUNT_NV", - }, - { - 0x953E, - "GL_MESH_WORK_GROUP_SIZE_NV", - }, - { - 0x953F, - "GL_TASK_WORK_GROUP_SIZE_NV", - }, - { - 0x9543, - "GL_MESH_OUTPUT_PER_PRIMITIVE_GRANULARITY_NV", - }, - { - 0x954D, - "GL_CONSERVATIVE_RASTER_MODE_NV", - }, - { - 0x954E, - "GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV", - }, - { - 0x954F, - "GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV", - }, - { - 0x9550, - "GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_NV", - }, - { - 0x9555, - "GL_SCISSOR_TEST_EXCLUSIVE_NV", - }, - { - 0x9556, - "GL_SCISSOR_BOX_EXCLUSIVE_NV", - }, - { - 0x9557, - "GL_MAX_MESH_VIEWS_NV", - }, - { - 0x9559, - "GL_MESH_SHADER_NV", - }, - { - 0x955A, - "GL_TASK_SHADER_NV", - }, - { - 0x955B, - "GL_SHADING_RATE_IMAGE_BINDING_NV", - }, - { - 0x955C, - "GL_SHADING_RATE_IMAGE_TEXEL_WIDTH_NV", - }, - { - 0x955D, - "GL_SHADING_RATE_IMAGE_TEXEL_HEIGHT_NV", - }, - { - 0x955E, - "GL_SHADING_RATE_IMAGE_PALETTE_SIZE_NV", - }, - { - 0x955F, - "GL_MAX_COARSE_FRAGMENT_SAMPLES_NV", - }, - { - 0x9563, - "GL_SHADING_RATE_IMAGE_NV", - }, - { - 0x9564, - "GL_SHADING_RATE_NO_INVOCATIONS_NV", - }, - { - 0x9565, - "GL_SHADING_RATE_1_INVOCATION_PER_PIXEL_NV", - }, - { - 0x9566, - "GL_SHADING_RATE_1_INVOCATION_PER_1X2_PIXELS_NV", - }, - { - 0x9567, - "GL_SHADING_RATE_1_INVOCATION_PER_2X1_PIXELS_NV", - }, - { - 0x9568, - "GL_SHADING_RATE_1_INVOCATION_PER_2X2_PIXELS_NV", - }, - { - 0x9569, - "GL_SHADING_RATE_1_INVOCATION_PER_2X4_PIXELS_NV", - }, - { - 0x956A, - "GL_SHADING_RATE_1_INVOCATION_PER_4X2_PIXELS_NV", - }, - { - 0x956B, - "GL_SHADING_RATE_1_INVOCATION_PER_4X4_PIXELS_NV", - }, - { - 0x956C, - "GL_SHADING_RATE_2_INVOCATIONS_PER_PIXEL_NV", - }, - { - 0x956D, - "GL_SHADING_RATE_4_INVOCATIONS_PER_PIXEL_NV", - }, - { - 0x956E, - "GL_SHADING_RATE_8_INVOCATIONS_PER_PIXEL_NV", - }, - { - 0x956F, - "GL_SHADING_RATE_16_INVOCATIONS_PER_PIXEL_NV", - }, - { - 0x9579, - "GL_MESH_VERTICES_OUT_NV", - }, - { - 0x957A, - "GL_MESH_PRIMITIVES_OUT_NV", - }, - { - 0x957B, - "GL_MESH_OUTPUT_TYPE_NV", - }, - { - 0x957C, - "GL_MESH_SUBROUTINE_NV", - }, - { - 0x957D, - "GL_TASK_SUBROUTINE_NV", - }, - { - 0x957E, - "GL_MESH_SUBROUTINE_UNIFORM_NV", - }, - { - 0x957F, - "GL_TASK_SUBROUTINE_UNIFORM_NV", - }, - { - 0x9580, - "GL_TEXTURE_TILING_EXT", - }, - { - 0x9581, - "GL_DEDICATED_MEMORY_OBJECT_EXT", - }, - { - 0x9582, - "GL_NUM_TILING_TYPES_EXT", - }, - { - 0x9583, - "GL_TILING_TYPES_EXT", - }, - { - 0x9584, - "GL_OPTIMAL_TILING_EXT", - }, - { - 0x9585, - "GL_LINEAR_TILING_EXT", - }, - { - 0x9586, - "GL_HANDLE_TYPE_OPAQUE_FD_EXT", - }, - { - 0x9587, - "GL_HANDLE_TYPE_OPAQUE_WIN32_EXT", - }, - { - 0x9588, - "GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT", - }, - { - 0x9589, - "GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT", - }, - { - 0x958A, - "GL_HANDLE_TYPE_D3D12_RESOURCE_EXT", - }, - { - 0x958B, - "GL_HANDLE_TYPE_D3D11_IMAGE_EXT", - }, - { - 0x958C, - "GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT", - }, - { - 0x958D, - "GL_LAYOUT_GENERAL_EXT", - }, - { - 0x958E, - "GL_LAYOUT_COLOR_ATTACHMENT_EXT", - }, - { - 0x958F, - "GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT", - }, - { - 0x9590, - "GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT", - }, - { - 0x9591, - "GL_LAYOUT_SHADER_READ_ONLY_EXT", - }, - { - 0x9592, - "GL_LAYOUT_TRANSFER_SRC_EXT", - }, - { - 0x9593, - "GL_LAYOUT_TRANSFER_DST_EXT", - }, - { - 0x9594, - "GL_HANDLE_TYPE_D3D12_FENCE_EXT", - }, - { - 0x9595, - "GL_D3D12_FENCE_VALUE_EXT", - }, - { - 0x9596, - "GL_NUM_DEVICE_UUIDS_EXT", - }, - { - 0x9597, - "GL_DEVICE_UUID_EXT", - }, - { - 0x9598, - "GL_DRIVER_UUID_EXT", - }, - { - 0x9599, - "GL_DEVICE_LUID_EXT", - }, - { - 0x959A, - "GL_DEVICE_NODE_MASK_EXT", - }, - { - 0x959B, - "GL_PROTECTED_MEMORY_OBJECT_EXT", - }, - { - 0x959C, - "GL_UNIFORM_BLOCK_REFERENCED_BY_MESH_SHADER_NV", - }, - { - 0x959D, - "GL_UNIFORM_BLOCK_REFERENCED_BY_TASK_SHADER_NV", - }, - { - 0x959E, - "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_MESH_SHADER_NV", - }, - { - 0x959F, - "GL_ATOMIC_COUNTER_BUFFER_REFERENCED_BY_TASK_SHADER_NV", - }, - { - 0x95A0, - "GL_REFERENCED_BY_MESH_SHADER_NV", - }, - { - 0x95A1, - "GL_REFERENCED_BY_TASK_SHADER_NV", - }, - { - 0x95A2, - "GL_MAX_MESH_WORK_GROUP_INVOCATIONS_NV", - }, - { - 0x95A3, - "GL_MAX_TASK_WORK_GROUP_INVOCATIONS_NV", - }, - { - 0x95A4, - "GL_ATTACHED_MEMORY_OBJECT_NV", - }, - { - 0x95A5, - "GL_ATTACHED_MEMORY_OFFSET_NV", - }, - { - 0x95A6, - "GL_MEMORY_ATTACHABLE_ALIGNMENT_NV", - }, - { - 0x95A7, - "GL_MEMORY_ATTACHABLE_SIZE_NV", - }, - { - 0x95A8, - "GL_MEMORY_ATTACHABLE_NV", - }, - { - 0x95A9, - "GL_DETACHED_MEMORY_INCARNATION_NV", - }, - { - 0x95AA, - "GL_DETACHED_TEXTURES_NV", - }, - { - 0x95AB, - "GL_DETACHED_BUFFERS_NV", - }, - { - 0x95AC, - "GL_MAX_DETACHED_TEXTURES_NV", - }, - { - 0x95AD, - "GL_MAX_DETACHED_BUFFERS_NV", - }, - { - 0x95AE, - "GL_SHADING_RATE_SAMPLE_ORDER_DEFAULT_NV", - }, - { - 0x95AF, - "GL_SHADING_RATE_SAMPLE_ORDER_PIXEL_MAJOR_NV", - }, - { - 0x95B0, - "GL_SHADING_RATE_SAMPLE_ORDER_SAMPLE_MAJOR_NV", - }, - { - 0x9630, - "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR", - }, - { - 0x9631, - "GL_MAX_VIEWS_OVR", - }, - { - 0x9632, - "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR", - }, - { - 0x9633, - "GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR", - }, - { - 0x9650, - "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT", - }, - { - 0x9651, - "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT", - }, - { - 0x9652, - "GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_" - "EXT", - }, - { - 0x96A2, - "GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM", - }, - { - 0x96BA, - "GL_RGBX8_ANGLE", - }, - { - 0x96E0, - "GL_MAX_PIXEL_LOCAL_STORAGE_PLANES_ANGLE", - }, - { - 0x96E1, - "GL_MAX_COLOR_ATTACHMENTS_WITH_ACTIVE_PIXEL_LOCAL_STORAGE_ANGLE", - }, - { - 0x96E2, - "GL_MAX_COMBINED_DRAW_BUFFERS_AND_PIXEL_LOCAL_STORAGE_PLANES_ANGLE", - }, - { - 0x96E3, - "GL_PIXEL_LOCAL_STORAGE_ACTIVE_PLANES_ANGLE", - }, - { - 0x96E4, - "GL_LOAD_OP_ZERO_ANGLE", - }, - { - 0x96E5, - "GL_LOAD_OP_CLEAR_ANGLE", - }, - { - 0x96E6, - "GL_LOAD_OP_LOAD_ANGLE", - }, - { - 0x96E7, - "GL_STORE_OP_STORE_ANGLE", - }, - { - 0x96E8, - "GL_PIXEL_LOCAL_FORMAT_ANGLE", - }, - { - 0x96E9, - "GL_PIXEL_LOCAL_TEXTURE_NAME_ANGLE", - }, - { - 0x96EA, - "GL_PIXEL_LOCAL_TEXTURE_LEVEL_ANGLE", - }, - { - 0x96EB, - "GL_PIXEL_LOCAL_TEXTURE_LAYER_ANGLE", - }, - { - 0x96EC, - "GL_PIXEL_LOCAL_CLEAR_VALUE_FLOAT_ANGLE", - }, - { - 0x96ED, - "GL_PIXEL_LOCAL_CLEAR_VALUE_INT_ANGLE", - }, - { - 0x96EE, - "GL_PIXEL_LOCAL_CLEAR_VALUE_UNSIGNED_INT_ANGLE", - }, - { - 0xC0, - "GL_SHARED_EDGE_NV", - }, - { - 0xE8, - "GL_ROUNDED_RECT_NV", - }, - { - 0xE9, - "GL_RELATIVE_ROUNDED_RECT_NV", - }, - { - 0xEA, - "GL_ROUNDED_RECT2_NV", - }, - { - 0xEB, - "GL_RELATIVE_ROUNDED_RECT2_NV", - }, - { - 0xEC, - "GL_ROUNDED_RECT4_NV", - }, - { - 0xED, - "GL_RELATIVE_ROUNDED_RECT4_NV", - }, - { - 0xEE, - "GL_ROUNDED_RECT8_NV", - }, - { - 0xEF, - "GL_RELATIVE_ROUNDED_RECT8_NV", - }, - { - 0xF0, - "GL_RESTART_PATH_NV", - }, - { - 0xF2, - "GL_DUP_FIRST_CUBIC_CURVE_TO_NV", - }, - { - 0xF4, - "GL_DUP_LAST_CUBIC_CURVE_TO_NV", - }, - { - 0xF6, - "GL_RECT_NV", - }, - { - 0xF7, - "GL_RELATIVE_RECT_NV", - }, - { - 0xF8, - "GL_CIRCULAR_CCW_ARC_TO_NV", - }, - { - 0xFA, - "GL_CIRCULAR_CW_ARC_TO_NV", - }, - { - 0xFC, - "GL_CIRCULAR_TANGENT_ARC_TO_NV", - }, - { - 0xFE, - "GL_ARC_TO_NV", - }, - { - 0xFF, - "GL_RELATIVE_ARC_TO_NV", - }, - { - 0xFFFFFFFF, - "GL_ALL_SHADER_BITS_EXT", - }, -}; - -const GLES2Util::EnumToString* const GLES2Util::enum_to_string_table_ = - enum_to_string_table; -const size_t GLES2Util::enum_to_string_table_len_ = - sizeof(enum_to_string_table) / sizeof(enum_to_string_table[0]); - std::string GLES2Util::GetStringAttachment(uint32_t value) { static const EnumToString string_table[] = { {GL_COLOR_ATTACHMENT0, "GL_COLOR_ATTACHMENT0"},
diff --git a/gpu/command_buffer/common/gpu_memory_buffer_support.cc b/gpu/command_buffer/common/gpu_memory_buffer_support.cc index abc58d1..454de94 100644 --- a/gpu/command_buffer/common/gpu_memory_buffer_support.cc +++ b/gpu/command_buffer/common/gpu_memory_buffer_support.cc
@@ -4,9 +4,6 @@ #include "gpu/command_buffer/common/gpu_memory_buffer_support.h" -#include <GLES2/gl2.h> -#include <GLES2/gl2extchromium.h> - #include "base/check.h" #include "base/containers/contains.h" #include "base/notreached.h"
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.cc b/gpu/command_buffer/service/shared_image/shared_image_factory.cc index 7923f11..909be10 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_factory.cc +++ b/gpu/command_buffer/service/shared_image/shared_image_factory.cc
@@ -696,7 +696,6 @@ } #endif // BUILDFLAG(IS_FUCHSIA) -#if BUILDFLAG(IS_WIN) bool SharedImageFactory::CopyToGpuMemoryBuffer(const Mailbox& mailbox) { auto it = shared_images_.find(mailbox); if (it == shared_images_.end()) { @@ -706,6 +705,7 @@ return (*it)->CopyToGpuMemoryBuffer(); } +#if BUILDFLAG(IS_WIN) bool SharedImageFactory::CopyToGpuMemoryBufferAsync( const Mailbox& mailbox, base::OnceCallback<void(bool)> callback) {
diff --git a/gpu/command_buffer/service/shared_image/shared_image_factory.h b/gpu/command_buffer/service/shared_image/shared_image_factory.h index 41585ca..3319fcf 100644 --- a/gpu/command_buffer/service/shared_image/shared_image_factory.h +++ b/gpu/command_buffer/service/shared_image/shared_image_factory.h
@@ -122,8 +122,9 @@ // |SharedImageManager::GetUsageForMailbox|. SharedImageUsageSet GetUsageForMailbox(const Mailbox& mailbox); -#if BUILDFLAG(IS_WIN) bool CopyToGpuMemoryBuffer(const Mailbox& mailbox); + +#if BUILDFLAG(IS_WIN) bool CopyToGpuMemoryBufferAsync(const Mailbox& mailbox, base::OnceCallback<void(bool)> callback); #endif
diff --git a/gpu/ipc/client/client_shared_image_interface.cc b/gpu/ipc/client/client_shared_image_interface.cc index c6d8364..647645d 100644 --- a/gpu/ipc/client/client_shared_image_interface.cc +++ b/gpu/ipc/client/client_shared_image_interface.cc
@@ -245,13 +245,13 @@ return shared_image_mapping; } -#if BUILDFLAG(IS_WIN) void ClientSharedImageInterface::CopyToGpuMemoryBuffer( const SyncToken& sync_token, const Mailbox& mailbox) { proxy_->CopyToGpuMemoryBuffer(sync_token, mailbox); } +#if BUILDFLAG(IS_WIN) void ClientSharedImageInterface::CopyToGpuMemoryBufferAsync( const SyncToken& sync_token, const Mailbox& mailbox,
diff --git a/gpu/ipc/client/client_shared_image_interface.h b/gpu/ipc/client/client_shared_image_interface.h index d2a0ce8..e9a7be7 100644 --- a/gpu/ipc/client/client_shared_image_interface.h +++ b/gpu/ipc/client/client_shared_image_interface.h
@@ -73,9 +73,9 @@ // get the shared memory mapping. SharedImageInterface::SharedImageMapping CreateSharedImage( const SharedImageInfo& si_info) override; -#if BUILDFLAG(IS_WIN) void CopyToGpuMemoryBuffer(const SyncToken& sync_token, const Mailbox& mailbox) override; +#if BUILDFLAG(IS_WIN) void CopyToGpuMemoryBufferAsync( const SyncToken& sync_token, const Mailbox& mailbox,
diff --git a/gpu/ipc/client/shared_image_interface_proxy.cc b/gpu/ipc/client/shared_image_interface_proxy.cc index 73f787e0..9da90dd1 100644 --- a/gpu/ipc/client/shared_image_interface_proxy.cc +++ b/gpu/ipc/client/shared_image_interface_proxy.cc
@@ -220,7 +220,6 @@ return mailbox; } -#if BUILDFLAG(IS_WIN) void SharedImageInterfaceProxy::CopyToGpuMemoryBuffer( const SyncToken& sync_token, const Mailbox& mailbox) { @@ -236,6 +235,7 @@ } } +#if BUILDFLAG(IS_WIN) void SharedImageInterfaceProxy::CopyToGpuMemoryBufferAsync( const SyncToken& sync_token, const Mailbox& mailbox,
diff --git a/gpu/ipc/client/shared_image_interface_proxy.h b/gpu/ipc/client/shared_image_interface_proxy.h index 2a5836d..112a365 100644 --- a/gpu/ipc/client/shared_image_interface_proxy.h +++ b/gpu/ipc/client/shared_image_interface_proxy.h
@@ -71,9 +71,10 @@ Mailbox CreateSharedImage(const SharedImageInfo& si_info, gfx::GpuMemoryBufferHandle handle); -#if BUILDFLAG(IS_WIN) void CopyToGpuMemoryBuffer(const SyncToken& sync_token, const Mailbox& mailbox); + +#if BUILDFLAG(IS_WIN) void CopyToGpuMemoryBufferAsync(const SyncToken& sync_token, const Mailbox& mailbox, base::OnceCallback<void(bool)> callback);
diff --git a/gpu/ipc/common/gpu_channel.mojom b/gpu/ipc/common/gpu_channel.mojom index 3f26dbb..73dc04d 100644 --- a/gpu/ipc/common/gpu_channel.mojom +++ b/gpu/ipc/common/gpu_channel.mojom
@@ -487,7 +487,6 @@ UpdateSharedImageParams update_shared_image; // See CopyToGpuMemoryBufferParams. - [EnableIf=is_win] CopyToGpuMemoryBufferParams copy_to_gpu_memory_buffer; // Destroys the shared image identified by this Mailbox. @@ -621,10 +620,9 @@ }; // Updates the contents of the GpuMemoryBuffer associated with the shared image. -// Necessary on platforms like Windows where renderer cannot create native GMBs. -// The command performs synchronization with the GPU so the copy is complete -// after the command runs. -[EnableIf=is_win] +// Necessary on platforms like Windows and Linux where renderer cannot create +// native GMBs. The command performs synchronization with the GPU so the copy is +// complete after the command runs. struct CopyToGpuMemoryBufferParams { // The mailbox identifying the shared image which should update its GMB. Mailbox mailbox;
diff --git a/gpu/ipc/service/shared_image_stub.cc b/gpu/ipc/service/shared_image_stub.cc index 4d54e15..1166d7e7 100644 --- a/gpu/ipc/service/shared_image_stub.cc +++ b/gpu/ipc/service/shared_image_stub.cc
@@ -152,13 +152,13 @@ OnDestroySharedImage(request->get_destroy_shared_image()); break; -#if BUILDFLAG(IS_WIN) case mojom::DeferredSharedImageRequest::Tag::kCopyToGpuMemoryBuffer: { auto& params = *request->get_copy_to_gpu_memory_buffer(); OnCopyToGpuMemoryBuffer(params.mailbox, release_count); break; } +#if BUILDFLAG(IS_WIN) case mojom::DeferredSharedImageRequest::Tag::kCreateSwapChain: OnCreateSwapChain(std::move(request->get_create_swap_chain()), release_count); @@ -412,7 +412,6 @@ #endif } -#if BUILDFLAG(IS_WIN) void SharedImageStub::OnCopyToGpuMemoryBuffer(const Mailbox& mailbox, uint64_t release_count) { TRACE_EVENT0("gpu", "SharedImageStub::OnCopyToGpuMemoryBuffer"); @@ -428,6 +427,7 @@ sync_point_client_state_->ReleaseFenceSync(release_count); } +#if BUILDFLAG(IS_WIN) void SharedImageStub::CopyToGpuMemoryBufferAsync( const Mailbox& mailbox, uint64_t release_count,
diff --git a/gpu/ipc/service/shared_image_stub.h b/gpu/ipc/service/shared_image_stub.h index eff604e..9a84a86 100644 --- a/gpu/ipc/service/shared_image_stub.h +++ b/gpu/ipc/service/shared_image_stub.h
@@ -122,8 +122,8 @@ void OnDestroySharedImage(const Mailbox& mailbox); void OnRegisterSharedImageUploadBuffer(base::ReadOnlySharedMemoryRegion shm); -#if BUILDFLAG(IS_WIN) void OnCopyToGpuMemoryBuffer(const Mailbox& mailbox, uint64_t release_count); +#if BUILDFLAG(IS_WIN) void OnCreateSwapChain(mojom::CreateSwapChainParamsPtr params, uint64_t release_count); void OnPresentSwapChain(const Mailbox& mailbox, uint64_t release_count);
diff --git a/infra/config/generated/testing/gn_isolate_map.pyl b/infra/config/generated/testing/gn_isolate_map.pyl index 0d0201ed4..8f25e242 100644 --- a/infra/config/generated/testing/gn_isolate_map.pyl +++ b/infra/config/generated/testing/gn_isolate_map.pyl
@@ -2,7 +2,6 @@ # Instead: # 1. Modify //infra/config/targets/binaries.star and/or //infra/config/targets/tests.star (for tests defined using targets.tests.junit_test) # 2. Run //infra/config/main.star -# 3. Run //infra/config/scripts/sync-pyl-files.py { "absl_hardening_tests": {
diff --git a/infra/config/generated/testing/mixins.pyl b/infra/config/generated/testing/mixins.pyl index 6439579..d9e77db 100644 --- a/infra/config/generated/testing/mixins.pyl +++ b/infra/config/generated/testing/mixins.pyl
@@ -2,7 +2,10 @@ # Instead: # 1. Modify //infra/config/targets/mixins.star # 2. Run //infra/config/main.star -# 3. Run //infra/config/scripts/sync-pyl-files.py + +# The copy of this file in //testing/buildbot is not read by generate_buildbot_json.py, +# but must be present for downstream uses. It can be kept in sync by running +# //infra/config/scripts/sync-pyl-files.py. { '10-x86-emulator': {
diff --git a/infra/config/generated/testing/test_suites.pyl b/infra/config/generated/testing/test_suites.pyl index 645e5486..17d3b64 100644 --- a/infra/config/generated/testing/test_suites.pyl +++ b/infra/config/generated/testing/test_suites.pyl
@@ -2,7 +2,6 @@ # Instead: # 1. Modify //infra/config/targets/basic_suites.star, //infra/config/targets/compound_suites.star and/or //infra/config/targets/matrix_compound_suites.star # 2. Run //infra/config/main.star -# 3. Run //infra/config/scripts/sync-pyl-files.py { 'basic_suites': {
diff --git a/infra/config/generated/testing/variants.pyl b/infra/config/generated/testing/variants.pyl index d8c38a1..a59158b 100644 --- a/infra/config/generated/testing/variants.pyl +++ b/infra/config/generated/testing/variants.pyl
@@ -2,7 +2,6 @@ # Instead: # 1. Modify //infra/config/targets/variants.star # 2. Run //infra/config/main.star -# 3. Run //infra/config/scripts/sync-pyl-files.py { 'AMD_RADEON_RX_5500_XT': {
diff --git a/infra/config/lib/targets-internal/pyl-generators.star b/infra/config/lib/targets-internal/pyl-generators.star index fc829a5..d54f7c11 100644 --- a/infra/config/lib/targets-internal/pyl-generators.star +++ b/infra/config/lib/targets-internal/pyl-generators.star
@@ -33,8 +33,7 @@ # Instead: # 1. Modify {star_file} # 2. Run //infra/config/main.star -# 3. Run //infra/config/scripts/sync-pyl-files.py - +{extra_comments} {{ {entries} }} @@ -64,6 +63,7 @@ entries.append(" },") ctx.output["testing/gn_isolate_map.pyl"] = _PYL_HEADER_FMT.format( star_file = "//infra/config/targets/binaries.star and/or //infra/config/targets/tests.star (for tests defined using targets.tests.junit_test)", + extra_comments = "", entries = "\n".join(entries), ) @@ -303,6 +303,13 @@ ctx.output["testing/mixins.pyl"] = _PYL_HEADER_FMT.format( star_file = "//infra/config/targets/mixins.star", + extra_comments = "\n".join([ + "", + "# The copy of this file in //testing/buildbot is not read by generate_buildbot_json.py,", + "# but must be present for downstream uses. It can be kept in sync by running", + "# //infra/config/scripts/sync-pyl-files.py.", + "", + ]), entries = formatter.output(), ) @@ -330,6 +337,7 @@ ctx.output["testing/variants.pyl"] = _PYL_HEADER_FMT.format( star_file = "//infra/config/targets/variants.star", + extra_comments = "", entries = formatter.output(), ) @@ -493,6 +501,7 @@ ctx.output["testing/test_suites.pyl"] = _PYL_HEADER_FMT.format( star_file = "//infra/config/targets/basic_suites.star, //infra/config/targets/compound_suites.star and/or //infra/config/targets/matrix_compound_suites.star", + extra_comments = "", entries = formatter.output(), )
diff --git a/infra/config/scripts/sync-pyl-files.py b/infra/config/scripts/sync-pyl-files.py index aa27b5c..77db5c8 100755 --- a/infra/config/scripts/sync-pyl-files.py +++ b/infra/config/scripts/sync-pyl-files.py
@@ -5,19 +5,13 @@ """Sync generated *.pyl files to //testing/buildbot. After modifying the starlark and running it to regenerate configs, if -any files in //infra/config/generated/testing are modified, this script -should be run to sync them to //testing/buildbot. The script can be run -with the --check flag to indicate whether any files are out-of-date. +mixins.pyl has been modified, this script should be run to sync it to +//testing/buildbot. The script can be run with the --check flag to +indicate whether a sync needs to be performed. -The *.pyl files need to be present in //testing/buildbot for multiple -reasons: -* The angle repo uses the *.pyl files in //testing/buildbot via a repo - that mirrors //testing so that the definitions do not need to be kept - in sync. -* pinpoint builds revisions not at head, so until all revisions in scope - for pinpoint contain - //infra/config/generated/testing/gn_isolate_map.pyl, the config - located in recipes cannot be updated to refer to that location. +mixins.pyl needs to be present in //testing/buildbot because the +directory is exported to a separate repo that the angle repo includes as +a dep in order to reuse the mixin definitions. """ import argparse @@ -62,17 +56,11 @@ def main(args): - for f in ( - 'gn_isolate_map.pyl', - 'mixins.pyl', - 'test_suites.pyl', - 'variants.pyl', - ): - error = args.func(os.path.normpath(f'{GENERATED_TESTING_DIR}/{f}'), - os.path.normpath(f'{TESTING_BUILDBOT_DIR}/{f}')) - if error is not None: - print(error, file=sys.stderr) - return 1 + error = args.func(os.path.normpath(f'{GENERATED_TESTING_DIR}/mixins.pyl'), + os.path.normpath(f'{TESTING_BUILDBOT_DIR}/mixins.pyl')) + if error is not None: + print(error, file=sys.stderr) + return 1 return 0
diff --git a/infra/config/targets/README.md b/infra/config/targets/README.md index 532419d..e0d180d3 100644 --- a/infra/config/targets/README.md +++ b/infra/config/targets/README.md
@@ -88,15 +88,15 @@ Currently, a migration is in process to enable tests for a builder to be configured as part of the builder definition itself. In order to avoid having to -manually sync definitions in two locations/systems, some of the .pyl files in -//testing/buildbot that used to be hand-written are now generated from the +manually sync definitions in two locations/systems, some of the .pyl that used +to be hand-written files in //testing/buildbot are now generated from the starlark definitions. Due to intentional design decisions in lucicfg, the files generated from the //infra/config starlark can't be located outside of -//infra/config. Owing to angle using an exported copy of the //testing/buildbot -directory, those .pyl files must still exist in //testing/buildbot. +//infra/config/generated. //testing/buildbot/generate_buildbot_json.py has been +updated to read gn_isolate_map.pyl, mixins.pyl, test_suites.pyl and variants.pyl +from //infra/config/generated/testing. -Because of those constraints, updating some of the .pyl files requires the -following process: +Updating these .pyl files requires the following process: 1. Modify starlark files @@ -115,12 +115,6 @@ On mac or linux, you can just do: `infra/config/main.star` -1. Copy the pyl files from //infra/config/generated/testing to - //testing/buildbot by running - [sync-pyl-files.py](/infra/config/scripts/sync-pyl-files.py) - - `infra/config/scripts/sync-pyl-files.py` - Then you can make any edits you wish to the hand-written .pyl files in //testing/buildbot ([waterfalls.pyl][waterfalls.pyl] and [test_suite_exceptions.pyl](/testing/buildbot/test_suite_exceptions.pyl)) and @@ -129,6 +123,16 @@ [waterfalls.pyl]: /testing/buildbot/waterfalls.pyl +Due to angle using mixins.pyl via a subtree repo that exports +//testing/buildbot, if mixins.pyl was modified by the above steps, it's +necessary to sync that file to //testing/buildbot. + +1. Copy mixins.pyl from //infra/config/generated/testing to + //testing/buildbot by running + [sync-pyl-files.py](/infra/config/scripts/sync-pyl-files.py) + + `infra/config/scripts/sync-pyl-files.py` + ### Setting tests for a builder in starlark It is now possible to specify test in starlark for builders in limited
diff --git a/infra/inclusive_language_presubmit_exempt_dirs.txt b/infra/inclusive_language_presubmit_exempt_dirs.txt index 7610b46..d2d25e5 100644 --- a/infra/inclusive_language_presubmit_exempt_dirs.txt +++ b/infra/inclusive_language_presubmit_exempt_dirs.txt
@@ -653,6 +653,7 @@ third_party/qcms 1 1 third_party/rapidhash 5 2 third_party/rust/chromium_crates_io/vendor/adler-1.0.2/.github/workflows 2 1 +third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.github/workflows 2 1 third_party/rust/chromium_crates_io/vendor/aho-corasick-1.1.3/.github/workflows 5 1 third_party/rust/chromium_crates_io/vendor/anstyle-1.0.8 1 1 third_party/rust/chromium_crates_io/vendor/anyhow-1.0.86 2 1 @@ -674,7 +675,7 @@ third_party/rust/chromium_crates_io/vendor/cxx-1.0.126/.github/workflows 4 3 third_party/rust/chromium_crates_io/vendor/cxx-1.0.126/src 4 1 third_party/rust/chromium_crates_io/vendor/either-1.13.0/.github/workflows 1 1 -third_party/rust/chromium_crates_io/vendor/flate2-1.0.31 32 1 +third_party/rust/chromium_crates_io/vendor/flate2-1.0.33 33 2 third_party/rust/chromium_crates_io/vendor/getrandom-0.2.15 5 1 third_party/rust/chromium_crates_io/vendor/hex-0.4.3 1 1 third_party/rust/chromium_crates_io/vendor/itertools-0.11.0/.github/workflows 1 1 @@ -684,6 +685,7 @@ third_party/rust/chromium_crates_io/vendor/log-0.4.22 1 1 third_party/rust/chromium_crates_io/vendor/log-0.4.22/.github/workflows 8 1 third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.7.4 4 2 +third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0 4 2 third_party/rust/chromium_crates_io/vendor/nom-7.1.3 5 1 third_party/rust/chromium_crates_io/vendor/nom-7.1.3/doc 1 1 third_party/rust/chromium_crates_io/vendor/proc-macro2-1.0.86 1 1
diff --git a/internal b/internal index 00df6cc..b49cbaf 160000 --- a/internal +++ b/internal
@@ -1 +1 @@ -Subproject commit 00df6ccb195fb28a11b4cf5e75ec4f4ff0184a28 +Subproject commit b49cbaf2dea6f1fbf2c6c1c3a09c585e3e80dc3f
diff --git a/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm b/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm index 8886d94..527bc179 100644 --- a/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm +++ b/ios/chrome/browser/autofill/model/autofill_controller_unittest.mm
@@ -977,8 +977,6 @@ // submitted with scripts (simulating form removal) results in a credit // card being successfully imported into the PersonalDataManager. TEST_F(AutofillControllerTest, CreditCardImportAfterFormRemoval) { - ScopedFeatureList feature_list( - features::kAutofillEnableXHRSubmissionDetectionIOS); InfoBarManagerImpl::CreateForWebState(web_state()); PersonalDataManager* personal_data_manager = PersonalDataManagerFactory::GetForBrowserState( @@ -1049,8 +1047,6 @@ // the submitted form. TEST_F(AutofillControllerTest, CreditCardImportWithFieldDataManagerValuesAfterFormRemoval) { - ScopedFeatureList feature_list( - features::kAutofillEnableXHRSubmissionDetectionIOS); InfoBarManagerImpl::CreateForWebState(web_state()); PersonalDataManager* personal_data_manager = PersonalDataManagerFactory::GetForBrowserState( @@ -1138,8 +1134,6 @@ // submitted with scripts (simulating form removal) results in a profile being // successfully imported into the PersonalDataManager. TEST_F(AutofillControllerTest, ProfileImportAfterFormlessFormRemoval) { - ScopedFeatureList feature_list( - features::kAutofillEnableXHRSubmissionDetectionIOS); PersonalDataManager* personal_data_manager = PersonalDataManagerFactory::GetForBrowserState( ChromeBrowserState::FromBrowserState(browser_state_.get()));
diff --git a/ios/chrome/browser/flags/about_flags.mm b/ios/chrome/browser/flags/about_flags.mm index 7798c17..895268f 100644 --- a/ios/chrome/browser/flags/about_flags.mm +++ b/ios/chrome/browser/flags/about_flags.mm
@@ -1650,12 +1650,6 @@ flag_descriptions::kDisableFullscreenScrollingName, flag_descriptions::kDisableFullscreenScrollingDescription, flags_ui::kOsIos, FEATURE_VALUE_TYPE(kDisableFullscreenScrolling)}, - {"autofill-enable-xhr-submission-detection-ios", - flag_descriptions::kAutofillEnableXHRSubmissionDetectionIOSName, - flag_descriptions::kAutofillEnableXHRSubmissionDetectionIOSDescription, - flags_ui::kOsIos, - FEATURE_VALUE_TYPE( - autofill::features::kAutofillEnableXHRSubmissionDetectionIOS)}, {"autofill-enable-prefetching-risk-data-for-retrieval", flag_descriptions::kAutofillEnablePrefetchingRiskDataForRetrievalName, flag_descriptions::
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc index dd3af9ce..f2c54ef 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.cc
@@ -137,12 +137,6 @@ "When enabled, virtual card enrollment and retrieval will be available on " "Bling."; -const char kAutofillEnableXHRSubmissionDetectionIOSName[] = - "Enable XHR submission detection for Autofill"; -const char kAutofillEnableXHRSubmissionDetectionIOSDescription[] = - "When enabled, Chrome will detect forms submitted asynchronously (e.g. " - "AJAX and XMLHttpRequest) for Autofill."; - const char kAutofillIsolatedWorldForJavascriptIOSName[] = "Isolated content world for Autofill"; const char kAutofillIsolatedWorldForJavascriptIOSDescription[] =
diff --git a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h index 29ab2a8..7456522d 100644 --- a/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h +++ b/ios/chrome/browser/flags/ios_chrome_flag_descriptions.h
@@ -110,10 +110,6 @@ extern const char kAutofillEnableVirtualCardsName[]; extern const char kAutofillEnableVirtualCardsDescription[]; -// Title and description for flag to enable XHR submission detection on iOS. -extern const char kAutofillEnableXHRSubmissionDetectionIOSName[]; -extern const char kAutofillEnableXHRSubmissionDetectionIOSDescription[]; - // Title and description for the flag to control whether to use the // isolated content world instead of the page content world for the Autofill JS // feature scripts.
diff --git a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_coordinator.mm b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_coordinator.mm index f6aed604..c733534d 100644 --- a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_coordinator.mm +++ b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_coordinator.mm
@@ -317,11 +317,6 @@ ]; sheet.prefersGrabberVisible = YES; - // TODO(crbug.com/359124093): Temporary workaround as - // `presentViewController:` loads the view asynchronously on the main thread. - // `_resultViewController` needs to first be loaded to avoid crashing by - // calling `setEditView:`. - [_resultViewController loadViewIfNeeded]; [_containerViewController presentViewController:_resultViewController animated:YES completion:nil]; @@ -355,7 +350,7 @@ _mediator.omniboxCoordinator = _omniboxCoordinator; _mediator.toolbarConsumer = _resultViewController; - _resultViewController.omniboxMutator = _mediator; + _resultViewController.toolbarMutator = _mediator; _omniboxCoordinator.focusDelegate = _mediator; }
diff --git a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator.h b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator.h index 941a8af..4ce0ac76 100644 --- a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator.h +++ b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator.h
@@ -8,8 +8,8 @@ #import <UIKit/UIKit.h> #import "ios/chrome/browser/lens_overlay/coordinator/lens_omnibox_client_delegate.h" -#import "ios/chrome/browser/lens_overlay/ui/lens_omnibox_mutator.h" #import "ios/chrome/browser/lens_overlay/ui/lens_overlay_result_consumer.h" +#import "ios/chrome/browser/lens_overlay/ui/lens_toolbar_mutator.h" #import "ios/chrome/browser/ui/omnibox/omnibox_focus_delegate.h" #import "ios/public/provider/chrome/browser/lens/lens_overlay_api.h" @@ -23,8 +23,8 @@ /// Main mediator for Lens Overlay. /// Manages data flow between Selection, Omnibox and Results. @interface LensOverlayMediator : NSObject <ChromeLensOverlayDelegate, - LensOmniboxMutator, LensOmniboxClientDelegate, + LensToolbarMutator, OmniboxFocusDelegate> @property(nonatomic, weak) id<LensOverlayResultConsumer> resultConsumer;
diff --git a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator.mm b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator.mm index d8546449..826cdc20 100644 --- a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator.mm +++ b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator.mm
@@ -74,7 +74,7 @@ [self.resultConsumer loadResultsURL:destinationURL]; } -#pragma mark LensOmniboxMutator +#pragma mark LensToolbarMutator - (void)focusOmnibox { [self.omniboxCoordinator focusOmnibox]; @@ -86,6 +86,10 @@ [self.toolbarConsumer setOmniboxFocused:NO]; } +- (void)goBack { + // TODO(crbug.com/347239663): Implement goBack. +} + #pragma mark OmniboxFocusDelegate - (void)omniboxDidBecomeFirstResponder {
diff --git a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator_unittest.mm b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator_unittest.mm index 2536f0c..46824db 100644 --- a/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator_unittest.mm +++ b/ios/chrome/browser/lens_overlay/coordinator/lens_overlay_mediator_unittest.mm
@@ -62,7 +62,7 @@ /// Tests that the omnibox and toolbar are updated on omnibox focus. TEST_F(LensOverlayMediatorTest, FocusOmnibox) { - // Focus from LensOmniboxMutator. + // Focus from LensToolbarMutator. OCMExpect([mock_omnibox_coordinator_ focusOmnibox]); OCMExpect([mock_toolbar_consumer_ setOmniboxFocused:YES]); [mediator_ focusOmnibox]; @@ -79,7 +79,7 @@ /// Tests that the omnibox and toolbar are updated on omnibox defocus. TEST_F(LensOverlayMediatorTest, DefocusOmnibox) { - // Defocus from LensOmniboxMutator. + // Defocus from LensToolbarMutator. OCMExpect([mock_omnibox_coordinator_ endEditing]); OCMExpect([mock_toolbar_consumer_ setOmniboxFocused:NO]); [mediator_ defocusOmnibox];
diff --git a/ios/chrome/browser/lens_overlay/ui/BUILD.gn b/ios/chrome/browser/lens_overlay/ui/BUILD.gn index add7237..78f0e2f 100644 --- a/ios/chrome/browser/lens_overlay/ui/BUILD.gn +++ b/ios/chrome/browser/lens_overlay/ui/BUILD.gn
@@ -4,9 +4,9 @@ source_set("protocols") { sources = [ - "lens_omnibox_mutator.h", "lens_overlay_result_consumer.h", "lens_toolbar_consumer.h", + "lens_toolbar_mutator.h", ] frameworks = [ "UIKit.framework" ] }
diff --git a/ios/chrome/browser/lens_overlay/ui/lens_omnibox_mutator.h b/ios/chrome/browser/lens_overlay/ui/lens_omnibox_mutator.h deleted file mode 100644 index bb8d862..0000000 --- a/ios/chrome/browser/lens_overlay/ui/lens_omnibox_mutator.h +++ /dev/null
@@ -1,19 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_BROWSER_LENS_OVERLAY_UI_LENS_OMNIBOX_MUTATOR_H_ -#define IOS_CHROME_BROWSER_LENS_OVERLAY_UI_LENS_OMNIBOX_MUTATOR_H_ - -/// Mutator of the lens omnibox. -@protocol LensOmniboxMutator - -/// Focuses the omnibox. -- (void)focusOmnibox; - -/// Defocuses the omnibox. -- (void)defocusOmnibox; - -@end - -#endif // IOS_CHROME_BROWSER_LENS_OVERLAY_UI_LENS_OMNIBOX_MUTATOR_H_
diff --git a/ios/chrome/browser/lens_overlay/ui/lens_result_page_view_controller.h b/ios/chrome/browser/lens_overlay/ui/lens_result_page_view_controller.h index c2206dc..173c035 100644 --- a/ios/chrome/browser/lens_overlay/ui/lens_result_page_view_controller.h +++ b/ios/chrome/browser/lens_overlay/ui/lens_result_page_view_controller.h
@@ -11,7 +11,7 @@ #import "ios/chrome/browser/lens_overlay/ui/lens_toolbar_consumer.h" #import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h" -@protocol LensOmniboxMutator; +@protocol LensToolbarMutator; @protocol TextFieldViewContaining; /// View controller of the lens result page. @@ -23,7 +23,7 @@ /// Container for the web view. @property(nonatomic, strong, readonly) UIView* webViewContainer; /// Mutator of the lens omnibox. -@property(nonatomic, weak) id<LensOmniboxMutator> omniboxMutator; +@property(nonatomic, weak) id<LensToolbarMutator> toolbarMutator; /// Sets the omnibox edit view. - (void)setEditView:(UIView<TextFieldViewContaining>*)editView;
diff --git a/ios/chrome/browser/lens_overlay/ui/lens_result_page_view_controller.mm b/ios/chrome/browser/lens_overlay/ui/lens_result_page_view_controller.mm index f394702..fc92d07 100644 --- a/ios/chrome/browser/lens_overlay/ui/lens_result_page_view_controller.mm +++ b/ios/chrome/browser/lens_overlay/ui/lens_result_page_view_controller.mm
@@ -7,7 +7,7 @@ #import "base/check.h" #import "components/strings/grit/components_strings.h" #import "ios/chrome/browser/keyboard/ui_bundled/UIKeyCommand+Chrome.h" -#import "ios/chrome/browser/lens_overlay/ui/lens_omnibox_mutator.h" +#import "ios/chrome/browser/lens_overlay/ui/lens_toolbar_mutator.h" #import "ios/chrome/browser/shared/public/features/features.h" #import "ios/chrome/browser/shared/ui/symbols/symbols.h" #import "ios/chrome/browser/ui/omnibox/text_field_view_containing.h" @@ -50,6 +50,13 @@ /// Edit view contained in `_omniboxContainer`. @property(nonatomic, strong) UIView<TextFieldViewContaining>* editView; +/// Whether the back button is available. The back button might be available but +/// hidden when the omnibox is focused. +@property(nonatomic, assign) BOOL canGoBack; + +/// Whether the omnibox is currently focused. +@property(nonatomic, assign) BOOL omniboxFocused; + @end @implementation LensResultPageViewController { @@ -72,6 +79,12 @@ if (self) { _webViewContainer = [[UIView alloc] init]; _omniboxPopupContainer = [[UIButton alloc] init]; + + // Initialize `setEditView` dependencies as it can be called before + // `viewDidLoad`. + _omniboxContainer = [[UIView alloc] init]; + _omniboxTapTarget = [[UIButton alloc] init]; + [_omniboxContainer addSubview:_omniboxTapTarget]; } return self; } @@ -108,7 +121,6 @@ forControlEvents:UIControlEventTouchUpInside]; // Omnibox container. - _omniboxContainer = [[UIView alloc] init]; _omniboxContainer.translatesAutoresizingMaskIntoConstraints = NO; _omniboxContainer.backgroundColor = [UIColor colorNamed:kGrey200Color]; _omniboxContainer.layer.cornerRadius = 21; @@ -117,13 +129,11 @@ forAxis:UILayoutConstraintAxisHorizontal]; // Omnibox tap target. - _omniboxTapTarget = [[UIButton alloc] init]; _omniboxTapTarget.translatesAutoresizingMaskIntoConstraints = NO; _omniboxTapTarget.backgroundColor = UIColor.clearColor; [_omniboxTapTarget addTarget:self action:@selector(didTapOmniboxTapTarget:) forControlEvents:UIControlEventTouchUpInside]; - [_omniboxContainer addSubview:_omniboxTapTarget]; AddSameConstraints(_omniboxContainer, _omniboxTapTarget); // Cancel button. @@ -216,7 +226,7 @@ } - (void)keyCommand_close { - [self.omniboxMutator defocusOmnibox]; + [self.toolbarMutator defocusOmnibox]; } #pragma mark - LensResultPageConsumer @@ -268,6 +278,9 @@ #pragma mark - LensToolbarConsumer - (void)setOmniboxFocused:(BOOL)isFocused { + _omniboxFocused = isFocused; + [self updateBackButtonVisibility]; + // Visible when omnibox is focused. _cancelButton.hidden = !isFocused; _omniboxPopupContainer.hidden = !isFocused; @@ -276,26 +289,35 @@ _omniboxTapTarget.hidden = isFocused; } +- (void)setCanGoBack:(BOOL)canGoBack { + _canGoBack = canGoBack; + [self updateBackButtonVisibility]; +} + #pragma mark - Private /// Handles back button taps. - (void)didTapBackButton:(UIView*)button { - // TODO(crbug.com/347239663): Handle back button tap. + [self.toolbarMutator goBack]; } /// Handles omnibox tap target taps. - (void)didTapOmniboxTapTarget:(UIView*)view { - [self.omniboxMutator focusOmnibox]; + [self.toolbarMutator focusOmnibox]; } /// Handles omnibox popup container taps, acting like a typing shield. - (void)didTapOmniboxPopupContainer:(UIView*)view { - [self.omniboxMutator defocusOmnibox]; + [self.toolbarMutator defocusOmnibox]; } /// Handles cancel button taps. - (void)didTapCancelButton:(UIView*)button { - [self.omniboxMutator defocusOmnibox]; + [self.toolbarMutator defocusOmnibox]; +} + +- (void)updateBackButtonVisibility { + _backButton.hidden = self.omniboxFocused || !self.canGoBack; } @end
diff --git a/ios/chrome/browser/lens_overlay/ui/lens_toolbar_consumer.h b/ios/chrome/browser/lens_overlay/ui/lens_toolbar_consumer.h index 05ccbbc..4cdfc49 100644 --- a/ios/chrome/browser/lens_overlay/ui/lens_toolbar_consumer.h +++ b/ios/chrome/browser/lens_overlay/ui/lens_toolbar_consumer.h
@@ -11,6 +11,9 @@ /// Update the UI for omnibox according to omnibox focus state. - (void)setOmniboxFocused:(BOOL)isFocused; +/// Updates the back button availability. +- (void)setCanGoBack:(BOOL)canGoBack; + @end #endif // IOS_CHROME_BROWSER_LENS_OVERLAY_UI_LENS_TOOLBAR_CONSUMER_H_
diff --git a/ios/chrome/browser/lens_overlay/ui/lens_toolbar_mutator.h b/ios/chrome/browser/lens_overlay/ui/lens_toolbar_mutator.h new file mode 100644 index 0000000..5d8df52 --- /dev/null +++ b/ios/chrome/browser/lens_overlay/ui/lens_toolbar_mutator.h
@@ -0,0 +1,22 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef IOS_CHROME_BROWSER_LENS_OVERLAY_UI_LENS_TOOLBAR_MUTATOR_H_ +#define IOS_CHROME_BROWSER_LENS_OVERLAY_UI_LENS_TOOLBAR_MUTATOR_H_ + +/// Mutator of the lens toolbar. +@protocol LensToolbarMutator + +/// Focuses the omnibox. +- (void)focusOmnibox; + +/// Defocuses the omnibox. +- (void)defocusOmnibox; + +/// Navigates to the previous URL. +- (void)goBack; + +@end + +#endif // IOS_CHROME_BROWSER_LENS_OVERLAY_UI_LENS_TOOLBAR_MUTATOR_H_
diff --git a/ios/chrome/browser/metrics/model/demographics_client.mm b/ios/chrome/browser/metrics/model/demographics_client.mm index bc620fd..7688bdb1 100644 --- a/ios/chrome/browser/metrics/model/demographics_client.mm +++ b/ios/chrome/browser/metrics/model/demographics_client.mm
@@ -33,7 +33,12 @@ } syncer::SyncService* DemographicsClient::GetSyncService() { - return SyncServiceFactory::GetForBrowserState(GetCachedBrowserState()); + CHECK_EQ(GetNumberOfProfilesOnDisk(), 1); + if (ChromeBrowserState* cached_browser_state = GetCachedBrowserState()) { + return SyncServiceFactory::GetForBrowserState(cached_browser_state); + } + + return nullptr; } PrefService* DemographicsClient::GetLocalState() { @@ -41,7 +46,12 @@ } PrefService* DemographicsClient::GetProfilePrefs() { - return GetCachedBrowserState()->GetPrefs(); + CHECK_EQ(GetNumberOfProfilesOnDisk(), 1); + if (ChromeBrowserState* cached_browser_state = GetCachedBrowserState()) { + return cached_browser_state->GetPrefs(); + } + + return nullptr; } int DemographicsClient::GetNumberOfProfilesOnDisk() { @@ -51,21 +61,30 @@ ->GetNumberOfProfiles(); } -// TODO(crbug.com/355629111): this API needs to be re-designed to work -// with Multiple Identities. +// Note: this method is only called when GetNumberOfProfilesOnDisk() == 1 thus +// the value should be stable across a single execution of the application. The +// reason is that ProfileManagerIOS only delete the data for a Profile during +// the application startup, so GetNumberOfProfilesOnDisk() can never decrease +// without restarting the application, and thus the return value cannot change +// (since the method must not be called if GetNumberOfProfilesOnDisk() > 1). ChromeBrowserState* DemographicsClient::GetCachedBrowserState() { - ChromeBrowserState* chrome_browser_state = chrome_browser_state_.get(); - if (!chrome_browser_state) { - chrome_browser_state = GetApplicationContext() - ->GetProfileManager() - ->GetLastUsedBrowserStateDeprecatedDoNotUse(); - - CHECK(chrome_browser_state); - chrome_browser_state_ = chrome_browser_state->AsWeakPtr(); + CHECK_EQ(GetNumberOfProfilesOnDisk(), 1); + if (ChromeBrowserState* cached_browser_state = chrome_browser_state_.get()) { + return cached_browser_state; } - CHECK(chrome_browser_state); - return chrome_browser_state; + std::vector<ChromeBrowserState*> loaded_browser_states = + GetApplicationContext()->GetProfileManager()->GetLoadedBrowserStates(); + + // Even if there is only one Profile on disk, it may have not been loaded yet. + if (loaded_browser_states.empty()) { + return nullptr; + } + + CHECK_EQ(loaded_browser_states.size(), 1u); + ChromeBrowserState* cached_browser_state = loaded_browser_states.back(); + chrome_browser_state_ = cached_browser_state->AsWeakPtr(); + return cached_browser_state; } } // namespace metrics
diff --git a/ios/chrome/browser/push_notification/model/push_notification_client_manager.mm b/ios/chrome/browser/push_notification/model/push_notification_client_manager.mm index b4eb84b..2504ba2 100644 --- a/ios/chrome/browser/push_notification/model/push_notification_client_manager.mm +++ b/ios/chrome/browser/push_notification/model/push_notification_client_manager.mm
@@ -8,6 +8,7 @@ #import <vector> +#import "base/task/sequenced_task_runner.h" #import "components/optimization_guide/core/optimization_guide_features.h" #import "ios/chrome/browser/commerce/model/push_notification/commerce_push_notification_client.h" #import "ios/chrome/browser/commerce/model/push_notification/push_notification_feature.h" @@ -34,8 +35,8 @@ } if (IsSafetyCheckNotificationsEnabled()) { - AddPushNotificationClient( - std::make_unique<SafetyCheckNotificationClient>()); + AddPushNotificationClient(std::make_unique<SafetyCheckNotificationClient>( + base::SequencedTaskRunner::GetCurrentDefault())); } } PushNotificationClientManager::~PushNotificationClientManager() = default;
diff --git a/ios/chrome/browser/safety_check_notifications/model/BUILD.gn b/ios/chrome/browser/safety_check_notifications/model/BUILD.gn index 0cba242..650e469 100644 --- a/ios/chrome/browser/safety_check_notifications/model/BUILD.gn +++ b/ios/chrome/browser/safety_check_notifications/model/BUILD.gn
@@ -10,11 +10,19 @@ public_deps = [ "//base", "//ios/chrome/browser/push_notification/model:push_notification_client", + "//ios/chrome/browser/safety_check/model", + "//ios/chrome/browser/safety_check/model:constants", ] deps = [ "//components/prefs", "//ios/chrome/browser/push_notification/model:constants", + "//ios/chrome/browser/safety_check/model", + "//ios/chrome/browser/safety_check/model:factory", + "//ios/chrome/browser/safety_check_notifications/utils", + "//ios/chrome/browser/safety_check_notifications/utils:constants", "//ios/chrome/browser/shared/model/application_context", + "//ios/chrome/browser/shared/model/browser", + "//ios/chrome/browser/shared/model/browser_state", "//ios/chrome/browser/shared/model/prefs:pref_names", ] frameworks = [ @@ -28,12 +36,26 @@ sources = [ "safety_check_notification_client_unittest.mm" ] deps = [ ":notification_client", + "//components/password_manager/core/browser:test_support", + "//components/password_manager/core/browser/password_store:test_support", "//components/prefs", + "//components/safe_browsing/core/common:safe_browsing_prefs", "//ios/chrome/browser/push_notification/model:constants", + "//ios/chrome/browser/safety_check/model", + "//ios/chrome/browser/safety_check/model:factory", + "//ios/chrome/browser/safety_check_notifications/utils:constants", + "//ios/chrome/browser/shared/coordinator/scene:scene_state_header", "//ios/chrome/browser/shared/model/application_context", + "//ios/chrome/browser/shared/model/browser", + "//ios/chrome/browser/shared/model/browser/test:test_support", "//ios/chrome/browser/shared/model/prefs:pref_names", + "//ios/chrome/browser/shared/model/profile/test", "//ios/chrome/test:test_support", + "//ios/testing:block_swizzler", + "//ios/web/public/", + "//ios/web/public/test", "//testing/gtest", + "//third_party/ocmock", ] frameworks = [ "UserNotifications.framework",
diff --git a/ios/chrome/browser/safety_check_notifications/model/DEPS b/ios/chrome/browser/safety_check_notifications/model/DEPS index 70f7ab63..82c4ae5af 100644 --- a/ios/chrome/browser/safety_check_notifications/model/DEPS +++ b/ios/chrome/browser/safety_check_notifications/model/DEPS
@@ -1,3 +1,4 @@ include_rules = [ "+ios/chrome/browser/push_notification/model", + "+ios/chrome/browser/safety_check/model", ]
diff --git a/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.h b/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.h index b03c8586..643c5e0 100644 --- a/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.h +++ b/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.h
@@ -8,14 +8,24 @@ #import <Foundation/Foundation.h> #import <UserNotifications/UserNotifications.h> +#import "base/functional/callback_forward.h" +#import "base/memory/scoped_refptr.h" +#import "base/memory/weak_ptr.h" #import "base/sequence_checker.h" +#import "base/task/sequenced_task_runner.h" #import "ios/chrome/browser/push_notification/model/push_notification_client.h" +#import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager.h" +#import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager_constants.h" // A push notification client for managing Safety Check-related notifications. -// Handles registration, reception, and user interaction with notifications. -class SafetyCheckNotificationClient : public PushNotificationClient { +// Observes Safety Check state changes to ensure notifications are accurate, and +// handles user registration, notification delivery, and user interaction. +class SafetyCheckNotificationClient + : public PushNotificationClient, + public IOSChromeSafetyCheckManagerObserver { public: - SafetyCheckNotificationClient(); + explicit SafetyCheckNotificationClient( + const scoped_refptr<base::SequencedTaskRunner> task_runner); ~SafetyCheckNotificationClient() override; // `PushNotificationClient` overrides. @@ -26,15 +36,68 @@ NSArray<UNNotificationCategory*>* RegisterActionableNotifications() override; void OnSceneActiveForegroundBrowserReady() override; + // Called when the scene becomes "active foreground" and the browser is + // ready. `completion` will be called when all async operations are done. + void OnSceneActiveForegroundBrowserReady(base::OnceClosure completion); + + // `IOSChromeSafetyCheckManagerObserver` overrides. + void PasswordCheckStateChanged(PasswordSafetyCheckState state) override; + void SafeBrowsingCheckStateChanged( + SafeBrowsingSafetyCheckState state) override; + void UpdateChromeCheckStateChanged( + UpdateChromeSafetyCheckState state) override; + void RunningStateChanged(RunningSafetyCheckState state) override; + void ManagerWillShutdown( + IOSChromeSafetyCheckManager* safety_check_manager) override; + private: + // Callback type used with `GetPendingRequest()`. + using GetPendingRequestCallback = + base::OnceCallback<void(UNNotificationRequest*)>; + + // Calls `completion` with a pending request matching `notification_id` if + // there is one, or `nil` if there isn't one. + void GetPendingRequest(NSString* notification_id, + GetPendingRequestCallback completion); + // Returns true if the user has enabled Safety Check notifications, either in // the Notifications Settings UI or through an opt-in prompt (e.g., Magic // Stack, Safety Check page, Password Checkup page). bool IsPermitted(); + // Called when the notification request matching `notification_id` is cleared + // from the pending notification requests schedule. + void OnNotificationCleared(NSString* notification_id, + UNNotificationRequest* request); + + // Clears any previously scheduled notification(s) that match + // `notification_id`. Runs `completion` at the end, once all async operations + // have completed. + void ClearNotification(NSString* notification_id, + base::OnceClosure completion); + + // Schedules a new Safe Browsing notification reflecting `state`, if + // permitted. Runs `completion` at the end, once all async operations have + // completed. + void ScheduleSafeBrowsingNotification(SafeBrowsingSafetyCheckState state, + base::OnceClosure completion); + + // Clears any existing Safe Browsing notification and schedules a new one + // reflecting the latest `state`, if permitted. Runs `completion` + // at the end, once all async operations have completed. + void ClearAndRescheduleSafeBrowsingNotification( + SafeBrowsingSafetyCheckState state, + base::OnceClosure completion); + // Validates asynchronous `PushNotificationClient` events are evaluated on the // same sequence that `SafetyCheckNotificationClient` was created on. SEQUENCE_CHECKER(sequence_checker_); + + // Ensures `IOSChromeSafetyCheckManagerObserver` events are posted on the + // same sequence that `SafetyCheckNotificationClient` was created on. + const scoped_refptr<base::SequencedTaskRunner> task_runner_; + + base::WeakPtrFactory<SafetyCheckNotificationClient> weak_ptr_factory_{this}; }; #endif // IOS_CHROME_BROWSER_SAFETY_CHECK_NOTIFICATIONS_MODEL_SAFETY_CHECK_NOTIFICATION_CLIENT_H_
diff --git a/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.mm b/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.mm index 8628015..94a559d 100644 --- a/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.mm +++ b/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.mm
@@ -4,14 +4,46 @@ #import "ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.h" +#import "base/functional/bind.h" +#import "base/functional/callback_helpers.h" +#import "base/location.h" +#import "base/task/bind_post_task.h" #import "components/prefs/pref_service.h" #import "ios/chrome/browser/push_notification/model/constants.h" #import "ios/chrome/browser/push_notification/model/push_notification_client_id.h" +#import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager.h" +#import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager_factory.h" +#import "ios/chrome/browser/safety_check_notifications/utils/constants.h" +#import "ios/chrome/browser/safety_check_notifications/utils/utils.h" #import "ios/chrome/browser/shared/model/application_context/application_context.h" +#import "ios/chrome/browser/shared/model/browser/browser.h" +#import "ios/chrome/browser/shared/model/browser_state/chrome_browser_state.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" -SafetyCheckNotificationClient::SafetyCheckNotificationClient() - : PushNotificationClient(PushNotificationClientId::kSafetyCheck) {} +namespace { + +// Returns the first notification from `requests` whose identifier matches +// `identifier`. +UNNotificationRequest* NotificationWithIdentifier( + NSString* identifier, + NSArray<UNNotificationRequest*>* requests) { + for (UNNotificationRequest* request in requests) { + if ([request.identifier isEqualToString:identifier]) { + return request; + } + } + + return nil; +} + +} // namespace + +SafetyCheckNotificationClient::SafetyCheckNotificationClient( + const scoped_refptr<base::SequencedTaskRunner> task_runner) + : PushNotificationClient(PushNotificationClientId::kSafetyCheck), + task_runner_(task_runner) { + CHECK(task_runner); +} SafetyCheckNotificationClient::~SafetyCheckNotificationClient() = default; @@ -47,9 +79,106 @@ void SafetyCheckNotificationClient::OnSceneActiveForegroundBrowserReady() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + OnSceneActiveForegroundBrowserReady(base::DoNothing()); +} + +void SafetyCheckNotificationClient::OnSceneActiveForegroundBrowserReady( + base::OnceClosure completion) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // TODO(crbug.com/362479882): Exit if user shouldn't receive a new Safe + // Browsing notification (e.g., notifications disabled, recent notification + // already shown). + if (!IsPermitted()) { + std::move(completion).Run(); + return; + } + + // Confirm that `SafetyCheckNotificationClient` is not observing + // `IOSChromeSafetyCheckManager` before registering itself as an observer for + // Safety Check updates. + if (!IOSChromeSafetyCheckManagerObserver::IsInObserverList()) { + Browser* browser = GetSceneLevelForegroundActiveBrowser(); + + if (!browser) { + std::move(completion).Run(); + return; + } + + ChromeBrowserState* browser_state = browser->GetBrowserState(); + + IOSChromeSafetyCheckManager* safety_check_manager = + IOSChromeSafetyCheckManagerFactory::GetForBrowserState(browser_state); + + safety_check_manager->AddObserver(this); + + ClearAndRescheduleSafeBrowsingNotification( + safety_check_manager->GetSafeBrowsingCheckState(), + std::move(completion)); + + return; + } + // TODO(crbug.com/347975105): Implement // `OnSceneActiveForegroundBrowserReady()` to conditionally schedule // notifications. + std::move(completion).Run(); +} + +void SafetyCheckNotificationClient::PasswordCheckStateChanged( + PasswordSafetyCheckState state) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // TODO(crbug.com/362486324): Re-schedule Safety Check notifications when the + // Passwords state changes. +} + +void SafetyCheckNotificationClient::SafeBrowsingCheckStateChanged( + SafeBrowsingSafetyCheckState state) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // Avoid modifying notifications while the Safe Browsing check is running. + // Wait for a meaningful state change that influences whether Safe Browsing + // notifications should be removed or scheduled. + if (state == SafeBrowsingSafetyCheckState::kRunning) { + return; + } + + ClearAndRescheduleSafeBrowsingNotification(state, base::DoNothing()); +} + +void SafetyCheckNotificationClient::UpdateChromeCheckStateChanged( + UpdateChromeSafetyCheckState state) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // TODO(crbug.com/362487375): Re-schedule Safety Check notifications when the + // Update Chrome state changes. +} + +void SafetyCheckNotificationClient::RunningStateChanged( + RunningSafetyCheckState state) { + // Do nothing. This method is currently a no-op as the running state of Safety + // Check does not directly impact notification scheduling or removal. +} + +void SafetyCheckNotificationClient::ManagerWillShutdown( + IOSChromeSafetyCheckManager* safety_check_manager) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + safety_check_manager->RemoveObserver(this); +} + +void SafetyCheckNotificationClient::GetPendingRequest( + NSString* notification_id, + GetPendingRequestCallback completion) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + auto callback = base::CallbackToBlock(base::BindPostTask( + task_runner_, base::BindOnce(&NotificationWithIdentifier, notification_id) + .Then(std::move(completion)))); + + [UNUserNotificationCenter.currentNotificationCenter + getPendingNotificationRequestsWithCompletionHandler:callback]; } bool SafetyCheckNotificationClient::IsPermitted() { @@ -65,3 +194,70 @@ .FindBool(kSafetyCheckNotificationKey) .value_or(false); } + +void SafetyCheckNotificationClient::OnNotificationCleared( + NSString* notification_id, + UNNotificationRequest* request) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + if (!request) { + // TODO(crbug.com/362481419): Add logging to track the state of the + // notification (requested, triggered, etc.). + return; + } + + [UNUserNotificationCenter.currentNotificationCenter + removePendingNotificationRequestsWithIdentifiers:@[ notification_id ]]; +} + +void SafetyCheckNotificationClient::ClearNotification( + NSString* notification_id, + base::OnceClosure completion) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + GetPendingRequest( + notification_id, + base::BindOnce(&SafetyCheckNotificationClient::OnNotificationCleared, + weak_ptr_factory_.GetWeakPtr(), notification_id) + .Then(std::move(completion))); +} + +void SafetyCheckNotificationClient::ScheduleSafeBrowsingNotification( + SafeBrowsingSafetyCheckState state, + base::OnceClosure completion) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + // TODO(crbug.com/362479882): Exit if user shouldn't receive a new Safe + // Browsing notification (e.g., notifications disabled, recent notification + // already shown). + if (!IsPermitted()) { + std::move(completion).Run(); + return; + } + + // TODO(crbug.com/362481419): Add completion handler to log metrics and + // actions when the Safe Browsing notification is requested. + + UNNotificationRequest* safe_browsing_notification = + SafeBrowsingNotificationRequest(state); + + if (safe_browsing_notification) { + [UNUserNotificationCenter.currentNotificationCenter + addNotificationRequest:safe_browsing_notification + withCompletionHandler:nil]; + } + + std::move(completion).Run(); +} + +void SafetyCheckNotificationClient::ClearAndRescheduleSafeBrowsingNotification( + SafeBrowsingSafetyCheckState state, + base::OnceClosure completion) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + ClearNotification( + kSafetyCheckSafeBrowsingNotificationID, + base::BindOnce( + &SafetyCheckNotificationClient::ScheduleSafeBrowsingNotification, + weak_ptr_factory_.GetWeakPtr(), state, std::move(completion))); +}
diff --git a/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client_unittest.mm b/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client_unittest.mm index 8e24c83..64c6e26 100644 --- a/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client_unittest.mm +++ b/ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client_unittest.mm
@@ -4,32 +4,160 @@ #import "ios/chrome/browser/safety_check_notifications/model/safety_check_notification_client.h" +#import <Foundation/Foundation.h> #import <UserNotifications/UserNotifications.h> #import <memory> +#import "base/functional/bind.h" +#import "base/memory/raw_ptr.h" +#import "base/run_loop.h" +#import "base/task/sequenced_task_runner.h" +#import "base/test/task_environment.h" +#import "components/password_manager/core/browser/password_manager_test_utils.h" +#import "components/password_manager/core/browser/password_store/test_password_store.h" #import "components/prefs/pref_service.h" #import "components/prefs/scoped_user_pref_update.h" +#import "components/safe_browsing/core/common/safe_browsing_prefs.h" +#import "ios/chrome/browser/passwords/model/ios_chrome_profile_password_store_factory.h" #import "ios/chrome/browser/push_notification/model/constants.h" +#import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager.h" +#import "ios/chrome/browser/safety_check/model/ios_chrome_safety_check_manager_factory.h" +#import "ios/chrome/browser/safety_check_notifications/utils/constants.h" +#import "ios/chrome/browser/shared/coordinator/scene/scene_state.h" #import "ios/chrome/browser/shared/model/application_context/application_context.h" +#import "ios/chrome/browser/shared/model/browser/browser_list.h" +#import "ios/chrome/browser/shared/model/browser/browser_list_factory.h" +#import "ios/chrome/browser/shared/model/browser/test/test_browser.h" #import "ios/chrome/browser/shared/model/prefs/pref_names.h" +#import "ios/chrome/browser/shared/model/profile/test/test_profile_manager_ios.h" #import "ios/chrome/test/ios_chrome_scoped_testing_local_state.h" +#import "ios/chrome/test/testing_application_context.h" +#import "ios/testing/scoped_block_swizzler.h" +#import "ios/web/public/browser_state.h" +#import "ios/web/public/test/web_task_environment.h" #import "testing/platform_test.h" +#import "third_party/ocmock/OCMock/OCMock.h" +#import "third_party/ocmock/gtest_support.h" class SafetyCheckNotificationClientTest : public PlatformTest { public: void SetUp() override { - notification_client_ = std::make_unique<SafetyCheckNotificationClient>(); + SetupMockNotificationCenter(); ScopedDictPrefUpdate update(GetApplicationContext()->GetLocalState(), prefs::kAppLevelPushNotificationPermissions); update->Set(kSafetyCheckNotificationKey, true); + + TestChromeBrowserState::Builder builder; + + builder.AddTestingFactory( + IOSChromeProfilePasswordStoreFactory::GetInstance(), + base::BindRepeating( + &password_manager::BuildPasswordStore< + web::BrowserState, password_manager::TestPasswordStore>)); + + ChromeBrowserState* browser_state = + profile_manager_.AddBrowserStateWithBuilder(std::move(builder)); + + BrowserList* list = BrowserListFactory::GetForBrowserState(browser_state); + + mock_scene_state_ = OCMClassMock([SceneState class]); + + OCMStub([mock_scene_state_ activationLevel]) + .andReturn(SceneActivationLevelForegroundActive); + + browser_ = std::make_unique<TestBrowser>(browser_state, mock_scene_state_); + + list->AddBrowser(browser_.get()); + + pref_service_ = browser_state->GetPrefs(); + + local_pref_service_ = + TestingApplicationContext::GetGlobal()->GetLocalState(); + + safety_check_manager_ = std::make_unique<IOSChromeSafetyCheckManager>( + pref_service_.get(), local_pref_service_.get(), + base::SequencedTaskRunner::GetCurrentDefault()); + + notification_client_ = std::make_unique<SafetyCheckNotificationClient>( + base::SequencedTaskRunner::GetCurrentDefault()); + } + + void TearDown() override { + safety_check_manager_->StopSafetyCheck(); + safety_check_manager_->Shutdown(); + } + + // Sets up a mock notification center, so notification requests can be + // tested. + void SetupMockNotificationCenter() { + mock_notification_center_ = OCMClassMock([UNUserNotificationCenter class]); + // Swizzle in the mock notification center. + UNUserNotificationCenter* (^swizzle_block)() = + ^UNUserNotificationCenter*() { + return mock_notification_center_; + }; + notification_center_swizzler_ = std::make_unique<ScopedBlockSwizzler>( + [UNUserNotificationCenter class], @selector(currentNotificationCenter), + swizzle_block); + } + + // Stubs the notification center's completion callback for + // getPendingNotificationRequestsWithCompletionHandler. + void StubGetPendingRequests(NSArray<UNNotificationRequest*>* requests) { + auto completionCaller = + ^BOOL(void (^completion)(NSArray<UNNotificationRequest*>* requests)) { + completion(requests); + return YES; + }; + OCMStub([mock_notification_center_ + getPendingNotificationRequestsWithCompletionHandler: + [OCMArg checkWithBlock:completionCaller]]); + } + + // Returns an `OCMArg` that verifies a `UNNotificationRequest` was passed + // matching `notification_id`. + id NotificationRequestArg(NSString* notification_id) { + return [OCMArg checkWithBlock:^BOOL(UNNotificationRequest* request) { + EXPECT_TRUE([request.identifier isEqualToString:notification_id]); + return YES; + }]; + } + + // Sets up an OCMock expectation that a notification matching + // `notification_id` is requested. + void ExpectNotificationRequest(NSString* notification_id) { + ExpectNotificationRequest(NotificationRequestArg(notification_id)); + } + + void ExpectNotificationRequest(id request) { + auto completionCaller = ^BOOL(void (^completion)(NSError* error)) { + if (completion) { + completion(nil); + } + return YES; + }; + + OCMExpect([mock_notification_center_ + addNotificationRequest:request + withCompletionHandler:[OCMArg checkWithBlock:completionCaller]]); } protected: + web::WebTaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; std::unique_ptr<SafetyCheckNotificationClient> notification_client_; IOSChromeScopedTestingLocalState scoped_testing_local_state_; + TestProfileManagerIOS profile_manager_; + std::unique_ptr<IOSChromeSafetyCheckManager> safety_check_manager_; + id mock_notification_center_; + std::unique_ptr<ScopedBlockSwizzler> notification_center_swizzler_; + id mock_scene_state_; + std::unique_ptr<TestBrowser> browser_; + raw_ptr<PrefService> pref_service_; + raw_ptr<PrefService> local_pref_service_; }; #pragma mark - Test cases @@ -46,3 +174,22 @@ RegisterActionableNotificationsReturnsEmptyArray) { EXPECT_EQ(notification_client_->RegisterActionableNotifications().count, 0u); } + +// Tests that a Safe Browsing notification is correctly scheduled when the user +// turns off Safe Browsing. +TEST_F(SafetyCheckNotificationClientTest, SchedulesSafeBrowsingNotification) { + pref_service_->SetBoolean(prefs::kSafeBrowsingEnhanced, false); + pref_service_->SetBoolean(prefs::kSafeBrowsingEnabled, false); + + StubGetPendingRequests(nil); + ExpectNotificationRequest(kSafetyCheckSafeBrowsingNotificationID); + + base::RunLoop run_loop; + + notification_client_->OnSceneActiveForegroundBrowserReady( + run_loop.QuitClosure()); + + run_loop.Run(); + + EXPECT_OCMOCK_VERIFY(mock_notification_center_); +}
diff --git a/ios/chrome/browser/safety_check_notifications/utils/BUILD.gn b/ios/chrome/browser/safety_check_notifications/utils/BUILD.gn index 4e652b8..8c96950b 100644 --- a/ios/chrome/browser/safety_check_notifications/utils/BUILD.gn +++ b/ios/chrome/browser/safety_check_notifications/utils/BUILD.gn
@@ -7,6 +7,7 @@ "constants.h", "constants.mm", ] + public_deps = [ "//base" ] frameworks = [ "Foundation.framework" ] }
diff --git a/ios/chrome/browser/safety_check_notifications/utils/constants.h b/ios/chrome/browser/safety_check_notifications/utils/constants.h index 45003cd8..f8c99f7 100644 --- a/ios/chrome/browser/safety_check_notifications/utils/constants.h +++ b/ios/chrome/browser/safety_check_notifications/utils/constants.h
@@ -7,6 +7,13 @@ #import <Foundation/Foundation.h> +#import "base/time/time.h" + +// The default duration of user inactivity required before displaying a Safety +// Check push notification. +inline constexpr base::TimeDelta kSafetyCheckNotificationDefaultDelay = + base::Hours(24); + // Unique identifiers and keys for Safety Check push notifications. // Notification ID for the current Password notification.
diff --git a/ios/chrome/browser/safety_check_notifications/utils/utils.h b/ios/chrome/browser/safety_check_notifications/utils/utils.h index 5300c54..b8bd1a42 100644 --- a/ios/chrome/browser/safety_check_notifications/utils/utils.h +++ b/ios/chrome/browser/safety_check_notifications/utils/utils.h
@@ -24,6 +24,12 @@ UNNotificationContent* NotificationForUpdateChromeCheckState( UpdateChromeSafetyCheckState state); +// Returns a notification request for the most critical Safe Browsing issue +// found using `state`. Returns `nil` if no notification request can be +// created. +UNNotificationRequest* SafeBrowsingNotificationRequest( + SafeBrowsingSafetyCheckState state); + // Returns notification content for the most critical Safe Browsing issue found // using `state`. Returns `nil` if no notification content can be created, i.e., // no issue is found.
diff --git a/ios/chrome/browser/safety_check_notifications/utils/utils.mm b/ios/chrome/browser/safety_check_notifications/utils/utils.mm index 7f07fc5c..3f463c5 100644 --- a/ios/chrome/browser/safety_check_notifications/utils/utils.mm +++ b/ios/chrome/browser/safety_check_notifications/utils/utils.mm
@@ -5,6 +5,7 @@ #import "ios/chrome/browser/safety_check_notifications/utils/utils.h" #import "base/strings/sys_string_conversions.h" +#import "base/time/time.h" #import "ios/chrome/browser/safety_check_notifications/utils/constants.h" #import "ios/chrome/grit/ios_branded_strings.h" #import "ios/chrome/grit/ios_strings.h" @@ -153,6 +154,27 @@ return nil; } +UNNotificationRequest* SafeBrowsingNotificationRequest( + SafeBrowsingSafetyCheckState state) { + UNNotificationContent* content = NotificationForSafeBrowsingCheckState(state); + + if (!content) { + return nil; + } + + // TODO(crbug.com/362475364): Enable Safe Browsing notification trigger + // to be configurable via Finch to allow for better testing and + // experimentation. + return [UNNotificationRequest + requestWithIdentifier:kSafetyCheckSafeBrowsingNotificationID + content:content + trigger:[UNTimeIntervalNotificationTrigger + triggerWithTimeInterval: + kSafetyCheckNotificationDefaultDelay + .InSecondsF() + repeats:NO]]; +} + UNNotificationContent* NotificationForSafeBrowsingCheckState( SafeBrowsingSafetyCheckState state) { if (state == SafeBrowsingSafetyCheckState::kUnsafe) {
diff --git a/ios/chrome/browser/sync/model/ios_chrome_sync_client.mm b/ios/chrome/browser/sync/model/ios_chrome_sync_client.mm index 68a7af14..4159d73 100644 --- a/ios/chrome/browser/sync/model/ios_chrome_sync_client.mm +++ b/ios/chrome/browser/sync/model/ios_chrome_sync_client.mm
@@ -152,8 +152,6 @@ browser_sync::CommonControllerBuilder builder; builder.SetAutofillWebDataService( web::GetUIThreadTaskRunner({}), - profile_web_data_service ? profile_web_data_service->GetDBTaskRunner() - : nullptr, profile_web_data_service, ios::WebDataServiceFactory::GetAutofillWebDataForAccount( browser_state_, ServiceAccessType::IMPLICIT_ACCESS));
diff --git a/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm b/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm index a7cb8a12..7e06561f 100644 --- a/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm +++ b/ios/chrome/browser/ui/omnibox/popup/autocomplete_match_formatter.mm
@@ -222,6 +222,9 @@ if (omnibox_feature_configs::SuggestionAnswerMigration::Get().enabled) { return _match.answer_type == omnibox::ANSWER_TYPE_DICTIONARY ? 3 : 1; } + if (_match.answer->second_line().text_fields().empty()) { + return 1; + } // Answers specify their own limit on the number of lines to show but are // additionally capped here at 3 to guard against unreasonable values. const SuggestionAnswer::TextField& first_text_field =
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_query_manager.h b/ios/components/security_interstitials/safe_browsing/safe_browsing_query_manager.h index ff62ec3..794b8d1 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_query_manager.h +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_query_manager.h
@@ -24,6 +24,13 @@ class SafeBrowsingClient; +// Used to identify the type of check a query is. For example, `kSync` is used +// to trigger logic related to sync checks. +enum class QueryType { + kSync = 0, + kAsync = 1, +}; + // A helper object that manages the Safe Browsing URL queries for a single // WebState. class SafeBrowsingQueryManager @@ -73,6 +80,7 @@ struct QueryData { explicit QueryData(SafeBrowsingQueryManager* manager, const SafeBrowsingQueryManager::Query& query, + const QueryType query_type, const SafeBrowsingQueryManager::Result& result, safe_browsing::SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check); @@ -85,6 +93,8 @@ SafeBrowsingQueryManager* manager; // The underlying query. const SafeBrowsingQueryManager::Query& query; + // The type of query. + const QueryType type; // The result of the query. const SafeBrowsingQueryManager::Result& result; // The PerformedCheck for a query. @@ -195,7 +205,7 @@ // `url_checker_client_`. void UrlCheckFinished( const Query query, - bool is_async_check, + const QueryType query_type, bool proceed, bool show_error_page, safe_browsing::SafeBrowsingUrlCheckerImpl::PerformedCheck
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_query_manager.mm b/ios/components/security_interstitials/safe_browsing/safe_browsing_query_manager.mm index 1f3b3cb..f2854f41 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_query_manager.mm +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_query_manager.mm
@@ -69,15 +69,14 @@ performed_check)> sync_callback = base::BindOnce(&SafeBrowsingQueryManager::UrlCheckFinished, - weak_factory_.GetWeakPtr(), query, - /*is_async_check=*/false); + weak_factory_.GetWeakPtr(), query, QueryType::kSync); base::OnceCallback<void( bool proceed, bool show_error_page, safe_browsing::SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check)> async_callback = base::BindOnce( &SafeBrowsingQueryManager::UrlCheckFinished, - weak_factory_.GetWeakPtr(), query, /*is_async_check=*/true); + weak_factory_.GetWeakPtr(), query, QueryType::kAsync); std::unique_ptr<safe_browsing::SafeBrowsingUrlCheckerImpl> sync_checker = safe_browsing_service->CreateSyncChecker(request_destination, @@ -96,9 +95,9 @@ bool proceed, bool show_error_page, safe_browsing::SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check)> - callback = base::BindOnce(&SafeBrowsingQueryManager::UrlCheckFinished, - weak_factory_.GetWeakPtr(), query, - /*is_async_check=*/false); + callback = + base::BindOnce(&SafeBrowsingQueryManager::UrlCheckFinished, + weak_factory_.GetWeakPtr(), query, QueryType::kSync); std::unique_ptr<safe_browsing::SafeBrowsingUrlCheckerImpl> url_checker = safe_browsing_service->CreateUrlChecker(request_destination, web_state_, @@ -129,7 +128,7 @@ void SafeBrowsingQueryManager::UrlCheckFinished( const Query query, - bool is_async_check, + const QueryType type, bool proceed, bool show_error_page, safe_browsing::SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check) { @@ -162,18 +161,18 @@ if (base::FeatureList::IsEnabled( safe_browsing::kSafeBrowsingAsyncRealTimeCheck)) { - if (is_async_check) { + if (type == QueryType::kAsync) { result.async_check_complete = true; - } else { + } else if (type == QueryType::kSync) { result.sync_check_complete = true; } for (auto& observer : observers_) { const QueryData& query_data = - QueryData(this, query, result, performed_check); - if (is_async_check) { + QueryData(this, query, type, result, performed_check); + if (type == QueryType::kAsync) { observer.SafeBrowsingAsyncQueryFinished(query_data); - } else { + } else if (type == QueryType::kSync) { observer.SafeBrowsingSyncQueryFinished(query_data); } @@ -229,10 +228,12 @@ SafeBrowsingQueryManager::QueryData::QueryData( SafeBrowsingQueryManager* manager, const SafeBrowsingQueryManager::Query& query, + const QueryType type, const SafeBrowsingQueryManager::Result& result, safe_browsing::SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check) : manager(manager), query(query), + type(type), result(result), performed_check(performed_check) {}
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_tab_helper.h b/ios/components/security_interstitials/safe_browsing/safe_browsing_tab_helper.h index 11cb521..97c16a4 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_tab_helper.h +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_tab_helper.h
@@ -90,8 +90,7 @@ // taking into account if the check is a sync or async check. void HandlePolicyDecision( const SafeBrowsingQueryManager::QueryData& query_data, - const web::WebStatePolicyDecider::PolicyDecision& policy_decision, - bool is_async_check); + const web::WebStatePolicyDecider::PolicyDecision& policy_decision); // Notifies the policy decider that a new main frame document has been // loaded. @@ -139,38 +138,33 @@ MainFrameUrlQuery* GetOldestPendingMainFrameQuery(const GURL& url); // Returns the oldest pending main frame query for `query_data` that has not - // yet received a decision taking into account `query_data` and uses - // `is_async` to only consider async queries if true and sync queries if - // false. If there are no queries for `query_data` or if all relevant - // queries have already been decided, returns null. + // yet received a decision taking into account `query_data` to distinguish + // sync and async queries. If there are no queries for `query_data` or if + // all relevant queries have already been decided, returns null. MainFrameUrlQuery* GetOldestPendingMainFrameQuery( - const SafeBrowsingQueryManager::QueryData& query_data, - bool is_async); + const SafeBrowsingQueryManager::QueryData& query_data); // Returns the oldest pending query for the // `to_be_committed_redirect_chain_` that has not yet received a decision - // taking into account `query_data` and uses `is_async` to distinguish sync - // and async queries. If there are no queries for `query_data` or if all - // relevant queries have already been decided, returns null. + // taking into account `query_data` to distinguish sync and async queries. + // If there are no queries for `query_data` or if all relevant queries have + // already been decided, returns null. MainFrameUrlQuery* GetOldestPendingToBeCommittedQuery( - const SafeBrowsingQueryManager::QueryData& query_data, - bool is_async); + const SafeBrowsingQueryManager::QueryData& query_data); // Returns the oldest pending query for the `committed_redirect_chain_` that - // has not yet received a decision taking into account `query_data` and uses - // `is_async` to distinguish sync and async queries. If there are no queries - // for `query_data` or if all relevant queries have already been decided, + // has not yet received a decision taking into account `query_data` to + // distinguish sync and async queries. If there are no queries for + // `query_data` or if all relevant queries have already been decided, // returns null. MainFrameUrlQuery* GetOldestPendingCommittedQuery( - const SafeBrowsingQueryManager::QueryData& query_data, - bool is_async); + const SafeBrowsingQueryManager::QueryData& query_data); - // Iterates through the `redirect_chain` and uses `query_data` and - // `is_async` to return an unanswered sync or async query. + // Iterates through the `redirect_chain` and uses `query_data` to return an + // unanswered sync or async query. MainFrameUrlQuery* GetUnansweredQueryForRedirectChain( std::list<MainFrameUrlQuery>& redirect_chain, - const SafeBrowsingQueryManager::QueryData& query_data, - bool is_async); + const SafeBrowsingQueryManager::QueryData& query_data); // Callback invoked when a main frame query for `url` has finished with // `decision` after performing a check of type `performed_check`.
diff --git a/ios/components/security_interstitials/safe_browsing/safe_browsing_tab_helper.mm b/ios/components/security_interstitials/safe_browsing/safe_browsing_tab_helper.mm index 432bed3..35df888 100644 --- a/ios/components/security_interstitials/safe_browsing/safe_browsing_tab_helper.mm +++ b/ios/components/security_interstitials/safe_browsing/safe_browsing_tab_helper.mm
@@ -202,13 +202,12 @@ void SafeBrowsingTabHelper::PolicyDecider::HandlePolicyDecision( const SafeBrowsingQueryManager::QueryData& query_data, - const web::WebStatePolicyDecider::PolicyDecision& policy_decision, - bool is_async_check) { + const web::WebStatePolicyDecider::PolicyDecision& policy_decision) { DCHECK(!IsQueryStale(query_data.query)); - if (is_async_check) { + if (query_data.type == QueryType::kAsync) { OnMainFrameUrlAsyncQueryDecided(query_data, policy_decision); - } else { + } else if (query_data.type == QueryType::kSync) { OnMainFrameUrlSyncQueryDecided(query_data, policy_decision); } } @@ -370,22 +369,23 @@ SafeBrowsingTabHelper::PolicyDecider::MainFrameUrlQuery* SafeBrowsingTabHelper::PolicyDecider::GetOldestPendingMainFrameQuery( - const SafeBrowsingQueryManager::QueryData& query_data, - bool is_async) { + const SafeBrowsingQueryManager::QueryData& query_data) { const GURL& url = query_data.query.url; MainFrameUrlQuery* redirect_chain_query = GetUnansweredQueryForRedirectChain( - pending_main_frame_redirect_chain_, query_data, is_async); + pending_main_frame_redirect_chain_, query_data); if (redirect_chain_query) { return redirect_chain_query; } if (pending_main_frame_query_ && pending_main_frame_query_->url == url) { - if (!is_async && !pending_main_frame_query_->sync_check_complete) { + if (query_data.type == QueryType::kSync && + !pending_main_frame_query_->sync_check_complete) { return &pending_main_frame_query_.value(); } - if (is_async && !pending_main_frame_query_->async_check_complete) { + if (query_data.type == QueryType::kAsync && + !pending_main_frame_query_->async_check_complete) { return &pending_main_frame_query_.value(); } } @@ -395,19 +395,17 @@ SafeBrowsingTabHelper::PolicyDecider::MainFrameUrlQuery* SafeBrowsingTabHelper::PolicyDecider::GetOldestPendingToBeCommittedQuery( - const SafeBrowsingQueryManager::QueryData& query_data, - bool is_async) { + const SafeBrowsingQueryManager::QueryData& query_data) { MainFrameUrlQuery* redirect_chain_query = GetUnansweredQueryForRedirectChain( - to_be_committed_redirect_chain_, query_data, is_async); + to_be_committed_redirect_chain_, query_data); return redirect_chain_query; } SafeBrowsingTabHelper::PolicyDecider::MainFrameUrlQuery* SafeBrowsingTabHelper::PolicyDecider::GetOldestPendingCommittedQuery( - const SafeBrowsingQueryManager::QueryData& query_data, - bool is_async) { - MainFrameUrlQuery* redirect_chain_query = GetUnansweredQueryForRedirectChain( - committed_redirect_chain_, query_data, is_async); + const SafeBrowsingQueryManager::QueryData& query_data) { + MainFrameUrlQuery* redirect_chain_query = + GetUnansweredQueryForRedirectChain(committed_redirect_chain_, query_data); return redirect_chain_query; } @@ -415,17 +413,16 @@ SafeBrowsingTabHelper::PolicyDecider::GetUnansweredQueryForRedirectChain( std::list<SafeBrowsingTabHelper::PolicyDecider::MainFrameUrlQuery>& redirect_chain, - const SafeBrowsingQueryManager::QueryData& query_data, - bool is_async) { + const SafeBrowsingQueryManager::QueryData& query_data) { const GURL& url = query_data.query.url; for (auto& query : redirect_chain) { if (query.url == url) { - if (is_async && !query.async_check_complete) { + if (query_data.type == QueryType::kAsync && !query.async_check_complete) { return &query; } - if (!is_async && !query.sync_check_complete) { + if (query_data.type == QueryType::kSync && !query.sync_check_complete) { return &query; } } @@ -474,8 +471,7 @@ const GURL& url = query_data.query.url; SafeBrowsingUrlCheckerImpl::PerformedCheck performed_check = query_data.performed_check; - MainFrameUrlQuery* query = - GetOldestPendingMainFrameQuery(query_data, /*is_async=*/false); + MainFrameUrlQuery* query = GetOldestPendingMainFrameQuery(query_data); query->decision = decision; query->sync_check_complete = true; @@ -515,8 +511,7 @@ void SafeBrowsingTabHelper::PolicyDecider::OnMainFrameUrlAsyncQueryDecided( const SafeBrowsingQueryManager::QueryData& query_data, web::WebStatePolicyDecider::PolicyDecision decision) { - MainFrameUrlQuery* query = - GetOldestPendingMainFrameQuery(query_data, /*is_async=*/true); + MainFrameUrlQuery* query = GetOldestPendingMainFrameQuery(query_data); query->async_check_complete = true; std::optional<web::WebStatePolicyDecider::PolicyDecision> query_decision = query->decision; @@ -666,8 +661,7 @@ web::WebStatePolicyDecider::PolicyDecision policy_decision = policy_decider_->CreatePolicyDecision(query_data.query, query_data.result, web_state_); - policy_decider_->HandlePolicyDecision(query_data, policy_decision, - /*is_async_check=*/false); + policy_decider_->HandlePolicyDecision(query_data, policy_decision); } void SafeBrowsingTabHelper::QueryObserver::SafeBrowsingAsyncQueryFinished(
diff --git a/ios/web_view/internal/sync/web_view_sync_service_factory.mm b/ios/web_view/internal/sync/web_view_sync_service_factory.mm index b78e368d..38f326b 100644 --- a/ios/web_view/internal/sync/web_view_sync_service_factory.mm +++ b/ios/web_view/internal/sync/web_view_sync_service_factory.mm
@@ -69,7 +69,6 @@ controller_builder.SetAutofillWebDataService( web::GetUIThreadTaskRunner({}), - autofill_profile_web_data_service->GetDBTaskRunner(), autofill_profile_web_data_service, WebViewWebDataServiceWrapperFactory::GetAutofillWebDataForAccount( browser_state, ServiceAccessType::IMPLICIT_ACCESS));
diff --git a/ios_internal b/ios_internal index 546afc2..e1fa9c5 160000 --- a/ios_internal +++ b/ios_internal
@@ -1 +1 @@ -Subproject commit 546afc212797e507ffad9bcecbc38e381f50e7aa +Subproject commit e1fa9c580e9ae769577b551d19ad93035aaa6a79
diff --git a/media/audio/audio_debug_file_writer.cc b/media/audio/audio_debug_file_writer.cc index d08a1da..db2fec19 100644 --- a/media/audio/audio_debug_file_writer.cc +++ b/media/audio/audio_debug_file_writer.cc
@@ -179,8 +179,7 @@ // to write to the file. static_assert(ARCH_CPU_LITTLE_ENDIAN); - auto span = base::as_chars(interleaved_data_->as_span()); - file_.WriteAtCurrentPos(span.data(), span.size_bytes()); + file_.WriteAtCurrentPos(base::as_bytes(interleaved_data_->as_span())); // Cache the AudioBus for later use. audio_bus_pool_->InsertAudioBus(std::move(data));
diff --git a/media/audio/simple_sources_unittest.cc b/media/audio/simple_sources_unittest.cc index c420fd1b..472063a 100644 --- a/media/audio/simple_sources_unittest.cc +++ b/media/audio/simple_sources_unittest.cc
@@ -15,6 +15,7 @@ #include <limits> #include <memory> +#include "base/containers/span.h" #include "base/files/file_util.h" #include "base/time/time.h" #include "media/audio/audio_io.h" @@ -123,7 +124,7 @@ ASSERT_TRUE(base::CreateTemporaryFile(&temp_path)); base::File temp(temp_path, base::File::FLAG_WRITE | base::File::FLAG_OPEN_ALWAYS); - temp.WriteAtCurrentPos(kTestAudioData, kTestAudioDataSize); + temp.WriteAtCurrentPos(base::byte_span_from_cstring(kTestAudioData)); ASSERT_EQ(kTestAudioDataSize, static_cast<size_t>(temp.GetLength())); temp.Close(); @@ -161,7 +162,7 @@ ASSERT_TRUE(base::CreateTemporaryFile(&temp_path)); base::File temp(temp_path, base::File::FLAG_WRITE | base::File::FLAG_OPEN_ALWAYS); - temp.WriteAtCurrentPos(kTestAudioData, kTestAudioDataSize); + temp.WriteAtCurrentPos(base::byte_span_from_cstring(kTestAudioData)); ASSERT_EQ(kTestAudioDataSize, static_cast<size_t>(temp.GetLength())); temp.Close(); @@ -216,7 +217,7 @@ ASSERT_TRUE(base::CreateTemporaryFile(&temp_path)); base::File temp(temp_path, base::File::FLAG_WRITE | base::File::FLAG_OPEN_ALWAYS); - temp.WriteAtCurrentPos(kTestAudioData, kTestAudioDataSize); + temp.WriteAtCurrentPos(base::byte_span_from_cstring(kTestAudioData)); // Corrupt the header. temp.Write(3, "0x00", 1);
diff --git a/media/base/video_aspect_ratio.cc b/media/base/video_aspect_ratio.cc index dac01e2c..6da2aa9 100644 --- a/media/base/video_aspect_ratio.cc +++ b/media/base/video_aspect_ratio.cc
@@ -37,6 +37,13 @@ aspect_ratio_ = h != 0.0 ? w / h : 0.0; } +bool VideoAspectRatio::operator==(const VideoAspectRatio& other) const { + if (!IsValid() || !other.IsValid()) { + return IsValid() == other.IsValid(); + } + return type_ == other.type_ && aspect_ratio_ == other.aspect_ratio_; +} + bool VideoAspectRatio::IsValid() const { return std::isfinite(aspect_ratio_) && aspect_ratio_ > 0.0; }
diff --git a/media/base/video_aspect_ratio.h b/media/base/video_aspect_ratio.h index 7288120..7eb3368 100644 --- a/media/base/video_aspect_ratio.h +++ b/media/base/video_aspect_ratio.h
@@ -11,8 +11,17 @@ #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" +namespace mojo { +template <typename DataViewType, typename T> +struct StructTraits; +} // namespace mojo + namespace media { +namespace mojom { +class VideoAspectRatioDataView; +} // namespace mojom + class MEDIA_EXPORT VideoAspectRatio { public: // Create a pixel aspect ratio (PAR). |width| and |height| describe the @@ -36,6 +45,8 @@ VideoAspectRatio(const gfx::Rect& visible_rect, const gfx::Size& natural_size); + bool operator==(const VideoAspectRatio& other) const; + // An aspect ratio is invalid if it was default constructed, had nonpositive // components, or exceeds implementation limits. bool IsValid() const; @@ -45,6 +56,9 @@ gfx::Size GetNaturalSize(const gfx::Rect& visible_rect) const; private: + friend struct mojo::StructTraits<mojom::VideoAspectRatioDataView, + VideoAspectRatio>; + enum class Type { kDisplay, kPixel,
diff --git a/media/base/video_decoder_config.cc b/media/base/video_decoder_config.cc index cb892a60..ee8c7a7 100644 --- a/media/base/video_decoder_config.cc +++ b/media/base/video_decoder_config.cc
@@ -81,6 +81,7 @@ coded_size() == config.coded_size() && visible_rect() == config.visible_rect() && natural_size() == config.natural_size() && + aspect_ratio() == config.aspect_ratio() && extra_data() == config.extra_data() && encryption_scheme() == config.encryption_scheme() && color_space_info() == config.color_space_info() &&
diff --git a/media/capture/video/chromeos/token_manager.cc b/media/capture/video/chromeos/token_manager.cc index 422374c..20c30bc 100644 --- a/media/capture/video/chromeos/token_manager.cc +++ b/media/capture/video/chromeos/token_manager.cc
@@ -63,8 +63,7 @@ << token_path.AsUTF8Unsafe(); return false; } - std::string token_string = token.ToString(); - token_file.WriteAtCurrentPos(token_string.c_str(), token_string.length()); + token_file.WriteAtCurrentPos(base::as_byte_span(token.ToString())); return true; }
diff --git a/media/gpu/test/video_test_helpers.cc b/media/gpu/test/video_test_helpers.cc index ad7e75c..b61aad7 100644 --- a/media/gpu/test/video_test_helpers.cc +++ b/media/gpu/test/video_test_helpers.cc
@@ -128,8 +128,7 @@ writer.WriteU32LittleEndian(0u); CHECK_EQ(writer.remaining(), 0u); - return output_file_.WriteAtCurrentPos(ivf_header, std::size(ivf_header)) == - static_cast<int>(std::size(ivf_header)); + return output_file_.WriteAtCurrentPosAndCheck(base::as_byte_span(ivf_header)); } bool IvfWriter::WriteFrame(uint32_t data_size, @@ -138,12 +137,12 @@ char ivf_frame_header[kIvfFrameHeaderSize] = {}; memcpy(&ivf_frame_header[0], &data_size, sizeof(data_size)); memcpy(&ivf_frame_header[4], ×tamp, sizeof(timestamp)); - bool success = - output_file_.WriteAtCurrentPos(ivf_frame_header, kIvfFrameHeaderSize) == - static_cast<int>(kIvfFrameHeaderSize) && - output_file_.WriteAtCurrentPos(reinterpret_cast<const char*>(data), - data_size) == static_cast<int>(data_size); - return success; + if (!output_file_.WriteAtCurrentPosAndCheck( + base::as_byte_span(ivf_frame_header))) { + return false; + } + auto data_span = UNSAFE_TODO(base::span(data, data_size)); + return output_file_.WriteAtCurrentPosAndCheck(data_span); } // static
diff --git a/media/mojo/mojom/BUILD.gn b/media/mojo/mojom/BUILD.gn index 306a06d..5f28c24 100644 --- a/media/mojo/mojom/BUILD.gn +++ b/media/mojo/mojom/BUILD.gn
@@ -378,23 +378,32 @@ { types = [ { + mojom = "media.mojom.VideoAspectRatio" + cpp = "::media::VideoAspectRatio" + }, + ] + traits_headers = [ "video_aspect_ratio_mojom_traits.h" ] + }, + { + types = [ + { mojom = "media.mojom.VideoColorSpace.PrimaryID" cpp = "::media::VideoColorSpace::PrimaryID" }, { - mojom = "media.mojom.VideoColorSpace.TransferID:" + mojom = "media.mojom.VideoColorSpace.TransferID" cpp = "::media::VideoColorSpace::TransferID" }, { - mojom = "media.mojom.VideoColorSpace.MatrixID:" + mojom = "media.mojom.VideoColorSpace.MatrixID" cpp = "::media::VideoColorSpace::MatrixID" }, { - mojom = "media.mojom.VideoColorSpace.RangeID:" + mojom = "media.mojom.VideoColorSpace.RangeID" cpp = "::gfx::ColorSpace::RangeID" }, { - mojom = "media.mojom.VideoColorSpace:" + mojom = "media.mojom.VideoColorSpace" cpp = "::media::VideoColorSpace" }, ]
diff --git a/media/mojo/mojom/media_types.mojom b/media/mojo/mojom/media_types.mojom index 0f25c1a..0b034df 100644 --- a/media/mojo/mojom/media_types.mojom +++ b/media/mojo/mojom/media_types.mojom
@@ -156,6 +156,18 @@ kOnKeyPic }; +// This defines a mojo transport format for media::VideoAspectRatio. +// See media/base/video_aspect_ratio.h for description. +struct VideoAspectRatio { + enum Type { + kDisplay, + kPixel, + }; + + Type type; + double value; +}; + // This defines a mojo transport format for media::VideoColorSpace. // See media/base/video_color_space.h for description. struct VideoColorSpace { @@ -208,6 +220,7 @@ gfx.mojom.Size coded_size; gfx.mojom.Rect visible_rect; gfx.mojom.Size natural_size; + VideoAspectRatio aspect_ratio; array<uint8> extra_data; EncryptionScheme encryption_scheme; VideoColorSpace color_space_info;
diff --git a/media/mojo/mojom/video_aspect_ratio_mojom_traits.h b/media/mojo/mojom/video_aspect_ratio_mojom_traits.h new file mode 100644 index 0000000..ae3da6e --- /dev/null +++ b/media/mojo/mojom/video_aspect_ratio_mojom_traits.h
@@ -0,0 +1,47 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_MOJO_MOJOM_VIDEO_ASPECT_RATIO_MOJOM_TRAITS_H_ +#define MEDIA_MOJO_MOJOM_VIDEO_ASPECT_RATIO_MOJOM_TRAITS_H_ + +#include "media/base/video_aspect_ratio.h" +#include "media/mojo/mojom/media_types.mojom.h" + +namespace mojo { + +template <> +struct StructTraits<media::mojom::VideoAspectRatioDataView, + media::VideoAspectRatio> { + static media::mojom::VideoAspectRatio_Type type( + const media::VideoAspectRatio& input) { + switch (input.type_) { + case media::VideoAspectRatio::Type::kDisplay: + return media::mojom::VideoAspectRatio_Type::kDisplay; + case media::VideoAspectRatio::Type::kPixel: + return media::mojom::VideoAspectRatio_Type::kPixel; + } + } + + static double value(const media::VideoAspectRatio& input) { + return input.aspect_ratio_; + } + + static bool Read(media::mojom::VideoAspectRatioDataView data, + media::VideoAspectRatio* output) { + switch (data.type()) { + case media::mojom::VideoAspectRatio_Type::kDisplay: + output->type_ = media::VideoAspectRatio::Type::kDisplay; + break; + case media::mojom::VideoAspectRatio_Type::kPixel: + output->type_ = media::VideoAspectRatio::Type::kPixel; + break; + } + output->aspect_ratio_ = data.value(); + return true; + } +}; + +} // namespace mojo + +#endif // MEDIA_MOJO_MOJOM_VIDEO_ASPECT_RATIO_MOJOM_TRAITS_H_
diff --git a/media/mojo/mojom/video_decoder_config_mojom_traits.cc b/media/mojo/mojom/video_decoder_config_mojom_traits.cc index df6dac0..d1b2a06 100644 --- a/media/mojo/mojom/video_decoder_config_mojom_traits.cc +++ b/media/mojo/mojom/video_decoder_config_mojom_traits.cc
@@ -35,6 +35,11 @@ if (!input.ReadNaturalSize(&natural_size)) return false; + media::VideoAspectRatio aspect_ratio; + if (!input.ReadAspectRatio(&aspect_ratio)) { + return false; + } + std::vector<uint8_t> extra_data; if (!input.ReadExtraData(&extra_data)) return false; @@ -58,11 +63,13 @@ color_space, transformation, coded_size, visible_rect, natural_size, extra_data, encryption_scheme); + output->set_level(input.level()); + + output->set_aspect_ratio(aspect_ratio); + if (hdr_metadata) output->set_hdr_metadata(hdr_metadata.value()); - output->set_level(input.level()); - if (!output->IsValidConfig()) return false;
diff --git a/media/mojo/mojom/video_decoder_config_mojom_traits.h b/media/mojo/mojom/video_decoder_config_mojom_traits.h index 2cd322c..e313c5a7 100644 --- a/media/mojo/mojom/video_decoder_config_mojom_traits.h +++ b/media/mojo/mojom/video_decoder_config_mojom_traits.h
@@ -10,6 +10,7 @@ #include "media/base/ipc/media_param_traits.h" #include "media/base/video_decoder_config.h" #include "media/mojo/mojom/media_types.mojom.h" +#include "media/mojo/mojom/video_aspect_ratio_mojom_traits.h" #include "media/mojo/mojom/video_color_space_mojom_traits.h" #include "media/mojo/mojom/video_transformation_mojom_traits.h" #include "ui/gfx/geometry/mojom/geometry_mojom_traits.h" @@ -46,6 +47,11 @@ return input.natural_size(); } + static const media::VideoAspectRatio& aspect_ratio( + const media::VideoDecoderConfig& input) { + return input.aspect_ratio(); + } + static const std::vector<uint8_t>& extra_data( const media::VideoDecoderConfig& input) { return input.extra_data();
diff --git a/media/mojo/mojom/video_decoder_config_mojom_traits_unittest.cc b/media/mojo/mojom/video_decoder_config_mojom_traits_unittest.cc index 49488d4..49a6b17 100644 --- a/media/mojo/mojom/video_decoder_config_mojom_traits_unittest.cc +++ b/media/mojo/mojom/video_decoder_config_mojom_traits_unittest.cc
@@ -72,6 +72,26 @@ } TEST(VideoDecoderConfigStructTraitsTest, + ConvertVideoDecoderConfig_AspectRatio) { + VideoDecoderConfig input( + VideoCodec::kVP8, VP8PROFILE_ANY, + VideoDecoderConfig::AlphaMode::kIsOpaque, + VideoColorSpace(VideoColorSpace::PrimaryID::BT2020, + VideoColorSpace::TransferID::SMPTEST2084, + VideoColorSpace::MatrixID::BT2020_CL, + gfx::ColorSpace::RangeID::LIMITED), + kNoTransformation, kCodedSize, kVisibleRect, kNaturalSize, + EmptyExtraData(), EncryptionScheme::kUnencrypted); + input.set_aspect_ratio(VideoAspectRatio::DAR(3, 1)); + std::vector<uint8_t> data = + media::mojom::VideoDecoderConfig::Serialize(&input); + VideoDecoderConfig output; + EXPECT_TRUE( + media::mojom::VideoDecoderConfig::Deserialize(std::move(data), &output)); + EXPECT_TRUE(output.Matches(input)); +} + +TEST(VideoDecoderConfigStructTraitsTest, ConvertVideoDecoderConfig_ColorSpaceInfo) { VideoDecoderConfig input( VideoCodec::kVP8, VP8PROFILE_ANY,
diff --git a/net/cert/cert_verify_proc_builtin.cc b/net/cert/cert_verify_proc_builtin.cc index c24daa4..68ddf27 100644 --- a/net/cert/cert_verify_proc_builtin.cc +++ b/net/cert/cert_verify_proc_builtin.cc
@@ -13,7 +13,6 @@ #include "base/feature_list.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" -#include "base/metrics/histogram_functions.h" #include "base/time/time.h" #include "base/values.h" #include "components/network_time/time_tracker/time_tracker.h" @@ -1229,9 +1228,6 @@ ct_policy_enforcer_.get(), net_fetcher_.get(), ev_metadata, &checked_revocation_for_some_path, net_log); - base::UmaHistogramCounts10000("Net.CertVerifier.PathBuilderIterationCount", - result.iteration_count); - net_log.EndEvent(NetLogEventType::CERT_VERIFY_PROC_PATH_BUILD_ATTEMPT, [&] { return NetLogPathBuilderResult(result); });
diff --git a/net/cert/cert_verify_proc_builtin_unittest.cc b/net/cert/cert_verify_proc_builtin_unittest.cc index 8f95249..ea02337 100644 --- a/net/cert/cert_verify_proc_builtin_unittest.cc +++ b/net/cert/cert_verify_proc_builtin_unittest.cc
@@ -15,7 +15,6 @@ #include "base/strings/stringprintf.h" #include "base/task/sequenced_task_runner.h" #include "base/task/thread_pool.h" -#include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" #include "base/time/time.h" @@ -429,7 +428,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -438,9 +436,6 @@ int error = callback.WaitForResult(); EXPECT_THAT(error, IsOk()); - EXPECT_THAT(histogram_tester.GetAllSamples( - "Net.CertVerifier.PathBuilderIterationCount"), - testing::ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); } TEST_F(CertVerifyProcBuiltinTest, CallsCtVerifierAndReturnsSctStatus) { @@ -468,7 +463,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -505,7 +499,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -531,7 +524,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -541,9 +533,6 @@ int error = callback.WaitForResult(); EXPECT_THAT(error, IsError(ERR_CERT_AUTHORITY_INVALID)); EXPECT_EQ(1u, verify_result.verified_cert->intermediate_buffers().size()); - EXPECT_THAT(histogram_tester.GetAllSamples( - "Net.CertVerifier.PathBuilderIterationCount"), - testing::ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); } TEST_F(CertVerifyProcBuiltinTest, AddedRootWithConstraints) { @@ -559,7 +548,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -583,7 +571,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -616,7 +603,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -625,9 +611,6 @@ int error = callback.WaitForResult(); EXPECT_THAT(error, IsOk()); - EXPECT_THAT(histogram_tester.GetAllSamples( - "Net.CertVerifier.PathBuilderIterationCount"), - testing::ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); } TEST_F(CertVerifyProcBuiltinTest, @@ -685,7 +668,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -694,9 +676,6 @@ int error = callback.WaitForResult(); EXPECT_THAT(error, IsOk()); - EXPECT_THAT(histogram_tester.GetAllSamples( - "Net.CertVerifier.PathBuilderIterationCount"), - testing::ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); } TEST_F(CertVerifyProcBuiltinTest, @@ -747,7 +726,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -771,7 +749,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -798,7 +775,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -826,7 +802,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback callback; @@ -873,7 +848,6 @@ { // Pretend the root is a known root. SetMockIsKnownRoot(true); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; TestCompletionCallback verify_callback; Verify(chain.get(), "www.example.com", @@ -885,9 +859,6 @@ // should be successful. EXPECT_THAT(error, IsOk()); EXPECT_TRUE(verify_result.cert_status & CERT_STATUS_REV_CHECKING_ENABLED); - EXPECT_THAT(histogram_tester.GetAllSamples( - "Net.CertVerifier.PathBuilderIterationCount"), - testing::ElementsAre(base::Bucket(/*min=*/1, /*count=*/1))); } } @@ -939,7 +910,6 @@ scoped_refptr<X509Certificate> chain = leaf->GetX509CertificateChain(); ASSERT_TRUE(chain.get()); - base::HistogramTester histogram_tester; CertVerifyResult verify_result; NetLogSource verify_net_log_source; TestCompletionCallback verify_callback; @@ -962,9 +932,6 @@ // Soft-fail revocation checking was used, therefore verification result // should be OK even though none of the CRLs could be retrieved. EXPECT_THAT(error, IsOk()); - EXPECT_THAT(histogram_tester.GetAllSamples( - "Net.CertVerifier.PathBuilderIterationCount"), - testing::ElementsAre(base::Bucket(/*min=*/2, /*count=*/1))); } // Tests that if the verification deadline is exceeded during revocation
diff --git a/net/http/transport_security_state_static.pins b/net/http/transport_security_state_static.pins index 210dc4c..ff7dced 100644 --- a/net/http/transport_security_state_static.pins +++ b/net/http/transport_security_state_static.pins
@@ -43,9 +43,9 @@ # hash function for preloaded entries again (we have already done so once). # -# Last updated: 2024-08-26 12:56 UTC +# Last updated: 2024-08-28 12:54 UTC PinsListTimestamp -1724676992 +1724849668 TestSPKI sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
diff --git a/net/http/transport_security_state_static_pins.json b/net/http/transport_security_state_static_pins.json index 8a83632..d65993e 100644 --- a/net/http/transport_security_state_static_pins.json +++ b/net/http/transport_security_state_static_pins.json
@@ -31,7 +31,7 @@ // the 'static_spki_hashes' and 'bad_static_spki_hashes' fields in 'pinsets' // refer to, and the timestamp at which the pins list was last updated. // -// Last updated: 2024-08-26 12:56 UTC +// Last updated: 2024-08-28 12:54 UTC // { "pinsets": [
diff --git a/remoting/base/BUILD.gn b/remoting/base/BUILD.gn index e183601..26df50c6 100644 --- a/remoting/base/BUILD.gn +++ b/remoting/base/BUILD.gn
@@ -66,6 +66,8 @@ "is_google_email.h", "leaky_bucket.cc", "leaky_bucket.h", + "local_session_policies_provider.cc", + "local_session_policies_provider.h", "logging_service_client.h", "protobuf_http_client.cc", "protobuf_http_client.h", @@ -135,6 +137,7 @@ ":name_value_map", ":protobuf_http_client_messages_proto", ":remoting_base_version", + ":session_policies", "//build:chromeos_buildflags", "//google_apis", "//google_apis/common:request_util", @@ -413,6 +416,7 @@ "capabilities_unittest.cc", "compound_buffer_unittest.cc", "leaky_bucket_unittest.cc", + "local_session_policies_provider_unittest.cc", "oauth_token_getter_proxy_unittest.cc", "port_range_unittest.cc", "protobuf_http_client_unittest.cc",
diff --git a/remoting/base/local_session_policies_provider.cc b/remoting/base/local_session_policies_provider.cc new file mode 100644 index 0000000..ee5ea29 --- /dev/null +++ b/remoting/base/local_session_policies_provider.cc
@@ -0,0 +1,29 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/base/local_session_policies_provider.h" + +#include "remoting/base/session_policies.h" + +namespace remoting { + +LocalSessionPoliciesProvider::LocalSessionPoliciesProvider() = default; +LocalSessionPoliciesProvider::~LocalSessionPoliciesProvider() = default; + +base::CallbackListSubscription +LocalSessionPoliciesProvider::AddLocalPoliciesChangedCallback( + LocalPoliciesChangedCallback callback) const { + return local_policies_changed_callbacks_.Add(std::move(callback)); +} + +void LocalSessionPoliciesProvider::set_local_policies( + const SessionPolicies& policies) { + if (policies == local_policies_) { + return; + } + local_policies_ = policies; + local_policies_changed_callbacks_.Notify(local_policies_); +} + +} // namespace remoting
diff --git a/remoting/base/local_session_policies_provider.h b/remoting/base/local_session_policies_provider.h new file mode 100644 index 0000000..3531692 --- /dev/null +++ b/remoting/base/local_session_policies_provider.h
@@ -0,0 +1,49 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef REMOTING_BASE_LOCAL_SESSION_POLICIES_PROVIDER_H_ +#define REMOTING_BASE_LOCAL_SESSION_POLICIES_PROVIDER_H_ + +#include "base/callback_list.h" +#include "base/functional/callback.h" +#include "remoting/base/session_policies.h" + +namespace remoting { + +// Class that provides the local SessionPolicies. +class LocalSessionPoliciesProvider final { + public: + using LocalPoliciesChangedCallbackList = + base::RepeatingCallbackList<void(const SessionPolicies&)>; + using LocalPoliciesChangedCallback = + LocalPoliciesChangedCallbackList::CallbackType; + + LocalSessionPoliciesProvider(); + ~LocalSessionPoliciesProvider(); + + LocalSessionPoliciesProvider(const LocalSessionPoliciesProvider&) = delete; + LocalSessionPoliciesProvider& operator=(const LocalSessionPoliciesProvider&) = + delete; + + // Calls `callback` whenever the local policies are changed. + // This is marked `const` to allow a holder of a const reference or pointer of + // `this` to add callbacks but not change the local policies. + base::CallbackListSubscription AddLocalPoliciesChangedCallback( + LocalPoliciesChangedCallback callback) const; + + const SessionPolicies& get_local_policies() const { return local_policies_; } + + // Sets the local policies. If the new policies are equal to the previous + // policies LocalPoliciesChanged callbacks will not be notified. + void set_local_policies(const SessionPolicies& policies); + + private: + SessionPolicies local_policies_; + // Mutable to allow const access from `AddLocalPoliciesChangedCallback()`. + mutable LocalPoliciesChangedCallbackList local_policies_changed_callbacks_; +}; + +} // namespace remoting + +#endif // REMOTING_BASE_LOCAL_SESSION_POLICIES_PROVIDER_H_
diff --git a/remoting/base/local_session_policies_provider_unittest.cc b/remoting/base/local_session_policies_provider_unittest.cc new file mode 100644 index 0000000..4ce599d --- /dev/null +++ b/remoting/base/local_session_policies_provider_unittest.cc
@@ -0,0 +1,62 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "remoting/base/local_session_policies_provider.h" + +#include <memory> + +#include "base/callback_list.h" +#include "base/test/mock_callback.h" +#include "base/time/time.h" +#include "remoting/base/session_policies.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace remoting { + +class LocalSessionPoliciesProviderTest : public testing::Test { + protected: + LocalSessionPoliciesProvider provider_; +}; + +TEST_F(LocalSessionPoliciesProviderTest, ProvideEmptyPoliciesByDefault) { + EXPECT_EQ(provider_.get_local_policies(), SessionPolicies()); +} + +TEST_F(LocalSessionPoliciesProviderTest, + PoliciesChanged_UpdatePoliciesAndNotifyCallbacks) { + base::MockCallback<LocalSessionPoliciesProvider::LocalPoliciesChangedCallback> + callback; + auto subscription = provider_.AddLocalPoliciesChangedCallback(callback.Get()); + SessionPolicies new_policies = {.maximum_session_duration = base::Hours(10)}; + EXPECT_CALL(callback, Run(new_policies)).Times(1); + provider_.set_local_policies(new_policies); + EXPECT_EQ(provider_.get_local_policies(), new_policies); +} + +TEST_F(LocalSessionPoliciesProviderTest, + PoliciesNotChanged_CallbacksNotNotified) { + SessionPolicies new_policies = {.maximum_session_duration = base::Hours(10)}; + provider_.set_local_policies(new_policies); + + base::MockCallback<LocalSessionPoliciesProvider::LocalPoliciesChangedCallback> + callback; + auto subscription = provider_.AddLocalPoliciesChangedCallback(callback.Get()); + provider_.set_local_policies(new_policies); + EXPECT_CALL(callback, Run(new_policies)).Times(0); +} + +TEST_F(LocalSessionPoliciesProviderTest, + SubscriptionDiscarded_CallbackNoLongerNotified) { + base::MockCallback<LocalSessionPoliciesProvider::LocalPoliciesChangedCallback> + callback; + auto subscription = std::make_unique<base::CallbackListSubscription>( + provider_.AddLocalPoliciesChangedCallback(callback.Get())); + subscription.reset(); + SessionPolicies new_policies = {.maximum_session_duration = base::Hours(10)}; + EXPECT_CALL(callback, Run(new_policies)).Times(0); + provider_.set_local_policies(new_policies); +} + +} // namespace remoting
diff --git a/remoting/host/base/desktop_environment_options.cc b/remoting/host/base/desktop_environment_options.cc index 5154d107..ed5aed8 100644 --- a/remoting/host/base/desktop_environment_options.cc +++ b/remoting/host/base/desktop_environment_options.cc
@@ -87,22 +87,6 @@ terminate_upon_input_ = enabled; } -bool DesktopEnvironmentOptions::enable_file_transfer() const { - return enable_file_transfer_; -} - -void DesktopEnvironmentOptions::set_enable_file_transfer(bool enabled) { - enable_file_transfer_ = enabled; -} - -bool DesktopEnvironmentOptions::enable_remote_open_url() const { - return enable_remote_open_url_; -} - -void DesktopEnvironmentOptions::set_enable_remote_open_url(bool enabled) { - enable_remote_open_url_ = enabled; -} - bool DesktopEnvironmentOptions::enable_remote_webauthn() const { return enable_remote_webauthn_; } @@ -111,15 +95,6 @@ enable_remote_webauthn_ = enabled; } -const std::optional<size_t>& DesktopEnvironmentOptions::clipboard_size() const { - return clipboard_size_; -} - -void DesktopEnvironmentOptions::set_clipboard_size( - std::optional<size_t> clipboard_size) { - clipboard_size_ = std::move(clipboard_size); -} - bool DesktopEnvironmentOptions::capture_video_on_dedicated_thread() const { // TODO(joedow): Determine whether we can migrate additional platforms to // using the DesktopCaptureWrapper instead of the DesktopCaptureProxy. Then
diff --git a/remoting/host/base/desktop_environment_options.h b/remoting/host/base/desktop_environment_options.h index cb72f84..2ae46af 100644 --- a/remoting/host/base/desktop_environment_options.h +++ b/remoting/host/base/desktop_environment_options.h
@@ -42,18 +42,9 @@ bool terminate_upon_input() const; void set_terminate_upon_input(bool enabled); - bool enable_file_transfer() const; - void set_enable_file_transfer(bool enabled); - - bool enable_remote_open_url() const; - void set_enable_remote_open_url(bool enabled); - bool enable_remote_webauthn() const; void set_enable_remote_webauthn(bool enabled); - const std::optional<size_t>& clipboard_size() const; - void set_clipboard_size(std::optional<size_t> clipboard_size); - const webrtc::DesktopCaptureOptions* desktop_capture_options() const; webrtc::DesktopCaptureOptions* desktop_capture_options(); @@ -80,22 +71,9 @@ // True if the session should be terminated when local input is detected. bool terminate_upon_input_ = false; - // True if this host has file transfer enabled. - bool enable_file_transfer_ = false; - - // True if this host has the remote open URL feature enabled. Note, caller - // should also call IsRemoteOpenUrlSupported() to determine if the feature is - // supported by the platform. - bool enable_remote_open_url_ = false; - // True if this host has the remote WebAuthn feature enabled. bool enable_remote_webauthn_ = false; - // If set, this value is used to constrain the amount of data that can be - // transferred using ClipboardEvents. A value of 0 will effectively disable - // clipboard sharing. - std::optional<size_t> clipboard_size_; - // True if the video capturer should be run on a dedicated thread. bool capture_video_on_dedicated_thread_ = false;
diff --git a/remoting/host/chromoting_host.cc b/remoting/host/chromoting_host.cc index ff77421b..9d76f07 100644 --- a/remoting/host/chromoting_host.cc +++ b/remoting/host/chromoting_host.cc
@@ -22,6 +22,7 @@ #include "components/named_mojo_ipc_server/named_mojo_ipc_server.h" #include "components/webrtc/thread_wrapper.h" #include "remoting/base/constants.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/base/logging.h" #include "remoting/host/desktop_environment.h" #include "remoting/host/host_config.h" @@ -83,7 +84,8 @@ scoped_refptr<protocol::TransportContext> transport_context, scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner, scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner, - const DesktopEnvironmentOptions& options) + const DesktopEnvironmentOptions& options, + const LocalSessionPoliciesProvider* local_session_policies_provider) : desktop_environment_factory_(desktop_environment_factory), session_manager_(std::move(session_manager)), transport_context_(transport_context), @@ -91,7 +93,8 @@ video_encode_task_runner_(video_encode_task_runner), status_monitor_(new HostStatusMonitor()), login_backoff_(&kDefaultBackoffPolicy), - desktop_environment_options_(options) { + desktop_environment_options_(options), + local_session_policies_provider_(local_session_policies_provider) { webrtc::ThreadWrapper::EnsureForCurrentMessageLoop(); } @@ -158,13 +161,6 @@ session_manager_->set_authenticator_factory(std::move(authenticator_factory)); } -void ChromotingHost::SetLocalSessionPolicies(const SessionPolicies& policies) { - local_session_policies_ = policies; - for (auto& client : clients_) { - client->OnLocalPoliciesChanged(policies); - } -} - //////////////////////////////////////////////////////////////////////////// // protocol::ClientSession::EventHandler implementation. void ChromotingHost::OnSessionAuthenticating(ClientSession* client) { @@ -326,7 +322,7 @@ clients_.push_back(std::make_unique<ClientSession>( this, std::move(connection), desktop_environment_factory_, desktop_environment_options_, pairing_registry_, extension_ptrs, - local_session_policies_)); + local_session_policies_provider_)); } ClientSession* ChromotingHost::GetConnectedClientSession() const {
diff --git a/remoting/host/chromoting_host.h b/remoting/host/chromoting_host.h index 6c40f0e..e14b5cf7 100644 --- a/remoting/host/chromoting_host.h +++ b/remoting/host/chromoting_host.h
@@ -20,7 +20,7 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "net/base/backoff_entry.h" -#include "remoting/base/session_policies.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/host/base/desktop_environment_options.h" #include "remoting/host/client_session.h" #include "remoting/host/host_extension.h" @@ -84,7 +84,8 @@ scoped_refptr<protocol::TransportContext> transport_context, scoped_refptr<base::SingleThreadTaskRunner> audio_task_runner, scoped_refptr<base::SingleThreadTaskRunner> video_encode_task_runner, - const DesktopEnvironmentOptions& options); + const DesktopEnvironmentOptions& options, + const LocalSessionPoliciesProvider* local_session_policies_provider); ChromotingHost(const ChromotingHost&) = delete; ChromotingHost& operator=(const ChromotingHost&) = delete; @@ -127,8 +128,6 @@ void SetAuthenticatorFactory( std::unique_ptr<protocol::AuthenticatorFactory> authenticator_factory); - void SetLocalSessionPolicies(const SessionPolicies& policies); - //////////////////////////////////////////////////////////////////////////// // ClientSession::EventHandler implementation. void OnSessionAuthenticating(ClientSession* client) override; @@ -196,7 +195,7 @@ // Options to initialize a DesktopEnvironment. const DesktopEnvironmentOptions desktop_environment_options_; - SessionPolicies local_session_policies_; + raw_ptr<const LocalSessionPoliciesProvider> local_session_policies_provider_; // The pairing registry for PIN-less authentication. scoped_refptr<protocol::PairingRegistry> pairing_registry_;
diff --git a/remoting/host/chromoting_host_unittest.cc b/remoting/host/chromoting_host_unittest.cc index 334ab9130..6a457d659 100644 --- a/remoting/host/chromoting_host_unittest.cc +++ b/remoting/host/chromoting_host_unittest.cc
@@ -25,7 +25,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "net/base/network_change_notifier.h" #include "remoting/base/auto_thread_task_runner.h" -#include "remoting/base/session_policies.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/host/audio_capturer.h" #include "remoting/host/chromoting_host_context.h" #include "remoting/host/fake_desktop_environment.h" @@ -95,7 +95,8 @@ protocol::TransportContext::ForTests(protocol::TransportRole::SERVER), task_runner_, // Audio task_runner_, - DesktopEnvironmentOptions::CreateDefault()); // Video encode + DesktopEnvironmentOptions::CreateDefault(), // Video encode + &local_session_policies_provider_); host_->status_monitor()->AddStatusObserver(&host_status_observer_); owner_email_ = "host@domain"; @@ -153,7 +154,7 @@ host_.get(), std::move(connection), desktop_environment_factory_.get(), DesktopEnvironmentOptions::CreateDefault(), nullptr, std::vector<raw_ptr<HostExtension, VectorExperimental>>(), - SessionPolicies()); + &local_session_policies_provider_); ClientSession* client_ptr = client.get(); connection_ptr->set_host_stub(client.get()); @@ -298,6 +299,7 @@ MockConnectionToClientEventHandler handler_; std::unique_ptr<FakeDesktopEnvironmentFactory> desktop_environment_factory_; MockHostStatusObserver host_status_observer_; + LocalSessionPoliciesProvider local_session_policies_provider_; std::unique_ptr<ChromotingHost> host_; raw_ptr<protocol::MockSessionManager> session_manager_; std::string owner_email_; @@ -406,49 +408,6 @@ ShutdownHost(); } -TEST_F(ChromotingHostTest, SetSessionPolicies_UpdatesNewClientsPolicies) { - SessionPolicies policies = {.maximum_session_duration = base::Hours(10)}; - StartHost(); - - host_->SetLocalSessionPolicies(policies); - MockSession* session = session_unowned1_.get(); - protocol::SessionManager::IncomingSessionResponse response; - host_->OnIncomingSession(session_unowned1_.release(), &response); - - EXPECT_EQ(host_->client_sessions_for_tests().size(), 1u); - const SessionPolicies& effective_policies = - host_->client_sessions_for_tests()[0]->effective_policies_for_tests(); - EXPECT_EQ(effective_policies, policies); - - EXPECT_CALL(*session, Close(_)) - .WillOnce(InvokeWithoutArgs( - this, &ChromotingHostTest::NotifyConnectionClosed1)); - ShutdownHost(); -} - -TEST_F(ChromotingHostTest, SetSessionPolicies_UpdatesExistingClientsPolicies) { - SessionPolicies old_policies = {.maximum_session_duration = base::Hours(10)}; - SessionPolicies new_policies = {.maximum_session_duration = base::Hours(23)}; - StartHost(); - - host_->SetLocalSessionPolicies(old_policies); - MockSession* session = session_unowned1_.get(); - protocol::SessionManager::IncomingSessionResponse response; - host_->OnIncomingSession(session_unowned1_.release(), &response); - host_->SetLocalSessionPolicies(new_policies); - - EXPECT_EQ(host_->client_sessions_for_tests().size(), 1u); - const SessionPolicies& effective_policies = - host_->client_sessions_for_tests()[0]->effective_policies_for_tests(); - EXPECT_NE(effective_policies, old_policies); - EXPECT_EQ(effective_policies, new_policies); - - EXPECT_CALL(*session, Close(_)) - .WillOnce(InvokeWithoutArgs( - this, &ChromotingHostTest::NotifyConnectionClosed1)); - ShutdownHost(); -} - TEST_F(ChromotingHostTest, LoginBackOffTriggersIfClientsDoNotAuthenticate) { StartHost();
diff --git a/remoting/host/client_session.cc b/remoting/host/client_session.cc index f789912d..1c38eb6 100644 --- a/remoting/host/client_session.cc +++ b/remoting/host/client_session.cc
@@ -24,6 +24,7 @@ #include "remoting/base/errors.h" #include "remoting/base/logging.h" #include "remoting/base/session_options.h" +#include "remoting/base/session_policies.h" #include "remoting/host/action_executor.h" #include "remoting/host/action_message_handler.h" #include "remoting/host/active_display_monitor.h" @@ -40,6 +41,7 @@ #include "remoting/host/mouse_shape_pump.h" #include "remoting/host/remote_open_url/remote_open_url_constants.h" #include "remoting/host/remote_open_url/remote_open_url_message_handler.h" +#include "remoting/host/remote_open_url/remote_open_url_util.h" #include "remoting/host/remote_open_url/url_forwarder_configurator.h" #include "remoting/host/remote_open_url/url_forwarder_control_message_handler.h" #include "remoting/host/security_key/security_key_extension.h" @@ -85,7 +87,7 @@ const DesktopEnvironmentOptions& desktop_environment_options, scoped_refptr<protocol::PairingRegistry> pairing_registry, const std::vector<raw_ptr<HostExtension, VectorExperimental>>& extensions, - const SessionPolicies& local_policies) + const LocalSessionPoliciesProvider* local_session_policies_provider) : event_handler_(event_handler), desktop_environment_factory_(desktop_environment_factory), desktop_environment_options_(desktop_environment_options), @@ -101,7 +103,7 @@ pairing_registry_(pairing_registry), connection_(std::move(connection)), client_jid_(connection_->session()->jid()), - effective_policies_(local_policies) { + local_session_policies_provider_(local_session_policies_provider) { connection_->session()->AddPlugin(&host_experiment_session_plugin_); connection_->SetEventHandler(this); @@ -507,6 +509,14 @@ desktop_display_info_.Reset(); + effective_policies_ = local_session_policies_provider_->get_local_policies(); + // TODO: crbug.com/359977809 - Do not subscribe when we use another source of + // session policies. + local_session_policy_update_subscription_ = + local_session_policies_provider_->AddLocalPoliciesChangedCallback( + base::BindRepeating(&ClientSession::OnLocalSessionPoliciesChanged, + weak_factory_.GetWeakPtr())); + HOST_LOG << "Connection authenticated with session policies: " << effective_policies_; @@ -532,8 +542,7 @@ // Create the desktop environment. Drop the connection if it could not be // created for any reason (for instance the curtain could not initialize). desktop_environment_ = desktop_environment_factory_->Create( - client_session_control_weak_factory_.GetWeakPtr(), - client_session_events_weak_factory_.GetWeakPtr(), options); + weak_factory_.GetWeakPtr(), weak_factory_.GetWeakPtr(), options); if (!desktop_environment_) { DisconnectSession(ErrorCode::HOST_CONFIGURATION_ERROR); return; @@ -560,6 +569,15 @@ host_capabilities_.append(" "); host_capabilities_.append(protocol::kTouchEventsCapability); } + if (effective_policies_.allow_file_transfer.value_or(true)) { + host_capabilities_.append(" "); + host_capabilities_.append(protocol::kFileTransferCapability); + } + if (effective_policies_.allow_uri_forwarding.value_or(true) && + IsRemoteOpenUrlSupported()) { + host_capabilities_.append(" "); + host_capabilities_.append(protocol::kRemoteOpenUrlCapability); + } // Create the object that controls the screen resolution. screen_controls_ = desktop_environment_->CreateScreenControls(); @@ -571,8 +589,8 @@ connection_->set_input_stub(&disable_input_filter_); input_tracker_.set_input_stub(input_injector_.get()); - if (desktop_environment_options_.clipboard_size().has_value()) { - int max_size = desktop_environment_options_.clipboard_size().value(); + if (effective_policies_.clipboard_size_bytes.has_value()) { + int max_size = *effective_policies_.clipboard_size_bytes; client_clipboard_filter_.set_max_size(max_size); host_clipboard_filter_.set_max_size(max_size); @@ -727,8 +745,7 @@ << "; error = " << ErrorCodeToString(error); // Ignore any further callbacks. - client_session_control_weak_factory_.InvalidateWeakPtrs(); - client_session_events_weak_factory_.InvalidateWeakPtrs(); + weak_factory_.InvalidateWeakPtrs(); // If the client never authenticated then the session failed. if (!is_authenticated_) { @@ -984,20 +1001,13 @@ mouse_clamping_filter_.set_output_offset(origin); } -void ClientSession::OnLocalPoliciesChanged(const SessionPolicies& policies) { - // TODO: crbug.com/359977809 - add a test for overridden local policies. - if (local_session_policies_overridden_) { - return; - } - if (policies != effective_policies_) { - // Update `effective_policies_` anyway so that tests can check the latest - // known policies. - effective_policies_ = policies; - HOST_LOG << "Effective policies have changed. Terminating session."; - // TODO: crbug.com/359977809 - create a new error code for session policy - // changed. - DisconnectSession(ErrorCode::HOST_CONFIGURATION_ERROR); - } +void ClientSession::OnLocalSessionPoliciesChanged( + const SessionPolicies& new_policies) { + DCHECK(local_session_policy_update_subscription_); + HOST_LOG << "Effective policies have changed. Terminating session."; + // TODO: crbug.com/359977809 - create a new error code for session policy + // changed. + DisconnectSession(ErrorCode::HOST_CONFIGURATION_ERROR); } void ClientSession::OnVideoSizeChanged(protocol::VideoStream* video_stream,
diff --git a/remoting/host/client_session.h b/remoting/host/client_session.h index 530073a1..6275a66 100644 --- a/remoting/host/client_session.h +++ b/remoting/host/client_session.h
@@ -11,6 +11,7 @@ #include <string> #include <vector> +#include "base/callback_list.h" #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" @@ -22,6 +23,7 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "remoting/base/constants.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/base/session_policies.h" #include "remoting/host/base/desktop_environment_options.h" #include "remoting/host/client_session_control.h" @@ -127,7 +129,7 @@ const DesktopEnvironmentOptions& desktop_environment_options, scoped_refptr<protocol::PairingRegistry> pairing_registry, const std::vector<raw_ptr<HostExtension, VectorExperimental>>& extensions, - const SessionPolicies& local_policies); + const LocalSessionPoliciesProvider* local_session_policies_provider); ClientSession(const ClientSession&) = delete; ClientSession& operator=(const ClientSession&) = delete; @@ -225,13 +227,13 @@ // Public for tests. void UpdateMouseClampingFilterOffset(); - void OnLocalPoliciesChanged(const SessionPolicies& policies); - const SessionPolicies& effective_policies_for_tests() const { return effective_policies_; } private: + void OnLocalSessionPoliciesChanged(const SessionPolicies& new_policies); + // Creates a proxy for sending clipboard events to the client. std::unique_ptr<protocol::ClipboardStub> CreateClipboardProxy(); @@ -441,22 +443,18 @@ SessionPolicies effective_policies_; - // False indicates that `effective_policies_` comes from the local policies. - // True indicates that it has been overridden by another source of session - // policies. - // TODO: crbug.com/359977809 - implement session policies overriding with the - // policies provided by the authenticator. - bool local_session_policies_overridden_ = false; + raw_ptr<const LocalSessionPoliciesProvider> local_session_policies_provider_; + + // If `effective_policies` does not come from local session policies, the + // subscription will be null and OnLocalSessionPoliciesChanged() will never + // be called. + base::CallbackListSubscription local_session_policy_update_subscription_; SEQUENCE_CHECKER(sequence_checker_); // Used to disable callbacks to |this| once DisconnectSession() has been // called. - base::WeakPtrFactory<ClientSessionControl> - client_session_control_weak_factory_{this}; - - base::WeakPtrFactory<ClientSessionEvents> client_session_events_weak_factory_{ - this}; + base::WeakPtrFactory<ClientSession> weak_factory_{this}; }; } // namespace remoting
diff --git a/remoting/host/client_session_unittest.cc b/remoting/host/client_session_unittest.cc index 483cf89..89421b72 100644 --- a/remoting/host/client_session_unittest.cc +++ b/remoting/host/client_session_unittest.cc
@@ -28,6 +28,7 @@ #include "build/build_config.h" #include "remoting/base/auto_thread_task_runner.h" #include "remoting/base/constants.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/base/session_policies.h" #include "remoting/codec/video_encoder_verbatim.h" #include "remoting/host/desktop_environment.h" @@ -65,6 +66,7 @@ using testing::_; using testing::AtLeast; using testing::Eq; +using testing::Not; using testing::ReturnRef; using testing::StrictMock; @@ -223,6 +225,8 @@ std::vector<protocol::MouseEvent> mouse_events_; std::vector<protocol::ClipboardEvent> clipboard_events_; + LocalSessionPoliciesProvider local_session_policies_provider_; + // ClientSession instance under test. std::unique_ptr<ClientSession> client_session_; @@ -250,6 +254,8 @@ task_environment_.GetMainThreadTaskRunner()); desktop_environment_options_ = DesktopEnvironmentOptions::CreateDefault(); + local_session_policies_provider_.set_local_policies(kInitialLocalPolicies); + // Suppress spammy "uninteresting call" logs. EXPECT_CALL(client_stub_, SetCursorShape(_)).Times(testing::AnyNumber()); } @@ -283,7 +289,7 @@ client_session_ = std::make_unique<ClientSession>( &session_event_handler_, std::move(connection), desktop_environment_factory_.get(), desktop_environment_options_, nullptr, - extensions_, kInitialLocalPolicies); + extensions_, &local_session_policies_provider_); } void ClientSessionTest::CreateClientSession() { @@ -480,7 +486,7 @@ ConnectClientSession(); EXPECT_TRUE(connection_->is_connected()); - client_session_->OnLocalPoliciesChanged(kInitialLocalPolicies); + local_session_policies_provider_.set_local_policies(kInitialLocalPolicies); EXPECT_TRUE(connection_->is_connected()); } @@ -490,7 +496,7 @@ ConnectClientSession(); EXPECT_TRUE(connection_->is_connected()); - client_session_->OnLocalPoliciesChanged( + local_session_policies_provider_.set_local_policies( {.maximum_session_duration = base::Hours(23)}); EXPECT_FALSE(connection_->is_connected()); } @@ -509,6 +515,40 @@ EXPECT_FALSE(connection_->is_connected()); } +TEST_F(ClientSessionTest, + EffectivePoliciesImplicitlyAllowFileTransfer_HasCapability) { + local_session_policies_provider_.set_local_policies({}); + EXPECT_CALL( + client_stub_, + SetCapabilities(IncludesCapabilities(protocol::kFileTransferCapability))); + + CreateClientSession(); + ConnectClientSession(); +} + +TEST_F(ClientSessionTest, + EffectivePoliciesExplicitlyAllowFileTransfer_HasCapability) { + local_session_policies_provider_.set_local_policies( + {.allow_file_transfer = true}); + EXPECT_CALL( + client_stub_, + SetCapabilities(IncludesCapabilities(protocol::kFileTransferCapability))); + + CreateClientSession(); + ConnectClientSession(); +} + +TEST_F(ClientSessionTest, + EffectivePoliciesDisallowFileTransfer_DoesNotHaveCapability) { + local_session_policies_provider_.set_local_policies( + {.allow_file_transfer = false}); + EXPECT_CALL(client_stub_, SetCapabilities(Not(IncludesCapabilities( + protocol::kFileTransferCapability)))); + + CreateClientSession(); + ConnectClientSession(); +} + TEST_F(ClientSessionTest, MultiMonMouseMove) { CreateClientSession(); ConnectClientSession();
diff --git a/remoting/host/desktop_session_proxy.cc b/remoting/host/desktop_session_proxy.cc index f8c9040..db4e392 100644 --- a/remoting/host/desktop_session_proxy.cc +++ b/remoting/host/desktop_session_proxy.cc
@@ -165,16 +165,6 @@ result += protocol::kTouchEventsCapability; } - if (options_.enable_file_transfer()) { - result += " "; - result += protocol::kFileTransferCapability; - } - - if (options_.enable_remote_open_url() && IsRemoteOpenUrlSupported()) { - result += " "; - result += protocol::kRemoteOpenUrlCapability; - } - if (options_.enable_remote_webauthn()) { result += " "; result += protocol::kRemoteWebAuthnCapability;
diff --git a/remoting/host/it2me/it2me_host.cc b/remoting/host/it2me/it2me_host.cc index bb9e7c3..e96f1126 100644 --- a/remoting/host/it2me/it2me_host.cc +++ b/remoting/host/it2me/it2me_host.cc
@@ -21,6 +21,7 @@ #include "components/webrtc/thread_wrapper.h" #include "google_apis/gaia/gaia_auth_util.h" #include "remoting/base/auto_thread_task_runner.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/base/logging.h" #include "remoting/base/oauth_token_getter.h" #include "remoting/base/rsa_key_pair.h" @@ -360,22 +361,15 @@ chrome_os_enterprise_params_->terminate_upon_input); options.set_enable_curtaining( chrome_os_enterprise_params_->curtain_local_user_session); - options.set_enable_file_transfer( - chrome_os_enterprise_params_->allow_file_transfer && - enterprise_file_transfer_allowed_); } #endif - if (max_clipboard_size_.has_value()) { - options.set_clipboard_size(max_clipboard_size_.value()); - } - // Create the host. host_ = std::make_unique<ChromotingHost>( desktop_environment_factory_.get(), std::move(session_manager), transport_context, host_context_->audio_task_runner(), - host_context_->video_encode_task_runner(), options); - host_->SetLocalSessionPolicies(local_session_policies_); + host_context_->video_encode_task_runner(), options, + &local_session_policies_provider_); host_->status_monitor()->AddStatusObserver(this); host_status_logger_ = std::make_unique<HostStatusLogger>( host_->status_monitor(), log_to_server_.get()); @@ -475,16 +469,6 @@ remote_support_connections_allowed_ = policies.FindBool(GetRemoteSupportPolicyKey()).value_or(true); -#if BUILDFLAG(IS_CHROMEOS_ASH) - enterprise_file_transfer_allowed_ = - policies - .FindBool(policy::key::kRemoteAccessHostAllowEnterpriseFileTransfer) - .value_or(false); - - HOST_LOG << "RemoteAccessHostEnterpriseFileTransfer capability is enabled: " - << enterprise_file_transfer_allowed_; -#endif - std::optional<bool> nat_policy_value = policies.FindBool(policy::key::kRemoteAccessHostFirewallTraversal); if (!nat_policy_value.has_value()) { @@ -525,14 +509,6 @@ UpdateHostUdpPortRangePolicy(*port_range_string); } - std::optional<int> max_clipboard_size = - policies.FindInt(policy::key::kRemoteAccessHostClipboardSizeBytes); - if (max_clipboard_size.has_value()) { - if (max_clipboard_size.value() >= 0) { - max_clipboard_size_ = max_clipboard_size.value(); - } - } - UpdateSessionPolicies(policies); } @@ -616,21 +592,34 @@ LOG(FATAL) << "Failed to parse local session policies."; } - local_session_policies_ = *local_session_policies; + // These are currently disallowed for IT2ME connections by default. + // TODO: yuweih - Figure out what should be done when we add SessionAuthz + // policies support for IT2ME. Given the current logic, these features can be + // enabled by SessionAuthz policies, which is not possible by local Chrome + // policies. + local_session_policies->allow_file_transfer = false; + local_session_policies->allow_uri_forwarding = false; #if BUILDFLAG(IS_CHROMEOS_ASH) || !defined(NDEBUG) if (chrome_os_enterprise_params_.has_value()) { - local_session_policies_.curtain_required = + local_session_policies->curtain_required = chrome_os_enterprise_params_->curtain_local_user_session; - local_session_policies_.allow_file_transfer = + +#if BUILDFLAG(IS_CHROMEOS_ASH) + bool enterprise_file_transfer_allowed = + platform_policies + .FindBool(policy::key::kRemoteAccessHostAllowEnterpriseFileTransfer) + .value_or(false); +#else + bool enterprise_file_transfer_allowed = false; +#endif + local_session_policies->allow_file_transfer = chrome_os_enterprise_params_->allow_file_transfer && - enterprise_file_transfer_allowed_; + enterprise_file_transfer_allowed; } #endif - if (host_) { - host_->SetLocalSessionPolicies(local_session_policies_); - } + local_session_policies_provider_.set_local_policies(*local_session_policies); } void It2MeHost::SetState(It2MeHostState state, ErrorCode error_code) {
diff --git a/remoting/host/it2me/it2me_host.h b/remoting/host/it2me/it2me_host.h index 146c7a2c..f8d4923 100644 --- a/remoting/host/it2me/it2me_host.h +++ b/remoting/host/it2me/it2me_host.h
@@ -15,8 +15,8 @@ #include "base/memory/weak_ptr.h" #include "base/values.h" #include "build/chromeos_buildflags.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/base/port_range.h" -#include "remoting/base/session_policies.h" #include "remoting/host/chromeos/chromeos_enterprise_params.h" #include "remoting/host/host_status_observer.h" #include "remoting/host/it2me/it2me_confirmation_dialog.h" @@ -238,6 +238,7 @@ std::unique_ptr<HostStatusLogger> host_status_logger_; std::unique_ptr<DesktopEnvironmentFactory> desktop_environment_factory_; std::unique_ptr<HostEventLogger> host_event_logger_; + LocalSessionPoliciesProvider local_session_policies_provider_; #if BUILDFLAG(IS_CHROMEOS_ASH) std::unique_ptr<HostEventReporter> host_event_reporter_; HostEventReporterFactory host_event_reporter_factory_; @@ -271,20 +272,12 @@ // The host port range policy setting. PortRange udp_port_range_; - // Stores the clipboard size policy value. - std::optional<size_t> max_clipboard_size_; - // Stores the remote support connections allowed policy value. bool remote_support_connections_allowed_ = true; - // Stores whether enterprise file transfer is allowed by policy. - bool enterprise_file_transfer_allowed_ = false; - // Tracks the JID of the remote user when in a connecting state. std::string connecting_jid_; - SessionPolicies local_session_policies_; - base::WeakPtrFactory<It2MeHost> weak_factory_{this}; };
diff --git a/remoting/host/it2me/it2me_host_unittest.cc b/remoting/host/it2me/it2me_host_unittest.cc index 43e9e40..3c231d5 100644 --- a/remoting/host/it2me/it2me_host_unittest.cc +++ b/remoting/host/it2me/it2me_host_unittest.cc
@@ -25,6 +25,7 @@ #include "components/policy/policy_constants.h" #include "net/base/network_change_notifier.h" #include "remoting/base/auto_thread_task_runner.h" +#include "remoting/base/session_policies.h" #include "remoting/host/chromeos/chromeos_enterprise_params.h" #include "remoting/host/chromeos/features.h" #include "remoting/host/chromoting_host.h" @@ -236,6 +237,10 @@ ChromotingHost* GetHost() { return it2me_host_->host_.get(); } + const SessionPolicies& get_local_session_policies() const { + return it2me_host_->local_session_policies_provider_.get_local_policies(); + } + // Configuration values used by StartHost(); std::optional<ChromeOsEnterpriseParams> enterprise_params_; std::optional<std::string> authorized_helper_; @@ -872,6 +877,18 @@ ASSERT_EQ(ErrorCode::DISALLOWED_BY_POLICY, last_error_code_); } +TEST_F(It2MeHostTest, FileTransferDisallowedByDefault) { + StartHost(); + + EXPECT_FALSE(*get_local_session_policies().allow_file_transfer); +} + +TEST_F(It2MeHostTest, UriForwardingDisallowedByDefault) { + StartHost(); + + EXPECT_FALSE(*get_local_session_policies().allow_uri_forwarding); +} + #if BUILDFLAG(IS_CHROMEOS_ASH) TEST_F(It2MeHostTest, ConnectRespectsSuppressDialogsParameter) { StartHost(ChromeOsEnterpriseParams{.suppress_user_dialogs = true}); @@ -918,7 +935,7 @@ StartHost(ChromeOsEnterpriseParams{.allow_file_transfer = true}); - EXPECT_TRUE(GetHost()->desktop_environment_options().enable_file_transfer()); + EXPECT_TRUE(*get_local_session_policies().allow_file_transfer); } TEST_F(It2MeHostTest, AllowEnterpriseFileTransferWithPolicyDisabled) { @@ -927,7 +944,7 @@ StartHost(ChromeOsEnterpriseParams{.allow_file_transfer = true}); - EXPECT_FALSE(GetHost()->desktop_environment_options().enable_file_transfer()); + EXPECT_FALSE(*get_local_session_policies().allow_file_transfer); } TEST_F(It2MeHostTest, @@ -937,7 +954,7 @@ StartHost(/*enterprise_params=*/std::nullopt); - EXPECT_FALSE(GetHost()->desktop_environment_options().enable_file_transfer()); + EXPECT_FALSE(*get_local_session_policies().allow_file_transfer); } TEST_F(It2MeHostTest, AllowEnterpriseFileTransferWithPolicyNotSet) { @@ -945,13 +962,13 @@ StartHost(ChromeOsEnterpriseParams{.allow_file_transfer = true}); - EXPECT_FALSE(GetHost()->desktop_environment_options().enable_file_transfer()); + EXPECT_FALSE(*get_local_session_policies().allow_file_transfer); } TEST_F(It2MeHostTest, EnableFileTransferDefaultsToFalse) { StartHost(/*enterprise_params=*/std::nullopt); - EXPECT_FALSE(GetHost()->desktop_environment_options().enable_file_transfer()); + EXPECT_FALSE(*get_local_session_policies().allow_file_transfer); } TEST_F(It2MeHostTest,
diff --git a/remoting/host/it2me_desktop_environment.cc b/remoting/host/it2me_desktop_environment.cc index 6ff76e1..3b4aabe 100644 --- a/remoting/host/it2me_desktop_environment.cc +++ b/remoting/host/it2me_desktop_environment.cc
@@ -98,10 +98,6 @@ std::string It2MeDesktopEnvironment::GetCapabilities() const { std::string capabilities = BasicDesktopEnvironment::GetCapabilities(); - if (desktop_environment_options().enable_file_transfer()) { - capabilities += " "; - capabilities += protocol::kFileTransferCapability; - } // TODO: joedow - Move MultiStream capability to a shared base // class once all platforms and connection modes support it.
diff --git a/remoting/host/it2me_desktop_environment_unittest.cc b/remoting/host/it2me_desktop_environment_unittest.cc index 7adbef0..34e1b836 100644 --- a/remoting/host/it2me_desktop_environment_unittest.cc +++ b/remoting/host/it2me_desktop_environment_unittest.cc
@@ -190,34 +190,5 @@ #endif // BUILDFLAG(IS_CHROMEOS) }; -#if BUILDFLAG(IS_CHROMEOS) -TEST_F(It2MeDesktopEnvironmentTest, - ShouldHaveFileTransferCapabilitiesWhenEnabled) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kEnableCrdFileTransferForKiosk); - DesktopEnvironmentOptions options(default_options()); - std::string expected_capabilities(" "); - expected_capabilities += protocol::kFileTransferCapability; - - options.set_enable_file_transfer(true); - auto desktop_environment = Create(options); - - EXPECT_THAT(desktop_environment->GetCapabilities(), - testing::HasSubstr(expected_capabilities)); -} - -TEST_F(It2MeDesktopEnvironmentTest, - ShouldNotHaveFileTransferCapabilitiesWhenDisabled) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature(features::kEnableCrdFileTransferForKiosk); - DesktopEnvironmentOptions options(default_options()); - - options.set_enable_file_transfer(false); - auto desktop_environment = Create(options); - - EXPECT_THAT(desktop_environment->GetCapabilities(), testing::HasSubstr("")); -} -#endif // BUILDFLAG(IS_CHROMEOS) - } // namespace } // namespace remoting
diff --git a/remoting/host/me2me_desktop_environment.cc b/remoting/host/me2me_desktop_environment.cc index 8c7a002e..b91e039b 100644 --- a/remoting/host/me2me_desktop_environment.cc +++ b/remoting/host/me2me_desktop_environment.cc
@@ -92,11 +92,6 @@ } capabilities += protocol::kRateLimitResizeRequests; - if (desktop_environment_options().enable_file_transfer()) { - capabilities += " "; - capabilities += protocol::kFileTransferCapability; - } - #if BUILDFLAG(IS_WIN) capabilities += " "; capabilities += protocol::kSendAttentionSequenceAction; @@ -108,12 +103,6 @@ } #endif // BUILDFLAG(IS_WIN) - if (desktop_environment_options().enable_remote_open_url() && - IsRemoteOpenUrlSupported()) { - capabilities += " "; - capabilities += protocol::kRemoteOpenUrlCapability; - } - if (desktop_environment_options().enable_remote_webauthn()) { capabilities += " "; capabilities += protocol::kRemoteWebAuthnCapability;
diff --git a/remoting/host/mojom/desktop_session.mojom b/remoting/host/mojom/desktop_session.mojom index 13209b4..ae0f6e23 100644 --- a/remoting/host/mojom/desktop_session.mojom +++ b/remoting/host/mojom/desktop_session.mojom
@@ -258,20 +258,9 @@ // True if the session should be terminated when local input is detected. bool terminate_upon_input; - // True if this host has file transfer enabled. - bool enable_file_transfer; - - // True if this host has the remote open URL feature enabled. - bool enable_remote_open_url; - // True if this host has the remote WebAuthn feature enabled. bool enable_remote_webauthn; - // If set, this value is used to constrain the amount of data that can be - // transferred using ClipboardEvents. A value of 0 will effectively disable - // clipboard sharing. - UInt32? clipboard_size; - // The DesktopCaptureOptions to initialize DesktopCapturer. DesktopCaptureOptions desktop_capture_options; };
diff --git a/remoting/host/mojom/remoting_mojom_traits.cc b/remoting/host/mojom/remoting_mojom_traits.cc index 2ea9b8c..c6a46a9 100644 --- a/remoting/host/mojom/remoting_mojom_traits.cc +++ b/remoting/host/mojom/remoting_mojom_traits.cc
@@ -91,18 +91,8 @@ out_options->set_enable_user_interface(data_view.enable_user_interface()); out_options->set_enable_notifications(data_view.enable_notifications()); out_options->set_terminate_upon_input(data_view.terminate_upon_input()); - out_options->set_enable_file_transfer(data_view.enable_file_transfer()); - out_options->set_enable_remote_open_url(data_view.enable_remote_open_url()); out_options->set_enable_remote_webauthn(data_view.enable_remote_webauthn()); - std::optional<uint32_t> clipboard_size; - if (!data_view.ReadClipboardSize(&clipboard_size)) { - return false; - } - if (clipboard_size.has_value()) { - out_options->set_clipboard_size(std::move(clipboard_size)); - } - if (!data_view.ReadDesktopCaptureOptions( out_options->desktop_capture_options())) { return false;
diff --git a/remoting/host/mojom/remoting_mojom_traits.h b/remoting/host/mojom/remoting_mojom_traits.h index 51ff498..b2c5bf1 100644 --- a/remoting/host/mojom/remoting_mojom_traits.h +++ b/remoting/host/mojom/remoting_mojom_traits.h
@@ -143,33 +143,11 @@ return options.terminate_upon_input(); } - static bool enable_file_transfer( - const ::remoting::DesktopEnvironmentOptions& options) { - return options.enable_file_transfer(); - } - - static bool enable_remote_open_url( - const ::remoting::DesktopEnvironmentOptions& options) { - return options.enable_remote_open_url(); - } - static bool enable_remote_webauthn( const ::remoting::DesktopEnvironmentOptions& options) { return options.enable_remote_webauthn(); } - static std::optional<uint32_t> clipboard_size( - const ::remoting::DesktopEnvironmentOptions& options) { - if (!options.clipboard_size().has_value()) { - return std::nullopt; - } - - size_t clipboard_size = options.clipboard_size().value(); - return base::IsValueInRangeForNumericType<int>(clipboard_size) - ? clipboard_size - : INT_MAX; - } - static const webrtc::DesktopCaptureOptions& desktop_capture_options( const ::remoting::DesktopEnvironmentOptions& options) { return *options.desktop_capture_options();
diff --git a/remoting/host/remoting_me2me_host.cc b/remoting/host/remoting_me2me_host.cc index c5f3d1e..7c72e73 100644 --- a/remoting/host/remoting_me2me_host.cc +++ b/remoting/host/remoting_me2me_host.cc
@@ -55,6 +55,7 @@ #include "remoting/base/cpu_utils.h" #include "remoting/base/host_settings.h" #include "remoting/base/is_google_email.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/base/logging.h" #include "remoting/base/oauth_token_getter_impl.h" #include "remoting/base/oauth_token_getter_proxy.h" @@ -354,11 +355,8 @@ bool OnCurtainPolicyUpdate(const base::Value::Dict& policies); bool OnPairingPolicyUpdate(const base::Value::Dict& policies); bool OnGnubbyAuthPolicyUpdate(const base::Value::Dict& policies); - bool OnFileTransferPolicyUpdate(const base::Value::Dict& policies); bool OnEnableUserInterfacePolicyUpdate(const base::Value::Dict& policies); bool OnAllowRemoteAccessConnections(const base::Value::Dict& policies); - bool OnMaxClipboardSizePolicyUpdate(const base::Value::Dict& policies); - bool OnUrlForwardingPolicyUpdate(const base::Value::Dict& policies); bool OnAllowPinAuthenticationUpdate(const base::Value::Dict& policies); void InitializeSignaling(); @@ -423,7 +421,6 @@ std::string service_account_email_; base::Value::Dict config_; std::string host_owner_; - std::optional<size_t> max_clipboard_size_; std::unique_ptr<PolicyWatcher> policy_watcher_; PolicyState policy_state_ = POLICY_INITIALIZING; @@ -439,7 +436,7 @@ std::optional<bool> allow_pin_auth_; bool is_corp_user_ = false; bool require_session_authorization_ = false; - SessionPolicies local_session_policies_; + LocalSessionPoliciesProvider local_session_policies_provider_; DesktopEnvironmentOptions desktop_environment_options_; bool security_key_auth_policy_enabled_ = false; @@ -1267,7 +1264,7 @@ OnPolicyError(); return; } - local_session_policies_ = *local_session_policies; + local_session_policies_provider_.set_local_policies(*local_session_policies); bool restart_required = false; restart_required |= OnClientDomainListPolicyUpdate(policies); @@ -1280,11 +1277,8 @@ restart_required |= OnUdpPortPolicyUpdate(policies); restart_required |= OnPairingPolicyUpdate(policies); restart_required |= OnGnubbyAuthPolicyUpdate(policies); - restart_required |= OnFileTransferPolicyUpdate(policies); restart_required |= OnEnableUserInterfacePolicyUpdate(policies); restart_required |= OnAllowRemoteAccessConnections(policies); - restart_required |= OnMaxClipboardSizePolicyUpdate(policies); - restart_required |= OnUrlForwardingPolicyUpdate(policies); restart_required |= OnAllowPinAuthenticationUpdate(policies); policy_state_ = POLICY_LOADED; @@ -1295,8 +1289,6 @@ } else if (state_ == HOST_STARTED) { if (restart_required) { RestartHost(kHostOfflineReasonPolicyChangeRequiresRestart); - } else { - host_->SetLocalSessionPolicies(local_session_policies_); } } } @@ -1597,56 +1589,6 @@ return true; } -bool HostProcess::OnFileTransferPolicyUpdate( - const base::Value::Dict& policies) { - DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); - - std::optional<bool> file_transfer_enabled = - policies.FindBool(policy::key::kRemoteAccessHostAllowFileTransfer); - if (!file_transfer_enabled.has_value()) { - return false; - } - - desktop_environment_options_.set_enable_file_transfer( - file_transfer_enabled.value()); - - if (file_transfer_enabled.value()) { - HOST_LOG << "Policy enables file transfer."; - } else { - HOST_LOG << "Policy disables file transfer."; - } - - // Restart required. - return true; -} - -bool HostProcess::OnUrlForwardingPolicyUpdate( - const base::Value::Dict& policies) { - DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); - - std::optional<bool> url_forwarding_enabled = - policies.FindBool(policy::key::kRemoteAccessHostAllowUrlForwarding); - if (!url_forwarding_enabled.has_value()) { - return false; - } - - // Always enable remote open URL when the platform supports it and the policy - // does not disable it. There is an additional IsRemoteOpenUrlSupported() - // check which ensures the capability won't be advertised if the machine is - // not properly configured. - desktop_environment_options_.set_enable_remote_open_url( - url_forwarding_enabled.value()); - - if (url_forwarding_enabled.value()) { - HOST_LOG << "Policy allows URL forwarding."; - } else { - HOST_LOG << "Policy disallows URL forwarding."; - } - - // Restart required. - return true; -} - bool HostProcess::OnAllowPinAuthenticationUpdate( const base::Value::Dict& policies) { DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); @@ -1699,29 +1641,6 @@ return true; } -bool HostProcess::OnMaxClipboardSizePolicyUpdate( - const base::Value::Dict& policies) { - DCHECK(context_->network_task_runner()->BelongsToCurrentThread()); - - std::optional<int> max_clipboard_size = - policies.FindInt(policy::key::kRemoteAccessHostClipboardSizeBytes); - if (!max_clipboard_size) { - return false; - } - - if (*max_clipboard_size >= 0) { - max_clipboard_size_ = *max_clipboard_size; - HOST_LOG << "Policy sets maximum clipboard size to " - << max_clipboard_size_.value() << " bytes."; - } else { - max_clipboard_size_.reset(); - HOST_LOG << "Policy does not set a maximum clipboard size."; - } - - // Restart required. - return true; -} - bool HostProcess::OnAllowRemoteAccessConnections( const base::Value::Dict& policies) { // Returns false: never restart the host after this policy update. @@ -1887,20 +1806,11 @@ desktop_environment_options_.set_enable_remote_webauthn(is_corp_user_); #endif - if (max_clipboard_size_.has_value()) { - desktop_environment_options_.set_clipboard_size( - max_clipboard_size_.value()); - } else if (desktop_environment_options_.clipboard_size().has_value()) { - // If we've transitioned from having a policy value to no value then make - // sure the value stored in desktop_environment_options has been cleared. - desktop_environment_options_.set_clipboard_size(std::optional<size_t>()); - } - host_ = std::make_unique<ChromotingHost>( desktop_environment_factory_.get(), std::move(session_manager), transport_context, context_->audio_task_runner(), - context_->video_encode_task_runner(), desktop_environment_options_); - host_->SetLocalSessionPolicies(local_session_policies_); + context_->video_encode_task_runner(), desktop_environment_options_, + &local_session_policies_provider_); if (security_key_auth_policy_enabled_ && security_key_extension_supported_) { host_->AddExtension(
diff --git a/remoting/host/session_policies_from_dict.cc b/remoting/host/session_policies_from_dict.cc index fe86cee..b57846a5 100644 --- a/remoting/host/session_policies_from_dict.cc +++ b/remoting/host/session_policies_from_dict.cc
@@ -4,6 +4,8 @@ #include "remoting/host/session_policies_from_dict.h" +#include <optional> + #include "base/logging.h" #include "base/time/time.h" #include "build/build_config.h" @@ -43,9 +45,18 @@ std::optional<bool> allow_firewall_traversal = dict.FindBool(policy::key::kRemoteAccessHostFirewallTraversal); + std::optional<int> clipboard_size_bytes_value = + dict.FindInt(policy::key::kRemoteAccessHostClipboardSizeBytes); + std::optional<size_t> clipboard_size_bytes; + // The default policy dict sets RemoteAccessHostClipboardSizeBytes + // to -1, so we need to treat negative values as unset values. + if (clipboard_size_bytes_value.has_value() && + *clipboard_size_bytes_value >= 0) { + clipboard_size_bytes = *clipboard_size_bytes_value; + } + return SessionPolicies{ - .clipboard_size_bytes = - dict.FindInt(policy::key::kRemoteAccessHostClipboardSizeBytes), + .clipboard_size_bytes = clipboard_size_bytes, .allow_stun_connections = allow_firewall_traversal, // Relayed connection is not allowed if RemoteAccessHostFirewallTraversal // is false. See:
diff --git a/remoting/host/session_policies_from_dict_unittest.cc b/remoting/host/session_policies_from_dict_unittest.cc index 8c7a432..a69077d 100644 --- a/remoting/host/session_policies_from_dict_unittest.cc +++ b/remoting/host/session_policies_from_dict_unittest.cc
@@ -59,6 +59,11 @@ } #endif +base::Value::Dict GetPolicyDictWithClipboardSize(int clipboard_size) { + return GetFullSessionPolicyDict().Clone().Set( + policy::key::kRemoteAccessHostClipboardSizeBytes, clipboard_size); +} + } // namespace TEST(SessionPoliciesFromDict, EmptyDict_CreatesEmptyPolicies) { @@ -128,4 +133,18 @@ EXPECT_EQ(SessionPoliciesFromDict(policy_dict), std::nullopt); } +TEST(SessionPoliciesFromDict, NegativeClipboardSize_FieldIsNullopt) { + SessionPolicies expected_policies = kFullSessionPolicies; + expected_policies.clipboard_size_bytes.reset(); + EXPECT_EQ(SessionPoliciesFromDict(GetPolicyDictWithClipboardSize(-1)), + expected_policies); +} + +TEST(SessionPoliciesFromDict, ZeroClipboardSize_FieldIsZero) { + SessionPolicies expected_policies = kFullSessionPolicies; + expected_policies.clipboard_size_bytes = 0; + EXPECT_EQ(SessionPoliciesFromDict(GetPolicyDictWithClipboardSize(0)), + expected_policies); +} + } // namespace remoting
diff --git a/remoting/test/it2me_standalone_host.cc b/remoting/test/it2me_standalone_host.cc index b051da1..91f6c07 100644 --- a/remoting/test/it2me_standalone_host.cc +++ b/remoting/test/it2me_standalone_host.cc
@@ -95,7 +95,7 @@ &handler_, std::unique_ptr<protocol::ConnectionToClient>(&connection_), &factory_, options, scoped_refptr<protocol::PairingRegistry>(), std::vector<raw_ptr<HostExtension, VectorExperimental>>(), - SessionPolicies()); + &local_session_policies_provider_); session_->OnConnectionAuthenticated(); session_->OnConnectionChannelsConnected(); session_->CreateMediaStreams();
diff --git a/remoting/test/it2me_standalone_host.h b/remoting/test/it2me_standalone_host.h index b430cf0..51ae747f 100644 --- a/remoting/test/it2me_standalone_host.h +++ b/remoting/test/it2me_standalone_host.h
@@ -12,6 +12,7 @@ #include "base/run_loop.h" #include "base/test/task_environment.h" #include "base/timer/timer.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/host/host_mock_objects.h" #include "remoting/host/it2me_desktop_environment.h" #include "remoting/protocol/fake_connection_to_client.h" @@ -48,6 +49,7 @@ std::unique_ptr<ChromotingHostContext> context_; scoped_refptr<AutoThreadTaskRunner> main_task_runner_; It2MeDesktopEnvironmentFactory factory_; + LocalSessionPoliciesProvider local_session_policies_provider_; protocol::FakeConnectionToClient connection_; std::string session_jid_; std::unique_ptr<protocol::SessionConfig> config_;
diff --git a/remoting/test/protocol_perftest.cc b/remoting/test/protocol_perftest.cc index 1a18f82..762b935 100644 --- a/remoting/test/protocol_perftest.cc +++ b/remoting/test/protocol_perftest.cc
@@ -23,6 +23,7 @@ #include "net/base/network_change_notifier.h" #include "net/test/test_data_directory.h" #include "net/url_request/url_request_context_getter.h" +#include "remoting/base/local_session_policies_provider.h" #include "remoting/base/rsa_key_pair.h" #include "remoting/client/audio/audio_player.h" #include "remoting/client/chromoting_client.h" @@ -313,7 +314,8 @@ desktop_environment_factory_.get(), std::move(session_manager), transport_context, host_thread_.task_runner(), encode_thread_.task_runner(), - DesktopEnvironmentOptions::CreateDefault()); + DesktopEnvironmentOptions::CreateDefault(), + &local_session_policies_provider_); base::FilePath certs_dir(net::GetTestCertsDirectory()); @@ -410,6 +412,7 @@ scoped_refptr<protocol::InputEventTimestampsSource> event_timestamp_source_; FakeCursorShapeStub cursor_shape_stub_; + LocalSessionPoliciesProvider local_session_policies_provider_; std::unique_ptr<protocol::CandidateSessionConfig> protocol_config_;
diff --git a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers_unittest.cc b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers_unittest.cc index 1693cde8..5a0fe9f 100644 --- a/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers_unittest.cc +++ b/sandbox/linux/seccomp-bpf-helpers/sigsys_handlers_unittest.cc
@@ -2,6 +2,11 @@ // 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 "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h" #include <linux/net.h>
diff --git a/sandbox/policy/features.cc b/sandbox/policy/features.cc index f4425b079c..0c85120a 100644 --- a/sandbox/policy/features.cc +++ b/sandbox/policy/features.cc
@@ -124,6 +124,11 @@ "WinSboxRestrictCoreSharingOnRenderer", base::FEATURE_DISABLED_BY_DEFAULT); +// Enables parallel process launching using the thread pool. +BASE_FEATURE(kWinSboxParallelProcessLaunch, + "WinSboxParallelProcessLaunch", + base::FEATURE_DISABLED_BY_DEFAULT); + // Creates an AppContainer policy without registering with the Windows firewall // service. See crbug.com/352720904 for details. BASE_FEATURE(kWinSboxACProfileWithoutFirewall, @@ -232,4 +237,9 @@ #endif // BUILDFLAG(IS_MAC) || BUILDFLAG(IS_FUCHSIA) } +#if BUILDFLAG(IS_WIN) +bool IsParallelLaunchEnabled() { + return base::FeatureList::IsEnabled(kWinSboxParallelProcessLaunch); +} +#endif // BUILDFLAG(IS_WIN) } // namespace sandbox::policy::features
diff --git a/sandbox/policy/features.h b/sandbox/policy/features.h index e0ccc80..5bad37b 100644 --- a/sandbox/policy/features.h +++ b/sandbox/policy/features.h
@@ -39,6 +39,7 @@ SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kWinSboxNoFakeGdiInit); SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE( kWinSboxRestrictCoreSharingOnRenderer); +SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kWinSboxParallelProcessLaunch); SANDBOX_POLICY_EXPORT BASE_DECLARE_FEATURE(kWinSboxACProfileWithoutFirewall); #endif // BUILDFLAG(IS_WIN) @@ -75,6 +76,10 @@ // calling ContentBrowserClient::ShouldSandboxNetworkService(). SANDBOX_POLICY_EXPORT bool IsNetworkSandboxEnabled(); +#if BUILDFLAG(IS_WIN) +// Returns whether parallel launching is enabled. +SANDBOX_POLICY_EXPORT bool IsParallelLaunchEnabled(); +#endif // BUILDFLAG(IS_WIN) } // namespace sandbox::policy::features #endif // SANDBOX_POLICY_FEATURES_H_
diff --git a/sandbox/policy/win/sandbox_win.cc b/sandbox/policy/win/sandbox_win.cc index d25dc43..451b3bc 100644 --- a/sandbox/policy/win/sandbox_win.cc +++ b/sandbox/policy/win/sandbox_win.cc
@@ -41,8 +41,8 @@ #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h" #include "base/task/sequenced_task_runner.h" +#include "base/task/thread_pool.h" #include "base/time/time.h" -#include "base/timer/elapsed_timer.h" #include "base/trace_event/trace_event.h" #include "base/win/iat_patch_function.h" #include "base/win/scoped_handle.h" @@ -100,59 +100,6 @@ "EnableCsrssLockdown", base::FEATURE_DISABLED_BY_DEFAULT); -// Helper to recording timing information during process creation. -class SandboxLaunchTimer { - public: - SandboxLaunchTimer() = default; - SandboxLaunchTimer(const SandboxLaunchTimer&) = delete; - SandboxLaunchTimer& operator=(const SandboxLaunchTimer&) = delete; - - // Call after the policy base object is created. - void OnPolicyCreated() { policy_created_ = timer_.Elapsed(); } - - // Call after the delegate has generated policy settings. - void OnPolicyGenerated() { policy_generated_ = timer_.Elapsed(); } - - // Call after CreateProcess() has returned a suspended process. - void OnProcessSpawned() { process_spawned_ = timer_.Elapsed(); } - - // Call after unsuspending the process. - void OnProcessResumed() { process_resumed_ = timer_.Elapsed(); } - - // Call once to record histograms for a successful process launch. - void RecordHistograms() { - // If these parameters change the histograms should be renamed. - // We're interested in the happy fast case so have a low maximum. - const auto kLowBound = base::Microseconds(5); - const auto kHighBound = base::Microseconds(100000); - const int kBuckets = 50; - - base::UmaHistogramCustomMicrosecondsTimes( - "Process.Sandbox.StartSandboxedWin.CreatePolicyDuration", - policy_created_, kLowBound, kHighBound, kBuckets); - base::UmaHistogramCustomMicrosecondsTimes( - "Process.Sandbox.StartSandboxedWin.GeneratePolicyDuration", - policy_generated_ - policy_created_, kLowBound, kHighBound, kBuckets); - base::UmaHistogramCustomMicrosecondsTimes( - "Process.Sandbox.StartSandboxedWin.SpawnTargetDuration", - process_spawned_ - policy_generated_, kLowBound, kHighBound, kBuckets); - base::UmaHistogramCustomMicrosecondsTimes( - "Process.Sandbox.StartSandboxedWin.PostSpawnTargetDuration", - process_resumed_ - process_spawned_, kLowBound, kHighBound, kBuckets); - base::UmaHistogramCustomMicrosecondsTimes( - "Process.Sandbox.StartSandboxedWin.TotalDuration", process_resumed_, - kLowBound, kHighBound, kBuckets); - } - - private: - // `timer_` starts when this object is created. - const base::ElapsedTimer timer_; - base::TimeDelta policy_created_; - base::TimeDelta policy_generated_; - base::TimeDelta process_spawned_; - base::TimeDelta process_resumed_; -}; - // Adds the policy rules to allow read-only access to the windows system fonts // directory, and any subdirectories. Used by PDF renderers. bool AddWindowsFontsDir(TargetConfig* config) { @@ -749,6 +696,30 @@ } // namespace +void SandboxLaunchTimer::RecordHistograms() { + // If these parameters change the histograms should be renamed. + // We're interested in the happy fast case so have a low maximum. + const auto kLowBound = base::Microseconds(5); + const auto kHighBound = base::Microseconds(100000); + const int kBuckets = 50; + + base::UmaHistogramCustomMicrosecondsTimes( + "Process.Sandbox.StartSandboxedWin.CreatePolicyDuration", policy_created_, + kLowBound, kHighBound, kBuckets); + base::UmaHistogramCustomMicrosecondsTimes( + "Process.Sandbox.StartSandboxedWin.GeneratePolicyDuration", + policy_generated_ - policy_created_, kLowBound, kHighBound, kBuckets); + base::UmaHistogramCustomMicrosecondsTimes( + "Process.Sandbox.StartSandboxedWin.SpawnTargetDuration", + process_spawned_ - policy_generated_, kLowBound, kHighBound, kBuckets); + base::UmaHistogramCustomMicrosecondsTimes( + "Process.Sandbox.StartSandboxedWin.PostSpawnTargetDuration", + process_resumed_ - process_spawned_, kLowBound, kHighBound, kBuckets); + base::UmaHistogramCustomMicrosecondsTimes( + "Process.Sandbox.StartSandboxedWin.TotalDuration", process_resumed_, + kLowBound, kHighBound, kBuckets); +} + // static ResultCode SandboxWin::SetJobLevel(Sandbox sandbox_type, JobLevel job_level, @@ -891,13 +862,56 @@ return false; } +class BrokerServicesDelegateImpl : public BrokerServicesDelegate { + public: + bool ParallelLaunchEnabled() override { + return features::IsParallelLaunchEnabled(); + } + + void ParallelLaunchPostTaskAndReplyWithResult( + const base::Location& from_here, + base::OnceCallback<CreateTargetResult()> task, + base::OnceCallback<void(CreateTargetResult)> reply) override { + base::ThreadPool::PostTaskAndReplyWithResult( + from_here, + {base::MayBlock(), base::TaskPriority::USER_BLOCKING, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, + std::move(task), std::move(reply)); + } + + void BeforeTargetProcessCreateOnCreationThread( + const void* trace_id) override { + int active_threads = ++creation_threads_in_use_; + base::UmaHistogramCounts100("MPArch.ChildProcessLaunchActivelyInParallel", + active_threads); + + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("startup", "TargetProcess::Create", + trace_id); + } + + void AfterTargetProcessCreateOnCreationThread(const void* trace_id, + DWORD process_id) override { + creation_threads_in_use_--; + TRACE_EVENT_NESTABLE_ASYNC_END1("startup", "TargetProcess::Create", + trace_id, "pid", process_id); + } + + private: + // When parallel launching is enabled, target creation will happen on the + // thread pool. This is atomic to keep track of the number of threads that are + // currently creating processes. + std::atomic<int> creation_threads_in_use_ = 0; +}; + // static bool SandboxWin::InitBrokerServices(BrokerServices* broker_services) { // TODO(abarth): DCHECK(CalledOnValidThread()); // See <http://b/1287166>. DCHECK(broker_services); DCHECK(!g_broker_services); - ResultCode init_result = broker_services->Init(); + + ResultCode init_result = + broker_services->Init(std::make_unique<BrokerServicesDelegateImpl>()); g_broker_services = broker_services; // In non-official builds warn about dangerous uses of DuplicateHandle. This @@ -980,14 +994,18 @@ const base::CommandLine& cmd_line, const base::HandlesToInheritVector& handles_to_inherit, SandboxDelegate* delegate, - base::Process* process) { + StartSandboxedProcessCallback result_callback) { SandboxLaunchTimer timer; // Avoid making a policy if we won't use it. if (IsUnsandboxedProcess(delegate->GetSandboxType(), cmd_line, *base::CommandLine::ForCurrentProcess())) { - return LaunchWithoutSandbox(cmd_line, handles_to_inherit, delegate, - process); + base::Process process; + ResultCode result = + LaunchWithoutSandbox(cmd_line, handles_to_inherit, delegate, &process); + DWORD last_error = GetLastError(); + std::move(result_callback).Run(std::move(process), last_error, result); + return SBOX_ALL_OK; } auto policy = g_broker_services->CreatePolicy(delegate->GetSandboxTag()); @@ -999,27 +1017,51 @@ return result; timer.OnPolicyGenerated(); - TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); + int64_t trace_event_id = timer.GetStartTimeInMicroseconds(); + TRACE_EVENT_NESTABLE_ASYNC_BEGIN0( + "startup", "StartProcessWithAccess::LAUNCHPROCESS", trace_event_id); - PROCESS_INFORMATION temp_process_info = {}; - DWORD last_error = ERROR_SUCCESS; - result = g_broker_services->SpawnTarget( + result = g_broker_services->SpawnTargetAsync( cmd_line.GetProgram().value().c_str(), - cmd_line.GetCommandLineString().c_str(), std::move(policy), &last_error, - &temp_process_info); + cmd_line.GetCommandLineString().c_str(), std::move(policy), + base::BindOnce(&SandboxWin::FinishStartSandboxedProcess, delegate, + std::move(timer), std::move(result_callback))); + + if (result != SBOX_ALL_OK) { + TRACE_EVENT_NESTABLE_ASYNC_END0( + "startup", "StartProcessWithAccess::LAUNCHPROCESS", trace_event_id); + + if (result == SBOX_ERROR_GENERIC) { + DPLOG(ERROR) << "Failed to launch process"; + } else { + DLOG(ERROR) << "Failed to launch process. Error: " << result; + } + } + return result; +} + +// static +void SandboxWin::FinishStartSandboxedProcess( + SandboxDelegate* delegate, + SandboxLaunchTimer timer, + StartSandboxedProcessCallback result_callback, + base::win::ScopedProcessInformation target, + DWORD last_error, + ResultCode result) { timer.OnProcessSpawned(); - base::win::ScopedProcessInformation target(temp_process_info); - - TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS"); - + int64_t trace_event_id = timer.GetStartTimeInMicroseconds(); + TRACE_EVENT_NESTABLE_ASYNC_END0( + "startup", "StartProcessWithAccess::LAUNCHPROCESS", trace_event_id); if (SBOX_ALL_OK != result) { base::UmaHistogramSparse("Process.Sandbox.Launch.Error", last_error); - if (result == SBOX_ERROR_GENERIC) + if (result == SBOX_ERROR_GENERIC) { DPLOG(ERROR) << "Failed to launch process"; - else + } else { DLOG(ERROR) << "Failed to launch process. Error: " << result; - return result; + } + std::move(result_callback).Run(base::Process(), last_error, result); + return; } delegate->PostSpawnTarget(target.process_handle()); @@ -1031,8 +1073,8 @@ timer.RecordHistograms(); } - *process = base::Process(target.TakeProcessHandle()); - return SBOX_ALL_OK; + base::Process process(target.TakeProcessHandle()); + std::move(result_callback).Run(std::move(process), last_error, result); } // static
diff --git a/sandbox/policy/win/sandbox_win.h b/sandbox/policy/win/sandbox_win.h index 271e80f5..ede8bb5 100644 --- a/sandbox/policy/win/sandbox_win.h +++ b/sandbox/policy/win/sandbox_win.h
@@ -7,14 +7,16 @@ #include <stdint.h> +#include <optional> #include <string> #include <string_view> -#include <optional> #include "base/functional/bind.h" #include "base/functional/callback_forward.h" #include "base/process/launch.h" #include "base/process/process_handle.h" +#include "base/timer/elapsed_timer.h" +#include "base/win/scoped_process_information.h" #include "build/build_config.h" #include "sandbox/policy/export.h" #include "sandbox/policy/sandbox_delegate.h" @@ -41,6 +43,43 @@ namespace sandbox { namespace policy { +// Helper to recording timing information during process creation. +class SANDBOX_POLICY_EXPORT SandboxLaunchTimer final { + public: + SandboxLaunchTimer() = default; + SandboxLaunchTimer(const SandboxLaunchTimer&) = delete; + SandboxLaunchTimer(SandboxLaunchTimer&& other) = default; + SandboxLaunchTimer& operator=(const SandboxLaunchTimer&) = delete; + + // Call after the policy base object is created. + void OnPolicyCreated() { policy_created_ = timer_.Elapsed(); } + + // Call after the delegate has generated policy settings. + void OnPolicyGenerated() { policy_generated_ = timer_.Elapsed(); } + + // Call after CreateProcess() has returned a suspended process. + void OnProcessSpawned() { process_spawned_ = timer_.Elapsed(); } + + // Call after unsuspending the process. + void OnProcessResumed() { process_resumed_ = timer_.Elapsed(); } + + // Returns when this timer was created. + int64_t GetStartTimeInMicroseconds() const { + return timer_.start_time().since_origin().InMicroseconds(); + } + + // Call once to record histograms for a successful process launch. + void RecordHistograms(); + + private: + // `timer_` starts when this object is created. + base::ElapsedTimer timer_; + base::TimeDelta policy_created_; + base::TimeDelta policy_generated_; + base::TimeDelta process_spawned_; + base::TimeDelta process_resumed_; +}; + class SANDBOX_POLICY_EXPORT SandboxWin { public: // Create a sandboxed process `process` with the specified `cmd_line`. @@ -48,13 +87,14 @@ // `delegate` specifies the sandbox delegate to use when resolving specific // sandbox policy. // - // Returns SBOX_ALL_OK if the process was successfully created. - // Otherwise, returns one of sandbox::ResultCode for any other error. + // If SBOX_ALL_OK is returned, then `result_callback` will be called with the + // process creation result. Otherwise, returns one of sandbox::ResultCode for + // any other error. static ResultCode StartSandboxedProcess( const base::CommandLine& cmd_line, const base::HandlesToInheritVector& handles_to_inherit, SandboxDelegate* delegate, - base::Process* process); + StartSandboxedProcessCallback result_callback); // Generates a sandbox policy into `policy` to match the one that would be // applied during `StartSandboxedProcess` for the identical set of arguments. @@ -124,6 +164,14 @@ private: FRIEND_TEST_ALL_PREFIXES(SandboxWinTest, GetJobMemoryLimit); + static void FinishStartSandboxedProcess( + SandboxDelegate* delegate, + SandboxLaunchTimer timer, + StartSandboxedProcessCallback result_callback, + base::win::ScopedProcessInformation target, + DWORD last_error, + ResultCode result); + static std::optional<size_t> GetJobMemoryLimit( sandbox::mojom::Sandbox sandbox_type); };
diff --git a/sandbox/win/BUILD.gn b/sandbox/win/BUILD.gn index 7f29a0cc..a82eaae 100644 --- a/sandbox/win/BUILD.gn +++ b/sandbox/win/BUILD.gn
@@ -192,6 +192,7 @@ "src/ipc_leak_test.cc", "src/ipc_ping_test.cc", "src/lpc_policy_test.cc", + "src/parallel_launch_test.cc", "src/policy_target_test.cc", "src/process_delegate_data_test.cc", "src/process_mitigations_deathtest.cc",
diff --git a/sandbox/win/fuzzer/sandbox_policy_rule_fuzzer.cc b/sandbox/win/fuzzer/sandbox_policy_rule_fuzzer.cc index 38a35e11..59f8afb 100644 --- a/sandbox/win/fuzzer/sandbox_policy_rule_fuzzer.cc +++ b/sandbox/win/fuzzer/sandbox_policy_rule_fuzzer.cc
@@ -2,6 +2,11 @@ // 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 <stddef.h> #include <stdint.h>
diff --git a/sandbox/win/src/broker_services.cc b/sandbox/win/src/broker_services.cc index 927a7c83..7dc8493 100644 --- a/sandbox/win/src/broker_services.cc +++ b/sandbox/win/src/broker_services.cc
@@ -16,7 +16,6 @@ #include "base/win/access_token.h" #include "base/win/current_module.h" #include "base/win/scoped_handle.h" -#include "base/win/scoped_process_information.h" #include "base/win/windows_version.h" #include "build/build_config.h" #include "sandbox/win/src/app_container.h" @@ -255,8 +254,11 @@ // The broker uses a dedicated worker thread that services the job completion // port to perform policy notifications and associated cleanup tasks. -ResultCode BrokerServicesBase::Init( +ResultCode BrokerServicesBase::InitInternal( + std::unique_ptr<BrokerServicesDelegate> delegate, std::unique_ptr<BrokerServicesTargetTracker> target_tracker) { + broker_services_delegate_ = std::move(delegate); + if (job_port_.is_valid() || thread_pool_) { return SBOX_ERROR_UNEXPECTED_CALL; } @@ -297,14 +299,17 @@ return SBOX_ALL_OK; } -ResultCode BrokerServicesBase::Init() { - return BrokerServicesBase::Init(nullptr); +ResultCode BrokerServicesBase::Init( + std::unique_ptr<BrokerServicesDelegate> delegate) { + return BrokerServicesBase::InitInternal(std::move(delegate), nullptr); } // Only called in test code. ResultCode BrokerServicesBase::InitForTesting( + std::unique_ptr<BrokerServicesDelegate> delegate, std::unique_ptr<BrokerServicesTargetTracker> target_tracker) { - return BrokerServicesBase::Init(std::move(target_tracker)); + return BrokerServicesBase::InitInternal(std::move(delegate), + std::move(target_tracker)); } // The destructor should only be called when the Broker process is terminating. @@ -359,13 +364,55 @@ return policy; } -// SpawnTarget does all the interesting sandbox setup and creates the target -// process inside the sandbox. ResultCode BrokerServicesBase::SpawnTarget(const wchar_t* exe_path, const wchar_t* command_line, std::unique_ptr<TargetPolicy> policy, DWORD* last_error, PROCESS_INFORMATION* target_info) { + *last_error = 0; + *target_info = {}; + // With parallel launching disabled, it is safe to capture local references + // because SpawnTargetAsyncImpl is guaranteed to run the callback before + // returning. + ResultCode launch_result = SBOX_ERROR_GENERIC; + ResultCode result = SpawnTargetAsyncImpl( + exe_path, command_line, std::move(policy), + base::BindOnce( + [](DWORD* last_error, PROCESS_INFORMATION* target_info, + ResultCode* launch_result, + base::win::ScopedProcessInformation result_target_info, + DWORD result_last_error, ResultCode result_code) -> void { + *target_info = result_target_info.Take(); + *last_error = result_last_error; + *launch_result = result_code; + }, + last_error, target_info, &launch_result), + /*allow_parallel_launch=*/false); + + if (result == SBOX_ALL_OK) { + result = launch_result; + } + return result; +} + +ResultCode BrokerServicesBase::SpawnTargetAsync( + const wchar_t* exe_path, + const wchar_t* command_line, + std::unique_ptr<TargetPolicy> policy, + SpawnTargetCallback result_callback) { + return SpawnTargetAsyncImpl(exe_path, command_line, std::move(policy), + std::move(result_callback), + /*allow_parallel_launch=*/true); +} + +// SpawnTarget does all the interesting sandbox setup and creates the target +// process inside the sandbox. +ResultCode BrokerServicesBase::SpawnTargetAsyncImpl( + const wchar_t* exe_path, + const wchar_t* command_line, + std::unique_ptr<TargetPolicy> policy, + SpawnTargetCallback result_callback, + bool allow_parallel_launch) { if (!exe_path) return SBOX_ERROR_BAD_PARAMS; @@ -464,23 +511,88 @@ // Create the TargetProcess object and spawn the target suspended. Note that // Brokerservices does not own the target object. It is owned by the Policy. - base::win::ScopedProcessInformation process_info; std::unique_ptr<TargetProcess> target = std::make_unique<TargetProcess>( std::move(*initial_token), std::move(*lockdown_token), thread_pool_); - result = target->Create(exe_path, command_line, std::move(startup_info), - &process_info, last_error); - - if (result != SBOX_ALL_OK) { - target->Terminate(); - return result; + if (allow_parallel_launch && + broker_services_delegate_->ParallelLaunchEnabled()) { + TargetProcess* target_ptr = target.get(); + broker_services_delegate_->ParallelLaunchPostTaskAndReplyWithResult( + FROM_HERE, + base::BindOnce(&BrokerServicesBase::CreateTarget, + base::Unretained(this), target_ptr, + std::wstring(exe_path), std::wstring(command_line), + std::move(startup_info)), + base::BindOnce(&BrokerServicesBase::FinishSpawnTarget, + base::Unretained(this), std::move(policy_base), + std::move(target), std::move(result_callback))); + return SBOX_ALL_OK; } + CreateTargetResult target_result = CreateTarget( + target.get(), exe_path, command_line, std::move(startup_info)); + + FinishSpawnTarget(std::move(policy_base), std::move(target), + std::move(result_callback), std::move(target_result)); + return SBOX_ALL_OK; +} + +CreateTargetResult BrokerServicesBase::CreateTarget( + TargetProcess* target, + const std::wstring& exe_path, + const std::wstring& command_line, + std::unique_ptr<StartupInformationHelper> startup_info) { + // A trace ID for the current scope is generated from the address of a local + // variable to ensure uniqueness across threads. + const void* trace_id = &startup_info; + broker_services_delegate_->BeforeTargetProcessCreateOnCreationThread( + trace_id); + + CreateTargetResult result; + result.result_code = target->Create(exe_path.c_str(), command_line.c_str(), + std::move(startup_info), + &result.process_info, &result.last_error); + + broker_services_delegate_->AfterTargetProcessCreateOnCreationThread( + trace_id, result.process_info.process_id()); + + return result; +} + +void BrokerServicesBase::FinishSpawnTarget( + std::unique_ptr<PolicyBase> policy_base, + std::unique_ptr<TargetProcess> target, + SpawnTargetCallback result_callback, + CreateTargetResult target_result) { + ResultCode result = FinishSpawnTargetImpl( + target_result.result_code, std::move(policy_base), std::move(target), + &target_result.process_info, &target_result.last_error); + if (result != SBOX_ALL_OK) { + target_result.process_info.Close(); + } + std::move(result_callback) + .Run(std::move(target_result.process_info), target_result.last_error, + result); +} + +ResultCode BrokerServicesBase::FinishSpawnTargetImpl( + ResultCode initial_result, + std::unique_ptr<PolicyBase> policy_base, + std::unique_ptr<TargetProcess> target, + base::win::ScopedProcessInformation* process_info, + DWORD* last_error) { + if (initial_result != SBOX_ALL_OK) { + target->Terminate(); + return initial_result; + } + + ConfigBase* config_base = static_cast<ConfigBase*>(policy_base->GetConfig()); + if (config_base->GetJobLevel() <= JobLevel::kLimitedUser) { // Restrict the job from containing any processes. Job restrictions // are only applied at process creation, so the target process is // unaffected. - result = policy_base->DropActiveProcessLimit(); + ResultCode result = policy_base->DropActiveProcessLimit(); if (result != SBOX_ALL_OK) { target->Terminate(); return result; @@ -489,7 +601,7 @@ // Now the policy is the owner of the target. TargetProcess will terminate // the process if it has not completed when it is destroyed. - result = policy_base->ApplyToTarget(std::move(target)); + ResultCode result = policy_base->ApplyToTarget(std::move(target)); if (result != SBOX_ALL_OK) { *last_error = ::GetLastError(); @@ -498,7 +610,7 @@ HANDLE job_handle = policy_base->GetJobHandle(); JobTracker* tracker = - new JobTracker(std::move(policy_base), process_info.process_id()); + new JobTracker(std::move(policy_base), process_info->process_id()); // Post the tracker to the tracking thread, then associate the job with // the tracker. The worker thread takes ownership of these objects. @@ -508,7 +620,6 @@ // There is no obvious cleanup here. CHECK(AssociateCompletionPort(job_handle, job_port_.get(), tracker)); - *target_info = process_info.Take(); return result; } @@ -602,6 +713,11 @@ alt_desktop_.reset(); } +void BrokerServicesBase::SetBrokerServicesDelegateForTesting( + std::unique_ptr<BrokerServicesDelegate> delegate) { + broker_services_delegate_ = std::move(delegate); +} + // static void BrokerServicesBase::FreezeTargetConfigForTesting(TargetConfig* config) { CHECK(!config->IsConfigured());
diff --git a/sandbox/win/src/broker_services.h b/sandbox/win/src/broker_services.h index 49a2e733..c8851070 100644 --- a/sandbox/win/src/broker_services.h +++ b/sandbox/win/src/broker_services.h
@@ -17,6 +17,7 @@ #include "base/memory/raw_ptr.h" #include "base/memory/scoped_refptr.h" #include "base/win/scoped_handle.h" +#include "base/win/scoped_process_information.h" #include "sandbox/win/src/alternate_desktop.h" #include "sandbox/win/src/crosscall_server.h" #include "sandbox/win/src/sandbox.h" @@ -45,8 +46,9 @@ ~BrokerServicesBase(); // BrokerServices interface. - ResultCode Init() override; + ResultCode Init(std::unique_ptr<BrokerServicesDelegate> delegate) override; ResultCode InitForTesting( + std::unique_ptr<BrokerServicesDelegate> delegate, std::unique_ptr<BrokerServicesTargetTracker> target_tracker) override; ResultCode CreateAlternateDesktop(Desktop desktop) override; void DestroyDesktops() override; @@ -58,6 +60,10 @@ std::unique_ptr<TargetPolicy> policy, DWORD* last_error, PROCESS_INFORMATION* target) override; + ResultCode SpawnTargetAsync(const wchar_t* exe_path, + const wchar_t* command_line, + std::unique_ptr<TargetPolicy> policy, + SpawnTargetCallback result_callback) override; ResultCode GetPolicyDiagnostics( std::unique_ptr<PolicyDiagnosticsReceiver> receiver) override; void SetStartingMitigations(MitigationFlags starting_mitigations) override; @@ -65,15 +71,56 @@ MitigationFlags additional_flags) override; std::wstring GetDesktopName(Desktop desktop) override; + void SetBrokerServicesDelegateForTesting( + std::unique_ptr<BrokerServicesDelegate> delegate); + static void FreezeTargetConfigForTesting(TargetConfig* config); private: // Implements Init and InitForTesting. - ResultCode Init(std::unique_ptr<BrokerServicesTargetTracker> target_tracker); + ResultCode InitInternal( + std::unique_ptr<BrokerServicesDelegate> delegate, + std::unique_ptr<BrokerServicesTargetTracker> target_tracker); // Ensures the desktop integrity suits any process we are launching. ResultCode UpdateDesktopIntegrity(Desktop desktop, IntegrityLevel integrity); + // Creates the target process and returns the new process handle in the + // result. In parallel launch mode, this function runs on the thread pool. + CreateTargetResult CreateTarget( + TargetProcess* target, + const std::wstring& exe_path, + const std::wstring& command_line, + std::unique_ptr<StartupInformationHelper> startup_info); + + // Implementation for SpawnTarget and SpawnTargetAsync. + // Parallel launching will be used if `allow_parallel_launch` is true and + // BrokerServicesDelegate::EnableParallelLaunch() returns true. + // When this function returns SBOX_ALL_OK, `result_callback` will be called + // with the target creation result. Otherwise, the returned error code is + // final and `result_callback` will not be called. + ResultCode SpawnTargetAsyncImpl(const wchar_t* exe_path, + const wchar_t* command_line, + std::unique_ptr<TargetPolicy> policy, + SpawnTargetCallback result_callback, + bool allow_parallel_launch); + + // This function is a wrapper for FinishSpawnTargetImpl and gets called after + // the target process is created. This function is responsible for running + // `result_callback` to return the information about the new process. + void FinishSpawnTarget(std::unique_ptr<PolicyBase> policy_base, + std::unique_ptr<TargetProcess> target, + SpawnTargetCallback result_callback, + CreateTargetResult target_result); + + // Finishes setup after the target process is created. + ResultCode FinishSpawnTargetImpl( + ResultCode initial_result, + std::unique_ptr<PolicyBase> policy_base, + std::unique_ptr<TargetProcess> target, + base::win::ScopedProcessInformation* process_info, + DWORD* last_error); + // The completion port used by the job objects to communicate events to // the worker thread. base::win::ScopedHandle job_port_; @@ -93,6 +140,9 @@ // Cache of configs backing policies. Entries are retained until shutdown and // used to prime policies created by CreatePolicy() with the same `tag`. base::flat_map<std::string, std::unique_ptr<TargetConfig>> config_cache_; + + // Provides configuration for using parallel or synchronous process launching. + std::unique_ptr<BrokerServicesDelegate> broker_services_delegate_; }; } // namespace sandbox
diff --git a/sandbox/win/src/parallel_launch_test.cc b/sandbox/win/src/parallel_launch_test.cc new file mode 100644 index 0000000..ec558455 --- /dev/null +++ b/sandbox/win/src/parallel_launch_test.cc
@@ -0,0 +1,251 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <windows.h> + +#include <memory> +#include <string> + +#include "base/process/process_info.h" +#include "base/task/lazy_thread_pool_task_runner.h" +#include "base/task/single_thread_task_runner.h" +#include "base/task/single_thread_task_runner_thread_mode.h" +#include "base/task/thread_pool.h" +#include "base/test/task_environment.h" +#include "base/win/scoped_process_information.h" +#include "sandbox/win/src/broker_services.h" +#include "sandbox/win/tests/common/controller.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace sandbox { + +// BrokerServicesDelegate common implementation. +class TestBrokerServicesDelegateBase : public BrokerServicesDelegate { + public: + bool ParallelLaunchEnabled() override { return true; } + + void ParallelLaunchPostTaskAndReplyWithResult( + const base::Location& from_here, + base::OnceCallback<CreateTargetResult()> task, + base::OnceCallback<void(CreateTargetResult)> reply) override { + base::ThreadPool::PostTaskAndReplyWithResult( + from_here, + {base::MayBlock(), base::TaskPriority::USER_BLOCKING, + base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, + std::move(task), std::move(reply)); + } + + void AfterTargetProcessCreateOnCreationThread(const void* trace_id, + DWORD process_id) override {} +}; + +class ParallelLaunchTest : public testing::Test { + public: + void SetUp() override { + task_environment_ = std::make_unique<base::test::TaskEnvironment>(); + } + + static void FinishSpawnTargetAsync(CreateTargetResult* spawn_result, + base::RunLoop* run_loop, + int* launches_remaining_count, + base::win::ScopedProcessInformation target, + DWORD last_error, + ResultCode result) { + spawn_result->process_info = std::move(target); + spawn_result->last_error = last_error; + spawn_result->result_code = result; + + if (--*launches_remaining_count == 0) { + run_loop->Quit(); + } + } + + private: + std::unique_ptr<base::test::TaskEnvironment> task_environment_; +}; + +class SingleLaunch_TestBrokerServicesDelegate + : public TestBrokerServicesDelegateBase { + public: + void BeforeTargetProcessCreateOnCreationThread( + const void* trace_id) override { + creation_thread_id_ = ::GetCurrentThreadId(); + } + + DWORD creation_thread_id_ = 0; +}; + +// Launches a single child with parallel launching enabled. The child process +// will be created on the thread pool. +TEST_F(ParallelLaunchTest, SingleLaunch) { + BrokerServices* broker = GetBroker(); + ASSERT_TRUE(broker); + + auto* delegate = new SingleLaunch_TestBrokerServicesDelegate(); + static_cast<BrokerServicesBase*>(broker)->SetBrokerServicesDelegateForTesting( + std::unique_ptr<BrokerServicesDelegate>(delegate)); + + // Get the path to the sandboxed app. + wchar_t prog_name[MAX_PATH]; + GetModuleFileNameW(nullptr, prog_name, MAX_PATH); + + std::wstring arguments(L"\""); + arguments += prog_name; + arguments += L"\" -child 0 wait"; // Don't care about the "state" argument. + + auto policy = broker->CreatePolicy(); + EXPECT_EQ(SBOX_ALL_OK, policy->GetConfig()->SetTokenLevel(USER_INTERACTIVE, + USER_LOCKDOWN)); + + CreateTargetResult spawn_result; + spawn_result.result_code = SBOX_ERROR_GENERIC; + + base::RunLoop run_loop; + int launches_remaining_count = 1; + ResultCode result_code = broker->SpawnTargetAsync( + prog_name, arguments.c_str(), std::move(policy), + base::BindOnce(&FinishSpawnTargetAsync, base::Unretained(&spawn_result), + base::Unretained(&run_loop), + base::Unretained(&launches_remaining_count))); + EXPECT_EQ(result_code, SBOX_ALL_OK); + + run_loop.Run(); + + // Target creation should happen on a different thread. + EXPECT_NE(delegate->creation_thread_id_, 0u); + EXPECT_NE(delegate->creation_thread_id_, GetCurrentThreadId()); + + EXPECT_EQ(SBOX_ALL_OK, spawn_result.result_code); + + EXPECT_EQ(1u, ::ResumeThread(spawn_result.process_info.thread_handle())); + + EXPECT_EQ( + static_cast<DWORD>(WAIT_TIMEOUT), + ::WaitForSingleObject(spawn_result.process_info.process_handle(), 2000)); + + EXPECT_TRUE( + ::TerminateProcess(spawn_result.process_info.process_handle(), 0)); + + ::WaitForSingleObject(spawn_result.process_info.process_handle(), INFINITE); +} + +class ParallelLaunch_TestBrokerServicesDelegate + : public TestBrokerServicesDelegateBase { + public: + void BeforeTargetProcessCreateOnCreationThread( + const void* trace_id) override { + if (first_launch_) { + first_creation_thread_id_ = ::GetCurrentThreadId(); + first_trace_id_ = reinterpret_cast<uintptr_t>(trace_id); + first_launch_ = false; + EXPECT_TRUE(::SetEvent(reached_first_creation_event_)); + ::WaitForSingleObject(first_block_event_, INFINITE); + } else { + second_creation_thread_id_ = ::GetCurrentThreadId(); + second_trace_id_ = reinterpret_cast<uintptr_t>(trace_id); + EXPECT_TRUE(::SetEvent(first_block_event_)); + } + } + + bool first_launch_ = true; + HANDLE reached_first_creation_event_; + HANDLE first_block_event_; + DWORD first_creation_thread_id_; + DWORD second_creation_thread_id_; + uintptr_t first_trace_id_; + uintptr_t second_trace_id_; +}; + +// This test launches two processes and synchronizes the target creation threads +// to run at the same time. +TEST_F(ParallelLaunchTest, ParallelLaunch) { + BrokerServices* broker = GetBroker(); + ASSERT_TRUE(broker); + + auto* delegate = new ParallelLaunch_TestBrokerServicesDelegate(); + static_cast<BrokerServicesBase*>(broker)->SetBrokerServicesDelegateForTesting( + std::unique_ptr<BrokerServicesDelegate>(delegate)); + + // Get the path to the sandboxed app. + wchar_t prog_name[MAX_PATH]; + GetModuleFileNameW(nullptr, prog_name, MAX_PATH); + + std::wstring arguments(L"\""); + arguments += prog_name; + arguments += L"\" -child 0 wait"; // Don't care about the "state" argument. + + base::RunLoop run_loop; + int launches_remaining_count = 2; + + // Launch the first process. This will block on the creation thread and wait + // for the second process launch to unblock it. + CreateTargetResult first_spawn_result; + first_spawn_result.result_code = SBOX_ERROR_GENERIC; + delegate->reached_first_creation_event_ = + ::CreateEvent(nullptr, FALSE, FALSE, nullptr); + delegate->first_block_event_ = ::CreateEvent(nullptr, FALSE, FALSE, nullptr); + + { + auto policy = broker->CreatePolicy(); + EXPECT_EQ(SBOX_ALL_OK, policy->GetConfig()->SetTokenLevel(USER_INTERACTIVE, + USER_LOCKDOWN)); + + ResultCode result_code = broker->SpawnTargetAsync( + prog_name, arguments.c_str(), std::move(policy), + base::BindOnce(&FinishSpawnTargetAsync, + base::Unretained(&first_spawn_result), + base::Unretained(&run_loop), + base::Unretained(&launches_remaining_count))); + EXPECT_EQ(result_code, SBOX_ALL_OK); + } + + ::WaitForSingleObject(delegate->reached_first_creation_event_, INFINITE); + + // Launch the second process. + CreateTargetResult second_spawn_result; + second_spawn_result.result_code = SBOX_ERROR_GENERIC; + { + auto policy = broker->CreatePolicy(); + EXPECT_EQ(SBOX_ALL_OK, policy->GetConfig()->SetTokenLevel(USER_INTERACTIVE, + USER_LOCKDOWN)); + + ResultCode result_code = broker->SpawnTargetAsync( + prog_name, arguments.c_str(), std::move(policy), + base::BindOnce(&FinishSpawnTargetAsync, + base::Unretained(&second_spawn_result), + base::Unretained(&run_loop), + base::Unretained(&launches_remaining_count))); + EXPECT_EQ(result_code, SBOX_ALL_OK); + } + + run_loop.Run(); + + // Targets should be created on different threads. + EXPECT_NE(delegate->first_creation_thread_id_, + delegate->second_creation_thread_id_); + + EXPECT_NE(delegate->first_trace_id_, delegate->second_trace_id_); + + EXPECT_EQ(SBOX_ALL_OK, first_spawn_result.result_code); + EXPECT_EQ(SBOX_ALL_OK, second_spawn_result.result_code); + + EXPECT_EQ(1u, + ::ResumeThread(first_spawn_result.process_info.thread_handle())); + EXPECT_EQ(1u, + ::ResumeThread(second_spawn_result.process_info.thread_handle())); + + HANDLE handles[2] = {first_spawn_result.process_info.process_handle(), + second_spawn_result.process_info.process_handle()}; + EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT), + ::WaitForMultipleObjects(2, handles, /*bWaitAll=*/TRUE, 2000)); + + EXPECT_TRUE( + ::TerminateProcess(first_spawn_result.process_info.process_handle(), 0)); + EXPECT_TRUE( + ::TerminateProcess(second_spawn_result.process_info.process_handle(), 0)); + + ::WaitForMultipleObjects(2, handles, /*bWaitAll=*/TRUE, INFINITE); +} + +} // namespace sandbox
diff --git a/sandbox/win/src/sandbox.h b/sandbox/win/src/sandbox.h index 5d35fa9a..c76136b 100644 --- a/sandbox/win/src/sandbox.h +++ b/sandbox/win/src/sandbox.h
@@ -20,13 +20,14 @@ #define SANDBOX_WIN_SRC_SANDBOX_H_ #include <stddef.h> -#include <memory> -#include <vector> +#include <memory> #include <optional> #include <string_view> +#include <vector> #include "base/containers/span.h" +#include "base/win/scoped_process_information.h" #include "base/win/windows_types.h" #include "sandbox/win/src/sandbox_policy.h" #include "sandbox/win/src/sandbox_types.h" @@ -34,6 +35,7 @@ // sandbox: Google User-Land Application Sandbox namespace sandbox { +class BrokerServicesDelegate; class BrokerServicesTargetTracker; class PolicyDiagnosticsReceiver; class ProcessState; @@ -59,15 +61,22 @@ // compatible definitions of the class even when LTO is enabled. class [[clang::lto_visibility_public]] BrokerServices { public: + // The callback used for receiving the SpawnTarget() process launch result. + // The parameters include the new process and thread handle, the Win32 last + // error code, and the sandbox ResultCode. + using SpawnTargetCallback = base::OnceCallback< + void(base::win::ScopedProcessInformation, DWORD, ResultCode)>; + // Initializes the broker. Must be called before any other on this class. // returns ALL_OK if successful. All other return values imply failure. // If the return is ERROR_GENERIC, you can call ::GetLastError() to get // more information. - virtual ResultCode Init() = 0; + virtual ResultCode Init(std::unique_ptr<BrokerServicesDelegate> delegate) = 0; // May be called in place of Init in test code to add a tracker that validates // job notifications and signals an event when all tracked processes are done. virtual ResultCode InitForTesting( + std::unique_ptr<BrokerServicesDelegate> delegate, std::unique_ptr<BrokerServicesTargetTracker> target_tracker) = 0; // Pre-creates an alternate desktop. Must be called before a non-default @@ -129,6 +138,18 @@ DWORD* last_error, PROCESS_INFORMATION* target) = 0; + // Async version of SpawnTarget that supports parallel process launching. + // Target creation happens on the thread pool when parallel launching is + // enabled (controlled by BrokerServicesDelegate). This function is the same + // as SpawnTarget, except the out parameters `last_error`, `target` and final + // ResultCode are passed to `result_callback`. + // Returns ALL_OK if `result_callback` will run with the result. Otherwise, + // the return error is final and `result_callback` will not be run. + virtual ResultCode SpawnTargetAsync(const wchar_t* exe_path, + const wchar_t* command_line, + std::unique_ptr<TargetPolicy> policy, + SpawnTargetCallback result_callback) = 0; + // This call creates a snapshot of policies managed by the sandbox and // returns them via a helper class. // Parameters: @@ -253,6 +274,38 @@ virtual ~BrokerServicesTargetTracker() {} }; +// Used internally by SpawnTarget() to return process launch info from a task. +struct [[clang::lto_visibility_public]] CreateTargetResult { + base::win::ScopedProcessInformation process_info; + DWORD last_error; + ResultCode result_code; +}; + +// This class configures BrokerServices to use parallel or synchronous process +// launching, and provides callbacks for implementing tracing. +class [[clang::lto_visibility_public]] BrokerServicesDelegate { + public: + // Returns true if parallel launching is enabled, otherwise synchronous + // launching is used. + virtual bool ParallelLaunchEnabled() = 0; + // This method runs `task` on the thread pool, then runs `reply` on the + // calling sequence with the returned CreateTargetResult. This method must be + // implemented if ParallelLaunchEnabled() can return true. + virtual void ParallelLaunchPostTaskAndReplyWithResult( + const base::Location& from_here, + base::OnceCallback<CreateTargetResult()> task, + base::OnceCallback<void(CreateTargetResult)> reply) = 0; + // Called before a target process is created. If parallel launching is + // enabled, this will be called on the thread pool. + virtual void BeforeTargetProcessCreateOnCreationThread( + const void* trace_id) = 0; + // Called after a target process is created. If parallel launching is enabled, + // this will be called on the thread pool. + virtual void AfterTargetProcessCreateOnCreationThread(const void* trace_id, + DWORD process_id) = 0; + virtual ~BrokerServicesDelegate() {} +}; + } // namespace sandbox #endif // SANDBOX_WIN_SRC_SANDBOX_H_
diff --git a/sandbox/win/src/sandbox_types.h b/sandbox/win/src/sandbox_types.h index 363a214..c76951c8 100644 --- a/sandbox/win/src/sandbox_types.h +++ b/sandbox/win/src/sandbox_types.h
@@ -5,6 +5,7 @@ #ifndef SANDBOX_WIN_SRC_SANDBOX_TYPES_H_ #define SANDBOX_WIN_SRC_SANDBOX_TYPES_H_ +#include "base/functional/callback.h" #include "base/memory/raw_ptr.h" #include "base/process/kill.h" #include "base/process/launch.h" @@ -212,6 +213,13 @@ INTERCEPTION_LAST // Placeholder for last item in the enumeration }; +// This callback is used for returning a process launch result from +// StartSandboxedProcess() to the child process launcher helper. The parameters +// include the new process handle, the Win32 last error code, and the sandbox +// ResultCode. +using StartSandboxedProcessCallback = + base::OnceCallback<void(base::Process, DWORD, int)>; + } // namespace sandbox #endif // SANDBOX_WIN_SRC_SANDBOX_TYPES_H_
diff --git a/sandbox/win/tests/common/controller.cc b/sandbox/win/tests/common/controller.cc index cfb3d66..6673d9c4 100644 --- a/sandbox/win/tests/common/controller.cc +++ b/sandbox/win/tests/common/controller.cc
@@ -15,6 +15,7 @@ #include "base/check.h" #include "base/dcheck_is_on.h" +#include "base/functional/callback.h" #include "base/memory/platform_shared_memory_region.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/process/process.h" @@ -133,6 +134,28 @@ : MakePathToSys32(name, is_obj_man_path); } +// This delegate is required for initializing BrokerServices and configures it +// to use synchronous launching. +class TestBrokerServicesDelegateImpl : public BrokerServicesDelegate { + public: + bool ParallelLaunchEnabled() override { return false; } + + void ParallelLaunchPostTaskAndReplyWithResult( + const base::Location& from_here, + base::OnceCallback<CreateTargetResult()> task, + base::OnceCallback<void(CreateTargetResult)> reply) override { + // This function is only used for parallel launching and should not get + // called. + CHECK(false); + } + + void BeforeTargetProcessCreateOnCreationThread( + const void* trace_id) override {} + + void AfterTargetProcessCreateOnCreationThread(const void* trace_id, + DWORD process_id) override {} +}; + BrokerServices* GetBroker() { static BrokerServices* broker = SandboxFactory::GetBrokerServices(); static bool is_initialized = false; @@ -148,7 +171,9 @@ } auto tracker = std::make_unique<TargetTracker>(g_no_targets_event); - if (SBOX_ALL_OK != broker->InitForTesting(std::move(tracker))) { + if (SBOX_ALL_OK != broker->InitForTesting( // IN-TEST + std::make_unique<TestBrokerServicesDelegateImpl>(), + std::move(tracker))) { return nullptr; }
diff --git a/services/network/BUILD.gn b/services/network/BUILD.gn index ec4813db..542c79d 100644 --- a/services/network/BUILD.gn +++ b/services/network/BUILD.gn
@@ -65,7 +65,6 @@ "ip_protection/ip_protection_config_getter.h", "ip_protection/ip_protection_config_getter_mojo_impl.cc", "ip_protection/ip_protection_config_getter_mojo_impl.h", - "ip_protection/ip_protection_data_types.h", "ip_protection/ip_protection_geo_utils.cc", "ip_protection/ip_protection_geo_utils.h", "ip_protection/ip_protection_proxy_delegate.cc",
diff --git a/services/network/ip_protection/ip_protection_config_cache.h b/services/network/ip_protection/ip_protection_config_cache.h index 1be1838..8a13ff19 100644 --- a/services/network/ip_protection/ip_protection_config_cache.h +++ b/services/network/ip_protection/ip_protection_config_cache.h
@@ -11,7 +11,7 @@ #include <vector> #include "base/component_export.h" -#include "services/network/ip_protection/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager.h" #include "services/network/ip_protection/ip_protection_token_cache_manager.h" @@ -38,7 +38,7 @@ // Returns `nullopt` if no token is available, whether for a transient or // permanent reason. This method may return `nullopt` even if // `IsAuthTokenAvailable()` recently returned `true`. - virtual std::optional<BlindSignedAuthToken> GetAuthToken( + virtual std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken( size_t chain_index) = 0; // Invalidate any previous instruction that token requests should not be @@ -68,14 +68,14 @@ // Set the token cache manager for the cache. virtual void SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, std::unique_ptr<IpProtectionTokenCacheManager> ipp_token_cache_manager) = 0; // Fetch the token cache manager. virtual IpProtectionTokenCacheManager* GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer) = 0; + ip_protection::ProxyLayer proxy_layer) = 0; // Set the proxy chain list manager for the cache. virtual void SetIpProtectionProxyListManagerForTesting(
diff --git a/services/network/ip_protection/ip_protection_config_cache_impl.cc b/services/network/ip_protection/ip_protection_config_cache_impl.cc index 6db01dfd..4cbccd2d 100644 --- a/services/network/ip_protection/ip_protection_config_cache_impl.cc +++ b/services/network/ip_protection/ip_protection_config_cache_impl.cc
@@ -11,12 +11,13 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/time/time.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "net/base/features.h" #include "net/base/network_change_notifier.h" #include "net/base/proxy_chain.h" #include "net/base/proxy_server.h" #include "net/base/proxy_string_util.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager_impl.h" #include "services/network/ip_protection/ip_protection_token_cache_manager.h" @@ -81,13 +82,13 @@ std::make_unique<IpProtectionProxyListManagerImpl>(this, *config_getter_); - ipp_token_cache_managers_[IpProtectionProxyLayer::kProxyA] = + ipp_token_cache_managers_[ip_protection::ProxyLayer::kProxyA] = std::make_unique<IpProtectionTokenCacheManagerImpl>( - this, config_getter_.get(), IpProtectionProxyLayer::kProxyA); + this, config_getter_.get(), ip_protection::ProxyLayer::kProxyA); - ipp_token_cache_managers_[IpProtectionProxyLayer::kProxyB] = + ipp_token_cache_managers_[ip_protection::ProxyLayer::kProxyB] = std::make_unique<IpProtectionTokenCacheManagerImpl>( - this, config_getter_.get(), IpProtectionProxyLayer::kProxyB); + this, config_getter_.get(), ip_protection::ProxyLayer::kProxyB); } net::NetworkChangeNotifier::AddNetworkChangeObserver(this); @@ -108,8 +109,7 @@ for (const auto& manager : ipp_token_cache_managers_) { if (!manager.second->IsAuthTokenAvailable( ipp_proxy_list_manager_->CurrentGeo())) { - base::UmaHistogramEnumeration( - "NetworkService.IpProtection.EmptyTokenCache", manager.first); + ip_protection::Telemetry().EmptyTokenCache(manager.first); all_caches_have_tokens = false; } } @@ -117,17 +117,17 @@ return all_caches_have_tokens; } -std::optional<BlindSignedAuthToken> IpProtectionConfigCacheImpl::GetAuthToken( - size_t chain_index) { - std::optional<BlindSignedAuthToken> result; +std::optional<ip_protection::BlindSignedAuthToken> +IpProtectionConfigCacheImpl::GetAuthToken(size_t chain_index) { + std::optional<ip_protection::BlindSignedAuthToken> result; // If the proxy list is empty, there cannot be any matching tokens. if (!IsProxyListAvailable() || ipp_token_cache_managers_.empty()) { return result; } - auto proxy_layer = chain_index == 0 ? IpProtectionProxyLayer::kProxyA - : IpProtectionProxyLayer::kProxyB; + auto proxy_layer = chain_index == 0 ? ip_protection::ProxyLayer::kProxyA + : ip_protection::ProxyLayer::kProxyB; if (ipp_token_cache_managers_.count(proxy_layer) > 0) { result = ipp_token_cache_managers_[proxy_layer]->GetAuthToken( ipp_proxy_list_manager_->CurrentGeo()); @@ -142,14 +142,14 @@ } void IpProtectionConfigCacheImpl::SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, std::unique_ptr<IpProtectionTokenCacheManager> ipp_token_cache_manager) { ipp_token_cache_managers_[proxy_layer] = std::move(ipp_token_cache_manager); } IpProtectionTokenCacheManager* IpProtectionConfigCacheImpl::GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer) { + ip_protection::ProxyLayer proxy_layer) { return ipp_token_cache_managers_[proxy_layer].get(); }
diff --git a/services/network/ip_protection/ip_protection_config_cache_impl.h b/services/network/ip_protection/ip_protection_config_cache_impl.h index 2a33bb1..201c4e91 100644 --- a/services/network/ip_protection/ip_protection_config_cache_impl.h +++ b/services/network/ip_protection/ip_protection_config_cache_impl.h
@@ -15,12 +15,12 @@ #include "base/sequence_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "net/base/features.h" #include "net/base/network_change_notifier.h" #include "net/base/proxy_chain.h" #include "services/network/ip_protection/ip_protection_config_cache.h" #include "services/network/ip_protection/ip_protection_config_getter.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager.h" #include "services/network/ip_protection/ip_protection_token_cache_manager.h" @@ -39,7 +39,8 @@ // IpProtectionConfigCache implementation. bool AreAuthTokensAvailable() override; - std::optional<BlindSignedAuthToken> GetAuthToken(size_t chain_index) override; + std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken( + size_t chain_index) override; void InvalidateTryAgainAfterTime() override; bool IsProxyListAvailable() override; void QuicProxiesFailed() override; @@ -47,11 +48,11 @@ void RequestRefreshProxyList() override; void GeoObserved(const std::string& geo_id) override; void SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, std::unique_ptr<IpProtectionTokenCacheManager> ipp_token_cache_manager) override; IpProtectionTokenCacheManager* GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer) override; + ip_protection::ProxyLayer proxy_layer) override; void SetIpProtectionProxyListManagerForTesting( std::unique_ptr<IpProtectionProxyListManager> ipp_proxy_list_manager) override; @@ -70,7 +71,7 @@ std::unique_ptr<IpProtectionProxyListManager> ipp_proxy_list_manager_; // Proxy layer managers for cache of blind-signed auth tokens. - std::map<IpProtectionProxyLayer, + std::map<ip_protection::ProxyLayer, std::unique_ptr<IpProtectionTokenCacheManager>> ipp_token_cache_managers_;
diff --git a/services/network/ip_protection/ip_protection_config_cache_impl_unittest.cc b/services/network/ip_protection/ip_protection_config_cache_impl_unittest.cc index 8a4ddf8..7ea7fd8 100644 --- a/services/network/ip_protection/ip_protection_config_cache_impl_unittest.cc +++ b/services/network/ip_protection/ip_protection_config_cache_impl_unittest.cc
@@ -16,9 +16,9 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "net/base/features.h" #include "net/base/network_change_notifier.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_geo_utils.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager_impl.h" @@ -55,11 +55,11 @@ current_geo_id_ = geo_id; } - std::optional<BlindSignedAuthToken> GetAuthToken() override { + std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken() override { return GetAuthToken(current_geo_id_); } - std::optional<BlindSignedAuthToken> GetAuthToken( + std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken( const std::string& geo_id) override { if (!auth_tokens_.contains(geo_id)) { return std::nullopt; @@ -68,14 +68,14 @@ return auth_tokens_.extract(geo_id).mapped(); } - void SetAuthToken(BlindSignedAuthToken auth_token) { + void SetAuthToken(ip_protection::BlindSignedAuthToken auth_token) { auth_tokens_[network::GetGeoIdFromGeoHint(auth_token.geo_hint)] = auth_token; } private: - std::map<std::string, BlindSignedAuthToken> auth_tokens_; - std::optional<BlindSignedAuthToken> auth_token_; + std::map<std::string, ip_protection::BlindSignedAuthToken> auth_tokens_; + std::optional<ip_protection::BlindSignedAuthToken> auth_token_; std::string current_geo_id_; }; @@ -190,7 +190,7 @@ AuthTokensNotAvailableIfProxyListIsNotAvailable) { // `IpProtectionProxyListManager` has not been set up. This means even if // tokens are available, `AreAuthTokensAvailable()` should return false. - BlindSignedAuthToken exp_token; + ip_protection::BlindSignedAuthToken exp_token; exp_token.token = "a-token"; exp_token.geo_hint = network::GetGeoHintFromGeoIdForTesting(kMountainViewGeoId).value(); @@ -198,7 +198,7 @@ std::make_unique<MockIpProtectionTokenCacheManager>(); ipp_token_cache_manager->SetAuthToken(std::move(exp_token)); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); + ip_protection::ProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); ASSERT_FALSE(ipp_config_cache_->AreAuthTokensAvailable()); // Neither calls will return a token since there is no proxy list available. @@ -215,7 +215,7 @@ auto ipp_token_cache_manager = std::make_unique<MockIpProtectionTokenCacheManager>(); - ipp_token_cache_manager->SetAuthToken(BlindSignedAuthToken{ + ipp_token_cache_manager->SetAuthToken(ip_protection::BlindSignedAuthToken{ .token = "a-token", .geo_hint = network::GetGeoHintFromGeoIdForTesting(kMountainViewGeoId).value()}); @@ -223,7 +223,7 @@ ipp_config_cache_->SetIpProtectionProxyListManagerForTesting( std::move(ipp_proxy_list_manager)); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); + ip_protection::ProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); ASSERT_TRUE(ipp_config_cache_->AreAuthTokensAvailable()); ASSERT_FALSE( @@ -238,7 +238,7 @@ ipp_proxy_list_manager->SetProxyList({MakeChain({"a-proxy"})}); ipp_proxy_list_manager->SetCurrentGeo(kMountainViewGeoId); - BlindSignedAuthToken exp_token; + ip_protection::BlindSignedAuthToken exp_token; exp_token.token = "b-token"; exp_token.geo_hint = network::GetGeoHintFromGeoIdForTesting(kMountainViewGeoId).value(); @@ -249,7 +249,7 @@ ipp_config_cache_->SetIpProtectionProxyListManagerForTesting( std::move(ipp_proxy_list_manager)); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyB, std::move(ipp_token_cache_manager)); + ip_protection::ProxyLayer::kProxyB, std::move(ipp_token_cache_manager)); ASSERT_TRUE(ipp_config_cache_->AreAuthTokensAvailable()); ASSERT_FALSE( @@ -266,7 +266,7 @@ ipp_proxy_list_manager->SetProxyList({MakeChain({"a-proxy"})}); ipp_proxy_list_manager->SetCurrentGeo(kMountainViewGeoId); - BlindSignedAuthToken exp_token; + ip_protection::BlindSignedAuthToken exp_token; exp_token.token = "a-token"; exp_token.geo_hint = network::GetGeoHintFromGeoIdForTesting(kMountainViewGeoId).value(); @@ -277,15 +277,15 @@ ipp_config_cache_->SetIpProtectionProxyListManagerForTesting( std::move(ipp_proxy_list_manager)); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); + ip_protection::ProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyB, + ip_protection::ProxyLayer::kProxyB, std::make_unique<MockIpProtectionTokenCacheManager>()); ASSERT_FALSE(ipp_config_cache_->AreAuthTokensAvailable()); histogram_tester_.ExpectTotalCount(kEmptyTokenCacheHistogram, 1); histogram_tester_.ExpectBucketCount(kEmptyTokenCacheHistogram, - IpProtectionProxyLayer::kProxyB, 1); + ip_protection::ProxyLayer::kProxyB, 1); } // GetAuthToken for where proxy list manager's geo is different than the current @@ -300,11 +300,11 @@ // geo and a new sunnyvale geo. auto ipp_token_cache_manager = std::make_unique<MockIpProtectionTokenCacheManager>(); - ipp_token_cache_manager->SetAuthToken(BlindSignedAuthToken{ + ipp_token_cache_manager->SetAuthToken(ip_protection::BlindSignedAuthToken{ .token = "a-token", .geo_hint = network::GetGeoHintFromGeoIdForTesting(kMountainViewGeoId).value()}); - ipp_token_cache_manager->SetAuthToken(BlindSignedAuthToken{ + ipp_token_cache_manager->SetAuthToken(ip_protection::BlindSignedAuthToken{ .token = "a-token", .geo_hint = network::GetGeoHintFromGeoIdForTesting(kSunnyvaleGeoId).value()}); @@ -312,12 +312,12 @@ ipp_config_cache_->SetIpProtectionProxyListManagerForTesting( std::move(ipp_proxy_list_manager)); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); + ip_protection::ProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); // The following calls will be based on the proxy list manager's geo (Mountain // View). ASSERT_TRUE(ipp_config_cache_->AreAuthTokensAvailable()); - std::optional<BlindSignedAuthToken> token = + std::optional<ip_protection::BlindSignedAuthToken> token = ipp_config_cache_->GetAuthToken(0); ASSERT_TRUE(token); ASSERT_EQ(token->geo_hint, @@ -460,7 +460,7 @@ std::make_unique<MockIpProtectionTokenCacheManager>(); ipp_token_cache_manager->SetCurrentGeo("US,US-MA,BOSTON"); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); + ip_protection::ProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); // Simulate that the new geo signal in the Proxy List Manager resulted in a // call to observe a geo change. @@ -471,7 +471,7 @@ new_geo_signal); EXPECT_EQ(ipp_config_cache_ ->GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA) + ip_protection::ProxyLayer::kProxyA) ->CurrentGeo(), new_geo_signal); @@ -501,7 +501,7 @@ std::make_unique<MockIpProtectionTokenCacheManager>(); ipp_token_cache_manager->SetCurrentGeo(boston_geo_id); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); + ip_protection::ProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); // Simulate the empty geo change in the proxy list manager caused a call such // as this. @@ -512,7 +512,7 @@ empty_geo_signal); EXPECT_EQ(ipp_config_cache_ ->GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA) + ip_protection::ProxyLayer::kProxyA) ->CurrentGeo(), empty_geo_signal); @@ -539,7 +539,7 @@ std::make_unique<MockIpProtectionTokenCacheManager>(); ipp_token_cache_manager->SetCurrentGeo(old_geo_id); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); + ip_protection::ProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); // Set up IppProxyListManager to have a "old" geo. auto ipp_proxy_list_manager = @@ -561,7 +561,7 @@ // Both should still contain the old geo id. EXPECT_EQ(ipp_config_cache_ ->GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA) + ip_protection::ProxyLayer::kProxyA) ->CurrentGeo(), old_geo_id); @@ -579,7 +579,7 @@ std::make_unique<MockIpProtectionTokenCacheManager>(); ipp_token_cache_manager->SetCurrentGeo(new_geo_signal); ipp_config_cache_->SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); + ip_protection::ProxyLayer::kProxyA, std::move(ipp_token_cache_manager)); // Set up IppProxyListManager to have a "old" geo. auto ipp_proxy_list_manager = @@ -599,7 +599,7 @@ EXPECT_EQ(ipp_config_cache_ ->GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer::kProxyA) + ip_protection::ProxyLayer::kProxyA) ->CurrentGeo(), new_geo_signal);
diff --git a/services/network/ip_protection/ip_protection_config_getter.h b/services/network/ip_protection/ip_protection_config_getter.h index 8f47524f..a679216 100644 --- a/services/network/ip_protection/ip_protection_config_getter.h +++ b/services/network/ip_protection/ip_protection_config_getter.h
@@ -9,8 +9,8 @@ #include "base/component_export.h" #include "base/functional/callback.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "net/base/proxy_chain.h" -#include "services/network/ip_protection/ip_protection_data_types.h" namespace network { // Interface used by the network service to get the IP Protection configuration @@ -19,9 +19,9 @@ public: virtual ~IpProtectionConfigGetter() = default; - using TryGetAuthTokensCallback = - base::OnceCallback<void(std::optional<std::vector<BlindSignedAuthToken>>, - std::optional<::base::Time>)>; + using TryGetAuthTokensCallback = base::OnceCallback<void( + std::optional<std::vector<ip_protection::BlindSignedAuthToken>>, + std::optional<::base::Time>)>; // Try to get a batch of IP Protection tokens. // @@ -38,12 +38,12 @@ // base::SequencedTaskRunnerHandle::Get() at the time of construction of // this object). virtual void TryGetAuthTokens(uint32_t batch_size, - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, TryGetAuthTokensCallback callback) = 0; using GetProxyListCallback = base::OnceCallback<void(std::optional<std::vector<::net::ProxyChain>>, - std::optional<GeoHint> geo_hint)>; + std::optional<ip_protection::GeoHint> geo_hint)>; // Get the list of IP Protection proxy chains. //
diff --git a/services/network/ip_protection/ip_protection_config_getter_mojo_impl.cc b/services/network/ip_protection/ip_protection_config_getter_mojo_impl.cc index 269eb17..d3ce66f6 100644 --- a/services/network/ip_protection/ip_protection_config_getter_mojo_impl.cc +++ b/services/network/ip_protection/ip_protection_config_getter_mojo_impl.cc
@@ -10,9 +10,9 @@ #include "base/check.h" #include "base/logging.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_config_cache_impl.h" #include "services/network/ip_protection/ip_protection_config_getter.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/public/mojom/network_context.mojom.h" namespace network { @@ -21,11 +21,11 @@ // TODO(abhijithnair): Replace the below with EnumTraits. network::mojom::IpProtectionProxyLayer convertToMojo( - const IpProtectionProxyLayer& layer) { + const ip_protection::ProxyLayer& layer) { switch (layer) { - case network::IpProtectionProxyLayer::kProxyA: + case ip_protection::ProxyLayer::kProxyA: return network::mojom::IpProtectionProxyLayer::kProxyA; - case network::IpProtectionProxyLayer::kProxyB: + case ip_protection::ProxyLayer::kProxyB: return network::mojom::IpProtectionProxyLayer::kProxyB; } } @@ -48,7 +48,7 @@ void IpProtectionConfigGetterMojoImpl::TryGetAuthTokens( uint32_t batch_size, - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, TryGetAuthTokensCallback callback) { config_getter_->TryGetAuthTokens( batch_size, convertToMojo(proxy_layer), @@ -66,13 +66,14 @@ void IpProtectionConfigGetterMojoImpl::OnGotProxyList( GetProxyListCallback callback, const std::optional<std::vector<net::ProxyChain>>& proxy_list, - const std::optional<GeoHint>& geo_hint) { + const std::optional<ip_protection::GeoHint>& geo_hint) { std::move(callback).Run(proxy_list, geo_hint); } void IpProtectionConfigGetterMojoImpl::OnGotAuthTokens( TryGetAuthTokensCallback callback, - const std::optional<std::vector<BlindSignedAuthToken>>& tokens, + const std::optional<std::vector<ip_protection::BlindSignedAuthToken>>& + tokens, std::optional<::base::Time> expiration_time) { std::move(callback).Run(tokens, expiration_time); }
diff --git a/services/network/ip_protection/ip_protection_config_getter_mojo_impl.h b/services/network/ip_protection/ip_protection_config_getter_mojo_impl.h index dfcd8ef..0aa7f7d 100644 --- a/services/network/ip_protection/ip_protection_config_getter_mojo_impl.h +++ b/services/network/ip_protection/ip_protection_config_getter_mojo_impl.h
@@ -7,9 +7,9 @@ #include "base/component_export.h" #include "base/memory/raw_ptr.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/network/ip_protection/ip_protection_config_getter.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/public/mojom/network_context.mojom.h" namespace network { @@ -22,7 +22,7 @@ ~IpProtectionConfigGetterMojoImpl() override; void TryGetAuthTokens(uint32_t batch_size, - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, TryGetAuthTokensCallback callback) override; void GetProxyList(GetProxyListCallback callback) override; bool IsAvailable() override; @@ -31,10 +31,11 @@ void OnGotProxyList( GetProxyListCallback callback, const std::optional<std::vector<net::ProxyChain>>& proxy_list, - const std::optional<GeoHint>& geo_hint); + const std::optional<ip_protection::GeoHint>& geo_hint); void OnGotAuthTokens( TryGetAuthTokensCallback callback, - const std::optional<std::vector<BlindSignedAuthToken>>& tokens, + const std::optional<std::vector<ip_protection::BlindSignedAuthToken>>& + tokens, std::optional<::base::Time> expiration_time); bool is_available_ = false;
diff --git a/services/network/ip_protection/ip_protection_data_types.h b/services/network/ip_protection/ip_protection_data_types.h deleted file mode 100644 index 3085070..0000000 --- a/services/network/ip_protection/ip_protection_data_types.h +++ /dev/null
@@ -1,51 +0,0 @@ -// Copyright 2024 The Chromium Authors -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SERVICES_NETWORK_IP_PROTECTION_IP_PROTECTION_DATA_TYPES_H_ -#define SERVICES_NETWORK_IP_PROTECTION_IP_PROTECTION_DATA_TYPES_H_ - -#include "base/time/time.h" - -namespace network { -// A GeoHint represents a course location of a user. Values are based on -// RFC 8805 geolocation. -struct GeoHint { - // Country code of the geo. Example: "US". - std::string country_code; - - // ISO region of the geo. Example: "US-CA". - std::string iso_region; - - // City name of the geo. Example: "MOUNTAIN VIEW". - std::string city_name; - - bool operator==(const GeoHint& geo_hint) const = default; -}; - -// A blind-signed auth token, suitable for use with IP protection proxies. -struct BlindSignedAuthToken { - // The token value, for inclusion in a header. - std::string token; - - // The expiration time of this token. - base::Time expiration; - - // The GeoHint which specifies the coarse geolocation of the token. - GeoHint geo_hint; - - bool operator==(const BlindSignedAuthToken& token) const = default; -}; - -// The proxy layer to fetch batches of tokens for. -// -// These values are persisted to logs. Entries should not be renumbered and -// numeric values should never be reused. -enum class IpProtectionProxyLayer { - kProxyA = 0, - kProxyB = 1, - kMaxValue = kProxyB -}; -} // namespace network - -#endif // SERVICES_NETWORK_IP_PROTECTION_IP_PROTECTION_DATA_TYPES_H_
diff --git a/services/network/ip_protection/ip_protection_geo_utils.cc b/services/network/ip_protection/ip_protection_geo_utils.cc index 397584a..71eae48 100644 --- a/services/network/ip_protection/ip_protection_geo_utils.cc +++ b/services/network/ip_protection/ip_protection_geo_utils.cc
@@ -8,11 +8,12 @@ #include <optional> #include <string> -#include "services/network/ip_protection/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_data_types.h" namespace network { -std::string GetGeoIdFromGeoHint(const std::optional<GeoHint> geo_hint) { +std::string GetGeoIdFromGeoHint( + const std::optional<ip_protection::GeoHint> geo_hint) { if (!geo_hint.has_value()) { return ""; // If nullopt, return empty string. } @@ -28,12 +29,13 @@ return geo_id; } -std::optional<GeoHint> GetGeoHintFromGeoIdForTesting( +// TODO(crbug.com/40176497): IN-TEST does not work for multi-line declarations. +std::optional<ip_protection::GeoHint> GetGeoHintFromGeoIdForTesting( // IN-TEST const std::string& geo_id) { if (geo_id.empty()) { return std::nullopt; // Return nullopt if the geo_id is empty. } - GeoHint geo_hint; + ip_protection::GeoHint geo_hint; std::stringstream geo_id_stream(geo_id); std::string segment;
diff --git a/services/network/ip_protection/ip_protection_geo_utils.h b/services/network/ip_protection/ip_protection_geo_utils.h index bba2dbd6..e5d5a41 100644 --- a/services/network/ip_protection/ip_protection_geo_utils.h +++ b/services/network/ip_protection/ip_protection_geo_utils.h
@@ -10,24 +10,27 @@ #include <string> #include "base/component_export.h" -#include "services/network/ip_protection/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_data_types.h" namespace network { -// GeoId is a string representation of a GeoHint. A GeoId is constructed by -// concatenating values of the GeoHint in order of increasing granularity. -// If a finer granularity is missing, a trailing commas is not appended. -// Ex. GeoHint{"US", "US-CA", "MOUNTAIN VIEW"} => "US,US-CA,MOUNTAIN VIEW". +// GeoId is a string representation of a ip_protection::GeoHint. A GeoId is +// constructed by concatenating values of the ip_protection::GeoHint in order of +// increasing granularity. If a finer granularity is missing, a trailing commas +// is not appended. +// Ex. GeoHint{"US", "US-CA", "MOUNTAIN VIEW"} => "US,US-CA,MOUNTAIN VIEW" // Ex. GeoHint{"US"} => "US" -// Returns a formatted version of the GeoHint. In the case +// Returns a formatted version of the ip_protection::GeoHint. In the case // of a nullptr or empty `GeoHintPtr`, an empty string will be returned. COMPONENT_EXPORT(NETWORK_SERVICE) -std::string GetGeoIdFromGeoHint(std::optional<GeoHint> geo_hint); +std::string GetGeoIdFromGeoHint(std::optional<ip_protection::GeoHint> geo_hint); -// Constructs a GeoHint from a GeoId string. The function requires a -// correctly formatted GeoId string. It DOES NOT handle invalid formats. +// Constructs a ip_protection::GeoHint from a GeoId string. The function +// requires a correctly formatted GeoId string. It DOES NOT handle invalid +// formats. COMPONENT_EXPORT(NETWORK_SERVICE) -std::optional<GeoHint> GetGeoHintFromGeoIdForTesting(const std::string& geo_id); +std::optional<ip_protection::GeoHint> GetGeoHintFromGeoIdForTesting( + const std::string& geo_id); } // namespace network
diff --git a/services/network/ip_protection/ip_protection_geo_utils_unittest.cc b/services/network/ip_protection/ip_protection_geo_utils_unittest.cc index 7b1d2143..cc5d53d 100644 --- a/services/network/ip_protection/ip_protection_geo_utils_unittest.cc +++ b/services/network/ip_protection/ip_protection_geo_utils_unittest.cc
@@ -7,7 +7,7 @@ #include <optional> #include <string> -#include "services/network/ip_protection/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "testing/gtest/include/gtest/gtest.h" namespace network { @@ -15,9 +15,9 @@ class IpProtectionGeoUtilsTest : public testing::Test {}; TEST_F(IpProtectionGeoUtilsTest, GetGeoIdFromGeoHint_ValidInput) { - GeoHint geo_hint = {.country_code = "US", - .iso_region = "US-CA", - .city_name = "MOUNTAIN VIEW"}; + ip_protection::GeoHint geo_hint = {.country_code = "US", + .iso_region = "US-CA", + .city_name = "MOUNTAIN VIEW"}; std::string geo_id = GetGeoIdFromGeoHint(std::move(geo_hint)); @@ -25,7 +25,7 @@ } TEST_F(IpProtectionGeoUtilsTest, GetGeoIdFromGeoHint_CountryCodeOnly) { - GeoHint geo_hint = { + ip_protection::GeoHint geo_hint = { .country_code = "US", }; @@ -35,7 +35,7 @@ } TEST_F(IpProtectionGeoUtilsTest, GetGeoIdFromGeoHint_EmptyGeoHintPtr) { - std::optional<GeoHint> geo_hint; + std::optional<ip_protection::GeoHint> geo_hint; std::string geo_id = GetGeoIdFromGeoHint(std::move(geo_hint)); @@ -49,26 +49,28 @@ } TEST_F(IpProtectionGeoUtilsTest, GetGeoHintFromGeoIdForTesting_CompleteGeoId) { - std::optional<GeoHint> geo_hint = + std::optional<ip_protection::GeoHint> geo_hint = GetGeoHintFromGeoIdForTesting("US,US-CA,MOUNTAIN VIEW"); - GeoHint expected_geo_hint = {.country_code = "US", - .iso_region = "US-CA", - .city_name = "MOUNTAIN VIEW"}; + ip_protection::GeoHint expected_geo_hint = {.country_code = "US", + .iso_region = "US-CA", + .city_name = "MOUNTAIN VIEW"}; EXPECT_TRUE(geo_hint == expected_geo_hint); } TEST_F(IpProtectionGeoUtilsTest, GetGeoHintFromGeoIdForTesting_CountryOnlyGeoId) { - std::optional<GeoHint> geo_hint = GetGeoHintFromGeoIdForTesting("US"); - GeoHint expected_geo_hint = {.country_code = "US"}; + std::optional<ip_protection::GeoHint> geo_hint = + GetGeoHintFromGeoIdForTesting("US"); + ip_protection::GeoHint expected_geo_hint = {.country_code = "US"}; EXPECT_TRUE(geo_hint == expected_geo_hint); } TEST_F(IpProtectionGeoUtilsTest, GetGeoHintFromGeoIdForTesting_EmptyGeoId) { - std::optional<GeoHint> geo_hint = GetGeoHintFromGeoIdForTesting(""); + std::optional<ip_protection::GeoHint> geo_hint = + GetGeoHintFromGeoIdForTesting(""); EXPECT_TRUE(!geo_hint.has_value()); }
diff --git a/services/network/ip_protection/ip_protection_proxy_delegate.cc b/services/network/ip_protection/ip_protection_proxy_delegate.cc index d4806b1..e4e281f 100644 --- a/services/network/ip_protection/ip_protection_proxy_delegate.cc +++ b/services/network/ip_protection/ip_protection_proxy_delegate.cc
@@ -12,6 +12,8 @@ #include "base/memory/scoped_refptr.h" #include "base/metrics/histogram_functions.h" #include "base/strings/strcat.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "components/ip_protection/common/masked_domain_list_manager.h" #include "net/base/features.h" #include "net/base/proxy_chain.h" @@ -22,7 +24,6 @@ #include "net/proxy_resolution/proxy_info.h" #include "net/proxy_resolution/proxy_resolution_service.h" #include "net/proxy_resolution/proxy_retry_info.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_geo_utils.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager_impl.h" #include "services/network/ip_protection/ip_protection_token_cache_manager_impl.h" @@ -35,28 +36,6 @@ using ip_protection::MaskedDomainListManager; -// An enumeration of the `chain_id` values supplied in the GetProxyInfo RPC -// response, for use with `UmaHistogramEnumeration`. These values are persisted -// to logs. Entries should not be renumbered and numeric values should never be -// reused. -enum class IpProtectionProxyChainId { - kUnknown = 0, - kChain1 = 1, - kChain2 = 2, - kChain3 = 3, - kMaxValue = kChain3, -}; - -IpProtectionProxyChainId ChainIdToEnum(int chain_id) { - static_assert(net::ProxyChain::kMaxIpProtectionChainId == - static_cast<int>(IpProtectionProxyChainId::kMaxValue), - "maximum `chain_id` must match between `net::ProxyChain` and " - "`network::IpProtectionProxyChainId`"); - CHECK(chain_id >= static_cast<int>(IpProtectionProxyChainId::kUnknown) && - chain_id <= static_cast<int>(IpProtectionProxyChainId::kMaxValue)); - return static_cast<IpProtectionProxyChainId>(chain_id); -} - } // namespace IpProtectionProxyDelegate::IpProtectionProxyDelegate( @@ -110,12 +89,7 @@ // - `is_ip_protection_enabled_` is `false` (in other words, the user has // disabled IP Protection via user settings). // - `kIpPrivacyDirectOnly` is `true`. - const ProtectionEligibility eligibility = - CheckEligibility(url, network_anonymization_key); - base::UmaHistogramEnumeration( - "NetworkService.IpProtection.RequestIsEligibleForProtection", - eligibility); - if (eligibility != ProtectionEligibility::kEligible) { + if (!CheckEligibility(url, network_anonymization_key)) { return; } result->set_is_mdl_match(true); @@ -134,9 +108,6 @@ return; } const bool available = CheckAvailability(url, network_anonymization_key); - base::UmaHistogramBoolean( - "NetworkService.IpProtection.ProtectionIsAvailableForRequest", - available); if (!available) { return; } @@ -185,10 +156,12 @@ return; } -IpProtectionProxyDelegate::ProtectionEligibility -IpProtectionProxyDelegate::CheckEligibility( +bool IpProtectionProxyDelegate::CheckEligibility( const GURL& url, const net::NetworkAnonymizationKey& network_anonymization_key) const { + ip_protection::ProtectionEligibility eligibility; + bool eligible; + auto dvlog = [&](std::string message) { std::optional<net::SchemefulSite> top_frame_site = network_anonymization_key.GetTopFrameSite(); @@ -199,14 +172,21 @@ }; if (!masked_domain_list_manager_->IsPopulated()) { dvlog("proxy allow list not populated"); - return ProtectionEligibility::kUnknown; - } - if (!masked_domain_list_manager_->Matches(url, network_anonymization_key)) { + eligibility = ip_protection::ProtectionEligibility::kUnknown; + eligible = false; + } else if (!masked_domain_list_manager_->Matches(url, + network_anonymization_key)) { dvlog("proxy allow list did not match"); - return ProtectionEligibility::kIneligible; + eligibility = ip_protection::ProtectionEligibility::kIneligible; + eligible = false; + } else { + dvlog("proxy allow list matched"); + eligibility = ip_protection::ProtectionEligibility::kEligible; + eligible = true; } - dvlog("proxy allow list matched"); - return ProtectionEligibility::kEligible; + + ip_protection::Telemetry().RequestIsEligibleForProtection(eligibility); + return eligible; } bool IpProtectionProxyDelegate::CheckAvailability( @@ -222,13 +202,10 @@ }; const bool auth_tokens_are_available = ipp_config_cache_->AreAuthTokensAvailable(); - base::UmaHistogramBoolean( - "NetworkService.IpProtection.AreAuthTokensAvailable", - auth_tokens_are_available); const bool proxy_list_is_available = ipp_config_cache_->IsProxyListAvailable(); - base::UmaHistogramBoolean("NetworkService.IpProtection.IsProxyListAvailable", - proxy_list_is_available); + ip_protection::Telemetry().ProtectionIsAvailableForRequest( + auth_tokens_are_available, proxy_list_is_available); if (!auth_tokens_are_available) { dvlog("no auth token available from cache"); return false; @@ -279,9 +256,8 @@ // If the bad proxy was an IP Protection proxy, refresh the list of IP // protection proxies immediately. if (bad_chain.is_for_ip_protection()) { - base::UmaHistogramEnumeration( - "NetworkService.IpProtection.ProxyChainFallback", - ChainIdToEnum(bad_chain.ip_protection_chain_id())); + ip_protection::Telemetry().ProxyChainFallback( + bad_chain.ip_protection_chain_id()); ipp_config_cache_->RequestRefreshProxyList(); } } @@ -294,7 +270,7 @@ VLOG(2) << "NSPD::OnBeforeTunnelRequest() - " << message; }; if (proxy_chain.is_for_ip_protection()) { - std::optional<BlindSignedAuthToken> token = + std::optional<ip_protection::BlindSignedAuthToken> token = ipp_config_cache_->GetAuthToken(chain_index); if (token) { vlog("adding auth token"); @@ -336,7 +312,7 @@ static_cast<IpProtectionTokenCacheManagerImpl*>( ipp_config_cache_ ->GetIpProtectionTokenCacheManagerForTesting( // IN-TEST - IpProtectionProxyLayer::kProxyA)); + ip_protection::ProxyLayer::kProxyA)); CHECK(ipp_token_cache_manager_impl); // If active cache management is enabled (the default), disable it and do a @@ -418,7 +394,7 @@ static_cast<IpProtectionTokenCacheManagerImpl*>( ipp_config_cache_ ->GetIpProtectionTokenCacheManagerForTesting( // IN-TEST - IpProtectionProxyLayer::kProxyA)); + ip_protection::ProxyLayer::kProxyA)); auto* ipp_proxy_list_manager_impl = static_cast<IpProtectionProxyListManagerImpl*>( ipp_config_cache_ @@ -430,7 +406,7 @@ net::ProxyServer::SCHEME_HTTPS, "proxy-a", std::nullopt)})}, network::GetGeoHintFromGeoIdForTesting( ipp_token_cache_manager_impl->CurrentGeo())); - std::optional<BlindSignedAuthToken> result = + std::optional<ip_protection::BlindSignedAuthToken> result = ipp_config_cache_->GetAuthToken(0); // kProxyA. if (result.has_value()) { std::move(callback).Run(std::move(result.value()), std::nullopt);
diff --git a/services/network/ip_protection/ip_protection_proxy_delegate.h b/services/network/ip_protection/ip_protection_proxy_delegate.h index 32f1930..4d4032ac 100644 --- a/services/network/ip_protection/ip_protection_proxy_delegate.h +++ b/services/network/ip_protection/ip_protection_proxy_delegate.h
@@ -9,6 +9,7 @@ #include "base/component_export.h" #include "base/memory/raw_ptr.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "components/ip_protection/common/masked_domain_list_manager.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" @@ -32,13 +33,6 @@ : public net::ProxyDelegate, public mojom::IpProtectionProxyDelegate { public: - enum class ProtectionEligibility { - kUnknown = 0, - kIneligible = 1, - kEligible = 2, - kMaxValue = kEligible, - }; - // Both masked_domain_list_manager and ipp_config_cache must be // non-null. The masked_domain_list_manager (MaskedDomainList) feature // must be enabled. @@ -93,7 +87,7 @@ friend class IpProtectionProxyDelegateTest; FRIEND_TEST_ALL_PREFIXES(IpProtectionProxyDelegateTest, MergeProxyRules); - ProtectionEligibility CheckEligibility( + bool CheckEligibility( const GURL& url, const net::NetworkAnonymizationKey& network_anonymization_key) const; bool CheckAvailability(
diff --git a/services/network/ip_protection/ip_protection_proxy_delegate_unittest.cc b/services/network/ip_protection/ip_protection_proxy_delegate_unittest.cc index 32446d7..5da2617 100644 --- a/services/network/ip_protection/ip_protection_proxy_delegate_unittest.cc +++ b/services/network/ip_protection/ip_protection_proxy_delegate_unittest.cc
@@ -16,6 +16,8 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "components/ip_protection/common/masked_domain_list_manager.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" @@ -29,7 +31,6 @@ #include "net/url_request/url_request_context_builder.h" #include "net/url_request/url_request_test_util.h" #include "services/network/ip_protection/ip_protection_config_cache_impl.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager.h" #include "services/network/ip_protection/ip_protection_token_cache_manager.h" #include "services/network/public/cpp/features.h" @@ -42,7 +43,8 @@ namespace network { namespace { -using ip_protection::MaskedDomainListManager; +using ::ip_protection::MaskedDomainListManager; +using ::ip_protection::ProtectionEligibility; constexpr char kHttpsUrl[] = "https://example.com"; constexpr char kHttpUrl[] = "http://example.com"; @@ -65,14 +67,15 @@ std::move(on_invalidate_try_again_after_time_).Run(); } } - std::optional<BlindSignedAuthToken> GetAuthToken( + std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken( size_t chain_index) override { return std::move(auth_token_); } // Set the auth token that will be returned from the next call to // `GetAuthToken()`. - void SetNextAuthToken(std::optional<BlindSignedAuthToken> auth_token) { + void SetNextAuthToken( + std::optional<ip_protection::BlindSignedAuthToken> auth_token) { auth_token_ = std::move(auth_token); } @@ -83,12 +86,12 @@ } IpProtectionTokenCacheManager* GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer) override { + ip_protection::ProxyLayer proxy_layer) override { NOTREACHED(); } void SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, std::unique_ptr<IpProtectionTokenCacheManager> ipp_token_cache_manager) override { NOTREACHED(); @@ -140,7 +143,7 @@ } private: - std::optional<BlindSignedAuthToken> auth_token_; + std::optional<ip_protection::BlindSignedAuthToken> auth_token_; std::optional<std::vector<net::ProxyChain>> proxy_list_; std::vector<net::ProxyChain> proxy_chain_list_; base::OnceClosure on_force_refresh_proxy_list_; @@ -233,8 +236,8 @@ return net::ProxyChain::ForIpProtection(servers, chain_id); } - BlindSignedAuthToken MakeAuthToken(std::string content) { - BlindSignedAuthToken token; + ip_protection::BlindSignedAuthToken MakeAuthToken(std::string content) { + ip_protection::BlindSignedAuthToken token; token.token = std::move(content); return token; } @@ -362,9 +365,8 @@ EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list)) << "Got: " << result.proxy_list().ToDebugString(); EXPECT_TRUE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kEligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kEligible, 1); histogram_tester_.ExpectUniqueSample(kAreAuthTokensAvailableHistogram, true, 1); histogram_tester_.ExpectUniqueSample(kIsProxyListAvailableHistogram, true, 1); @@ -400,9 +402,8 @@ EXPECT_TRUE(result.is_direct()); EXPECT_FALSE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kEligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kEligible, 1); histogram_tester_.ExpectUniqueSample(kAreAuthTokensAvailableHistogram, true, 1); histogram_tester_.ExpectUniqueSample(kIsProxyListAvailableHistogram, true, 1); @@ -459,9 +460,8 @@ net::NetLogWithSource())); EXPECT_TRUE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kEligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kEligible, 1); histogram_tester_.ExpectUniqueSample(kAreAuthTokensAvailableHistogram, true, 1); histogram_tester_.ExpectUniqueSample(kIsProxyListAvailableHistogram, true, 1); @@ -498,9 +498,8 @@ EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list)) << "Got: " << result.proxy_list().ToDebugString(); EXPECT_TRUE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kEligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kEligible, 1); histogram_tester_.ExpectUniqueSample(kAreAuthTokensAvailableHistogram, true, 1); histogram_tester_.ExpectUniqueSample(kIsProxyListAvailableHistogram, true, 1); @@ -529,9 +528,8 @@ EXPECT_TRUE(result.is_direct()); EXPECT_FALSE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kIneligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kIneligible, 1); histogram_tester_.ExpectTotalCount(kAreAuthTokensAvailableHistogram, 0); histogram_tester_.ExpectTotalCount(kIsProxyListAvailableHistogram, 0); histogram_tester_.ExpectTotalCount(kAvailabilityHistogram, 0); @@ -557,9 +555,8 @@ EXPECT_TRUE(result.is_direct()); EXPECT_FALSE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kEligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kEligible, 1); histogram_tester_.ExpectUniqueSample(kAreAuthTokensAvailableHistogram, false, 1); histogram_tester_.ExpectUniqueSample(kIsProxyListAvailableHistogram, true, 1); @@ -586,9 +583,8 @@ EXPECT_TRUE(result.is_direct()); EXPECT_FALSE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kEligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kEligible, 1); histogram_tester_.ExpectUniqueSample(kAreAuthTokensAvailableHistogram, true, 1); histogram_tester_.ExpectUniqueSample(kIsProxyListAvailableHistogram, false, @@ -618,9 +614,8 @@ EXPECT_TRUE(result.is_direct()); EXPECT_FALSE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kEligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kEligible, 1); histogram_tester_.ExpectTotalCount(kAreAuthTokensAvailableHistogram, 0); histogram_tester_.ExpectTotalCount(kIsProxyListAvailableHistogram, 0); histogram_tester_.ExpectTotalCount(kAvailabilityHistogram, 0); @@ -648,9 +643,8 @@ "GET", net::ProxyRetryInfoMap(), &result); EXPECT_TRUE(result.is_direct()); EXPECT_FALSE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kIneligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kIneligible, 1); histogram_tester_.ExpectTotalCount(kAreAuthTokensAvailableHistogram, 0); histogram_tester_.ExpectTotalCount(kIsProxyListAvailableHistogram, 0); histogram_tester_.ExpectTotalCount(kAvailabilityHistogram, 0); @@ -679,9 +673,8 @@ "GET", net::ProxyRetryInfoMap(), &result); EXPECT_TRUE(result.is_direct()); EXPECT_FALSE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kUnknown, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kUnknown, 1); histogram_tester_.ExpectTotalCount(kAreAuthTokensAvailableHistogram, 0); histogram_tester_.ExpectTotalCount(kIsProxyListAvailableHistogram, 0); histogram_tester_.ExpectTotalCount(kAvailabilityHistogram, 0); @@ -709,9 +702,8 @@ "GET", net::ProxyRetryInfoMap(), &result); EXPECT_FALSE(result.is_direct()); EXPECT_TRUE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kEligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kEligible, 1); histogram_tester_.ExpectUniqueSample(kAreAuthTokensAvailableHistogram, true, 1); histogram_tester_.ExpectUniqueSample(kIsProxyListAvailableHistogram, true, 1); @@ -739,9 +731,8 @@ "GET", net::ProxyRetryInfoMap(), &result); EXPECT_FALSE(result.is_direct()); EXPECT_TRUE(result.is_for_ip_protection()); - histogram_tester_.ExpectUniqueSample( - kEligibilityHistogram, - IpProtectionProxyDelegate::ProtectionEligibility::kEligible, 1); + histogram_tester_.ExpectUniqueSample(kEligibilityHistogram, + ProtectionEligibility::kEligible, 1); histogram_tester_.ExpectUniqueSample(kAreAuthTokensAvailableHistogram, true, 1); histogram_tester_.ExpectUniqueSample(kIsProxyListAvailableHistogram, true, 1);
diff --git a/services/network/ip_protection/ip_protection_proxy_list_manager_impl.cc b/services/network/ip_protection/ip_protection_proxy_list_manager_impl.cc index 8de52e9..70a4050 100644 --- a/services/network/ip_protection/ip_protection_proxy_list_manager_impl.cc +++ b/services/network/ip_protection/ip_protection_proxy_list_manager_impl.cc
@@ -5,15 +5,17 @@ #include "services/network/ip_protection/ip_protection_proxy_list_manager_impl.h" #include <memory> +#include <optional> #include "base/metrics/histogram_functions.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/time/time.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "net/base/features.h" #include "net/base/proxy_chain.h" #include "services/network/ip_protection/ip_protection_config_cache.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_geo_utils.h" namespace network { @@ -28,15 +30,24 @@ // call which means a `proxy_list` with a value of `std::nullopt` would be // returned. Thus, the following function captures all states of failure // accurately even though we only check the `proxy_chain`. -IpProtectionProxyListManagerImpl::ProxyListResult GetProxyListResult( - const std::optional<std::vector<net::ProxyChain>>& proxy_list) { +void RecordTelemetry( + const std::optional<std::vector<net::ProxyChain>>& proxy_list, + base::TimeDelta duration) { + using ::ip_protection::GetProxyListResult; + + GetProxyListResult result; if (!proxy_list.has_value()) { - return IpProtectionProxyListManagerImpl::ProxyListResult::kFailed; + result = GetProxyListResult::kFailed; + } else if (proxy_list->empty()) { + result = GetProxyListResult::kEmptyList; + } else { + result = GetProxyListResult::kPopulatedList; } - if (proxy_list->empty()) { - return IpProtectionProxyListManagerImpl::ProxyListResult::kEmptyList; - } - return IpProtectionProxyListManagerImpl::ProxyListResult::kPopulatedList; + + ip_protection::Telemetry().ProxyListRefreshComplete( + result, result == GetProxyListResult::kFailed + ? std::nullopt + : std::make_optional(duration)); } } // namespace @@ -126,20 +137,15 @@ void IpProtectionProxyListManagerImpl::OnGotProxyList( const base::TimeTicks refresh_start_time_for_metrics, const std::optional<std::vector<net::ProxyChain>> proxy_list, - const std::optional<GeoHint> geo_hint) { + const std::optional<ip_protection::GeoHint> geo_hint) { fetching_proxy_list_ = false; - base::UmaHistogramEnumeration( - "NetworkService.IpProtection.GetProxyListResult", - GetProxyListResult(proxy_list)); + RecordTelemetry(proxy_list, + base::TimeTicks::Now() - refresh_start_time_for_metrics); // If the request for fetching the proxy list is successful, utilize the new // proxy list, otherwise, continue using the existing list, if any. if (proxy_list.has_value()) { - base::UmaHistogramMediumTimes( - "NetworkService.IpProtection.ProxyListRefreshTime", - base::TimeTicks::Now() - refresh_start_time_for_metrics); - proxy_list_ = *proxy_list; have_fetched_proxy_list_ = true;
diff --git a/services/network/ip_protection/ip_protection_proxy_list_manager_impl.h b/services/network/ip_protection/ip_protection_proxy_list_manager_impl.h index e5bc83a4b..893f72c7 100644 --- a/services/network/ip_protection/ip_protection_proxy_list_manager_impl.h +++ b/services/network/ip_protection/ip_protection_proxy_list_manager_impl.h
@@ -13,10 +13,10 @@ #include "base/memory/raw_ref.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "net/base/proxy_chain.h" #include "services/network/ip_protection/ip_protection_config_cache.h" #include "services/network/ip_protection/ip_protection_config_getter.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_geo_utils.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager.h" @@ -27,15 +27,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) IpProtectionProxyListManagerImpl : public IpProtectionProxyListManager { public: - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - enum class ProxyListResult { - kFailed = 0, - kEmptyList = 1, - kPopulatedList = 2, - kMaxValue = kPopulatedList, - }; - explicit IpProtectionProxyListManagerImpl( IpProtectionConfigCache* config_cache, IpProtectionConfigGetter& config_getter, @@ -69,7 +60,7 @@ void SetProxyListForTesting( std::optional<std::vector<net::ProxyChain>> proxy_list, - std::optional<GeoHint> geo_hint) { + std::optional<ip_protection::GeoHint> geo_hint) { current_geo_id_ = network::GetGeoIdFromGeoHint(geo_hint); proxy_list_ = *proxy_list; have_fetched_proxy_list_ = true; @@ -80,7 +71,7 @@ void ScheduleRefreshProxyList(base::TimeDelta delay); void OnGotProxyList(base::TimeTicks refresh_start_time_for_metrics, std::optional<std::vector<net::ProxyChain>> proxy_list, - std::optional<GeoHint> geo_hint); + std::optional<ip_protection::GeoHint> geo_hint); bool IsProxyListOlderThanMinAge() const; // Latest fetched proxy list.
diff --git a/services/network/ip_protection/ip_protection_proxy_list_manager_impl_unittest.cc b/services/network/ip_protection/ip_protection_proxy_list_manager_impl_unittest.cc index d9906d228..14467e24 100644 --- a/services/network/ip_protection/ip_protection_proxy_list_manager_impl_unittest.cc +++ b/services/network/ip_protection/ip_protection_proxy_list_manager_impl_unittest.cc
@@ -16,9 +16,10 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "net/base/features.h" #include "net/base/proxy_chain.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_geo_utils.h" #include "services/network/ip_protection/ip_protection_proxy_list_manager.h" #include "testing/gmock/include/gmock/gmock.h" @@ -72,7 +73,7 @@ bool IsAvailable() override { return true; } void TryGetAuthTokens(uint32_t batch_size, - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, TryGetAuthTokensCallback callback) override { NOTREACHED(); } @@ -99,17 +100,17 @@ // Dummy implementations for functions not tested in this file. bool AreAuthTokensAvailable() override { return false; } - std::optional<BlindSignedAuthToken> GetAuthToken( + std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken( size_t chain_index) override { return std::nullopt; } void InvalidateTryAgainAfterTime() override {} void SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, std::unique_ptr<IpProtectionTokenCacheManager> ipp_token_cache_manager) override {} IpProtectionTokenCacheManager* GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer) override { + ip_protection::ProxyLayer proxy_layer) override { return nullptr; } void SetIpProtectionProxyListManagerForTesting( @@ -515,8 +516,8 @@ ipp_proxy_list_->RequestRefreshProxyList(); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); histogram_tester_.ExpectUniqueSample( - kGetProxyListResultHistogram, - IpProtectionProxyListManagerImpl::ProxyListResult::kFailed, 1); + kGetProxyListResultHistogram, ip_protection::GetProxyListResult::kFailed, + 1); histogram_tester_.ExpectTotalCount(kProxyListRefreshTimeHistogram, 0); } @@ -532,7 +533,7 @@ ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); histogram_tester_.ExpectUniqueSample( kGetProxyListResultHistogram, - IpProtectionProxyListManagerImpl::ProxyListResult::kEmptyList, 1); + ip_protection::GetProxyListResult::kEmptyList, 1); histogram_tester_.ExpectTotalCount(kProxyListRefreshTimeHistogram, 1); } @@ -549,7 +550,7 @@ ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); histogram_tester_.ExpectUniqueSample( kGetProxyListResultHistogram, - IpProtectionProxyListManagerImpl::ProxyListResult::kPopulatedList, 1); + ip_protection::GetProxyListResult::kPopulatedList, 1); histogram_tester_.ExpectTotalCount(kProxyListRefreshTimeHistogram, 1); }
diff --git a/services/network/ip_protection/ip_protection_token_cache_manager.h b/services/network/ip_protection/ip_protection_token_cache_manager.h index 6003574..a7beb2f 100644 --- a/services/network/ip_protection/ip_protection_token_cache_manager.h +++ b/services/network/ip_protection/ip_protection_token_cache_manager.h
@@ -9,8 +9,8 @@ #include <string> #include "base/component_export.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_config_getter.h" -#include "services/network/ip_protection/ip_protection_data_types.h" namespace network { @@ -39,14 +39,14 @@ // Returns `nullopt` if no token is available, whether for a transient or // permanent reason. This method may return `nullopt` even if // `IsAuthTokenAvailable()` recently returned `true`. - virtual std::optional<BlindSignedAuthToken> GetAuthToken() = 0; + virtual std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken() = 0; // Get a token, if one is available. // // Returns `nullopt` if no token is available, whether for a transient or // permanent reason. This method may return `nullopt` even if // `IsAuthTokenAvailable()` recently returned `true`. - virtual std::optional<BlindSignedAuthToken> GetAuthToken( + virtual std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken( const std::string& geo_id) = 0; // Invalidate any previous instruction that token requests should not be made
diff --git a/services/network/ip_protection/ip_protection_token_cache_manager_impl.cc b/services/network/ip_protection/ip_protection_token_cache_manager_impl.cc index fba6055..1adff92c 100644 --- a/services/network/ip_protection/ip_protection_token_cache_manager_impl.cc +++ b/services/network/ip_protection/ip_protection_token_cache_manager_impl.cc
@@ -9,40 +9,19 @@ #include "base/metrics/histogram_functions.h" #include "base/rand_util.h" -#include "base/strings/strcat.h" #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "base/time/time.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "net/base/features.h" #include "services/network/ip_protection/ip_protection_config_cache.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_geo_utils.h" namespace network { namespace { -IpProtectionTokenCacheManagerImpl::AuthTokenResultForGeo -GetAuthTokenResultForGeo(bool is_token_available, - bool is_cache_empty, - bool does_requested_geo_match_current) { - if (is_token_available) { - if (does_requested_geo_match_current) { - return IpProtectionTokenCacheManagerImpl::AuthTokenResultForGeo:: - kAvailableForCurrentGeo; - } - return IpProtectionTokenCacheManagerImpl::AuthTokenResultForGeo:: - kAvailableForOtherCachedGeo; - } - - if (!is_cache_empty) { - return IpProtectionTokenCacheManagerImpl::AuthTokenResultForGeo:: - kUnavailableButCacheContainsTokens; - } - return IpProtectionTokenCacheManagerImpl::AuthTokenResultForGeo:: - kUnavailableCacheEmpty; -} - // Minimum time before actual expiration that a token is considered // "expired" and removed. The maximum time is given by the // `IpPrivacyExpirationFuzz` feature param. @@ -62,10 +41,12 @@ } // namespace +using ::ip_protection::BlindSignedAuthToken; + IpProtectionTokenCacheManagerImpl::IpProtectionTokenCacheManagerImpl( IpProtectionConfigCache* config_cache, IpProtectionConfigGetter* config_getter, - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, bool disable_cache_management_for_testing) : batch_size_(net::features::kIpPrivacyAuthTokenCacheBatchSize.Get()), cache_low_water_mark_( @@ -171,8 +152,7 @@ // Ensuring that a geo change has occurred. if (emitted_geo_presence_histogram_before_refill_ && current_geo_id_ != "" && current_geo_id_ != geo_id) { - base::UmaHistogramBoolean( - "NetworkService.IpProtection.GeoChangeTokenPresence", + ip_protection::Telemetry().GeoChangeTokenPresence( cache_by_geo_.contains(geo_id)); } @@ -322,8 +302,7 @@ bool has_geo_id_changed = geo_id_from_token != current_geo_id_; if (enable_token_caching_by_geo_ && has_geo_id_changed && current_geo_id_ != "") { - base::UmaHistogramBoolean( - "NetworkService.IpProtection.GeoChangeTokenPresence", + ip_protection::Telemetry().GeoChangeTokenPresence( cache_by_geo_.contains(geo_id_from_token)); emitted_geo_presence_histogram_before_refill_ = false; } @@ -364,8 +343,7 @@ ip_protection_config_cache_->GeoObserved(geo_id_from_token); } - base::UmaHistogramMediumTimes( - "NetworkService.IpProtection.TokenBatchGenerationTime", + ip_protection::Telemetry().TokenBatchGenerationComplete( base::TimeTicks::Now() - attempt_start_time_for_metrics); if (on_try_get_auth_tokens_completed_for_testing_) { @@ -399,15 +377,9 @@ tokens_spent_++; } - if (enable_token_caching_by_geo_) { - base::UmaHistogramEnumeration( - "NetworkService.IpProtection.GetAuthTokenResultForGeo", - GetAuthTokenResultForGeo(result.has_value(), cache_by_geo_.empty(), - geo_id == current_geo_id_)); - } - - base::UmaHistogramBoolean("NetworkService.IpProtection.GetAuthTokenResult", - tokens_in_cache > 0); + ip_protection::Telemetry().GetAuthTokenResultForGeo( + result.has_value(), enable_token_caching_by_geo_, cache_by_geo_.empty(), + geo_id == current_geo_id_); VLOG(2) << "IPPATC::GetAuthToken with " << tokens_in_cache << " tokens available"; MaybeRefillCache(); @@ -447,28 +419,16 @@ last_token_rate_measurement_ = now; auto spend_rate = tokens_spent_ * denominator / interval_ms; - std::string proxy_layer = [&] { - switch (proxy_layer_) { - case IpProtectionProxyLayer::kProxyA: - return "ProxyA"; - case IpProtectionProxyLayer::kProxyB: - return "ProxyB"; - } - }(); // A maximum of 1000 would correspond to a spend rate of about 16/min, // which is higher than we expect to see. - base::UmaHistogramCounts1000(base::StrCat({"NetworkService.IpProtection.", - proxy_layer, ".TokenSpendRate"}), - spend_rate); + ip_protection::Telemetry().TokenSpendRate(proxy_layer_, spend_rate); auto expiration_rate = tokens_expired_ * denominator / interval_ms; // Entire batches of tokens are likely to expire within a single 5-minute // measurement interval. 1024 tokens in 5 minutes is equivalent to 12288 // tokens per hour, comfortably under 100,000. - base::UmaHistogramCounts100000( - base::StrCat({"NetworkService.IpProtection.", proxy_layer, - ".TokenExpirationRate"}), - expiration_rate); + ip_protection::Telemetry().TokenExpirationRate(proxy_layer_, + expiration_rate); } last_token_rate_measurement_ = now;
diff --git a/services/network/ip_protection/ip_protection_token_cache_manager_impl.h b/services/network/ip_protection/ip_protection_token_cache_manager_impl.h index c35c131..8fa6134 100644 --- a/services/network/ip_protection/ip_protection_token_cache_manager_impl.h +++ b/services/network/ip_protection/ip_protection_token_cache_manager_impl.h
@@ -16,9 +16,9 @@ #include "base/sequence_checker.h" #include "base/time/time.h" #include "base/timer/timer.h" +#include "components/ip_protection/common/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_config_cache.h" #include "services/network/ip_protection/ip_protection_config_getter.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_token_cache_manager.h" namespace network { @@ -28,31 +28,18 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) IpProtectionTokenCacheManagerImpl : public IpProtectionTokenCacheManager { public: - // These values are persisted to logs. Entries should not be renumbered and - // numeric values should never be reused. - // - // LINT.IfChange(AuthTokenResultForGeo) - enum class AuthTokenResultForGeo { - kUnavailableCacheEmpty = 0, - kUnavailableButCacheContainsTokens = 1, - kAvailableForCurrentGeo = 2, - kAvailableForOtherCachedGeo = 3, - kMaxValue = kAvailableForOtherCachedGeo, - }; - // LINT.ThenChange(//tools/metrics/histograms/metadata/network/enums.xml:IpProtectionGetAuthTokenResultForGeo) - explicit IpProtectionTokenCacheManagerImpl( IpProtectionConfigCache* config_cache, IpProtectionConfigGetter* config_getter, - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, bool disable_cache_management_for_testing = false); ~IpProtectionTokenCacheManagerImpl() override; // IpProtectionTokenCacheManager implementation. bool IsAuthTokenAvailable() override; bool IsAuthTokenAvailable(const std::string& geo_id) override; - std::optional<BlindSignedAuthToken> GetAuthToken() override; - std::optional<BlindSignedAuthToken> GetAuthToken( + std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken() override; + std::optional<ip_protection::BlindSignedAuthToken> GetAuthToken( const std::string& geo_id) override; std::string CurrentGeo() const override; void SetCurrentGeo(const std::string& geo_id) override; @@ -94,9 +81,10 @@ bool fetching_auth_tokens_for_testing() { return fetching_auth_tokens_; } private: - void OnGotAuthTokens(base::TimeTicks attempt_start_time_for_metrics, - std::optional<std::vector<BlindSignedAuthToken>> tokens, - std::optional<base::Time> try_again_after); + void OnGotAuthTokens( + base::TimeTicks attempt_start_time_for_metrics, + std::optional<std::vector<ip_protection::BlindSignedAuthToken>> tokens, + std::optional<base::Time> try_again_after); void RemoveExpiredTokens(); void MeasureTokenRates(); void MaybeRefillCache(); @@ -124,13 +112,14 @@ // Map for caches of tokens keyed by geo id. For each geo entry, tokens are // sorted by their expiration time. - std::map<std::string, std::deque<BlindSignedAuthToken>> cache_by_geo_; + std::map<std::string, std::deque<ip_protection::BlindSignedAuthToken>> + cache_by_geo_; // Source of proxy list, when needed. raw_ptr<IpProtectionConfigGetter> config_getter_; // The proxy layer which the cache of tokens will be used for. - IpProtectionProxyLayer proxy_layer_; + ip_protection::ProxyLayer proxy_layer_; // Pointer to the `IpProtectionConfigCache` that holds the proxy list and // tokens. Required to observe geo changes from retrieved tokens.
diff --git a/services/network/ip_protection/ip_protection_token_cache_manager_impl_unittest.cc b/services/network/ip_protection/ip_protection_token_cache_manager_impl_unittest.cc index 909cce7e..1ab94b5c4 100644 --- a/services/network/ip_protection/ip_protection_token_cache_manager_impl_unittest.cc +++ b/services/network/ip_protection/ip_protection_token_cache_manager_impl_unittest.cc
@@ -16,9 +16,10 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/task_environment.h" +#include "components/ip_protection/common/ip_protection_data_types.h" +#include "components/ip_protection/common/ip_protection_telemetry.h" #include "net/base/features.h" #include "services/network/ip_protection/ip_protection_config_cache.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/ip_protection/ip_protection_geo_utils.h" #include "services/network/ip_protection/ip_protection_token_cache_manager.h" #include "testing/gtest/include/gtest/gtest.h" @@ -29,6 +30,8 @@ constexpr char kGeoChangeTokenPresence[] = "NetworkService.IpProtection.GeoChangeTokenPresence"; +using ::ip_protection::BlindSignedAuthToken; + constexpr char kGetAuthTokenResultHistogram[] = "NetworkService.IpProtection.GetAuthTokenResult"; constexpr char kProxyATokenSpendRateHistogram[] = @@ -50,15 +53,15 @@ const bool kEnableTokenCacheByGeo = true; const bool kDisableTokenCacheByGeo = false; -const GeoHint kMountainViewGeo = {.country_code = "US", - .iso_region = "US-CA", - .city_name = "MOUNTAIN VIEW"}; +const ip_protection::GeoHint kMountainViewGeo = {.country_code = "US", + .iso_region = "US-CA", + .city_name = "MOUNTAIN VIEW"}; const std::string kMountainViewGeoId = network::GetGeoIdFromGeoHint(kMountainViewGeo); -const GeoHint kSunnyvaleGeo = {.country_code = "US", - .iso_region = "US-CA", - .city_name = "SUNNYVALE"}; +const ip_protection::GeoHint kSunnyvaleGeo = {.country_code = "US", + .iso_region = "US-CA", + .city_name = "SUNNYVALE"}; const std::string kSunnyvaleGeoId = network::GetGeoIdFromGeoHint(kSunnyvaleGeo); struct ExpectedTryGetAuthTokensCall { @@ -109,7 +112,7 @@ bool IsAvailable() override { return true; } void TryGetAuthTokens(uint32_t batch_size, - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, TryGetAuthTokensCallback callback) override { ASSERT_FALSE(expected_try_get_auth_token_calls_.empty()) << "Unexpected call to TryGetAuthTokens"; @@ -137,11 +140,11 @@ } void InvalidateTryAgainAfterTime() override {} void SetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer, + ip_protection::ProxyLayer proxy_layer, std::unique_ptr<IpProtectionTokenCacheManager> ipp_token_cache_manager) override {} IpProtectionTokenCacheManager* GetIpProtectionTokenCacheManagerForTesting( - IpProtectionProxyLayer proxy_layer) override { + ip_protection::ProxyLayer proxy_layer) override { return nullptr; } void SetIpProtectionProxyListManagerForTesting( @@ -197,11 +200,11 @@ ipp_proxy_a_token_cache_manager_ = std::make_unique<IpProtectionTokenCacheManagerImpl>( - &mock_config_cache_, &mock_, IpProtectionProxyLayer::kProxyA, + &mock_config_cache_, &mock_, ip_protection::ProxyLayer::kProxyA, /* disable_cache_management_for_testing=*/true); ipp_proxy_b_token_cache_manager_ = std::make_unique<IpProtectionTokenCacheManagerImpl>( - &mock_config_cache_, &mock_, IpProtectionProxyLayer::kProxyB, + &mock_config_cache_, &mock_, ip_protection::ProxyLayer::kProxyB, /* disable_cache_management_for_testing=*/true); // Default to disabling token expiration fuzzing. @@ -224,7 +227,7 @@ std::vector<BlindSignedAuthToken> TokenBatch( int count, base::Time expiration, - GeoHint geo_hint = kMountainViewGeo) { + ip_protection::GeoHint geo_hint = kMountainViewGeo) { std::vector<BlindSignedAuthToken> tokens; for (int i = 0; i < count; i++) { tokens.emplace_back( @@ -235,8 +238,8 @@ return tokens; } - void CallTryGetAuthTokensAndWait(IpProtectionProxyLayer proxy_layer) { - if (proxy_layer == IpProtectionProxyLayer::kProxyA) { + void CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer proxy_layer) { + if (proxy_layer == ip_protection::ProxyLayer::kProxyA) { ipp_proxy_a_token_cache_manager_ ->SetOnTryGetAuthTokensCompletedForTesting( task_environment_.QuitClosure()); @@ -251,8 +254,9 @@ } // Wait until the cache fills itself. - void WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer proxy_layer) { - if (proxy_layer == IpProtectionProxyLayer::kProxyA) { + void WaitForTryGetAuthTokensCompletion( + ip_protection::ProxyLayer proxy_layer) { + if (proxy_layer == ip_protection::ProxyLayer::kProxyA) { ipp_proxy_a_token_cache_manager_ ->SetOnTryGetAuthTokensCompletedForTesting( task_environment_.QuitClosure()); @@ -307,7 +311,7 @@ mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1, kFutureExpiration, kSunnyvaleGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Looking for geo that is not found in the token. In this case, only @@ -324,7 +328,7 @@ mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, TokenBatch(1, kFutureExpiration)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); EXPECT_TRUE(ipp_proxy_a_token_cache_manager_->IsAuthTokenAvailable()); @@ -338,7 +342,7 @@ mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1, kFutureExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); EXPECT_TRUE(ipp_proxy_a_token_cache_manager_->IsAuthTokenAvailable( @@ -353,7 +357,7 @@ mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, TokenBatch(1, kPastExpiration)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); EXPECT_FALSE(ipp_proxy_a_token_cache_manager_->IsAuthTokenAvailable()); } @@ -367,7 +371,7 @@ // Expired tokens added mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1, kPastExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); EXPECT_FALSE(ipp_proxy_a_token_cache_manager_->IsAuthTokenAvailable( @@ -393,9 +397,7 @@ ExpectHistogramState(HistogramState{.success = 0, .failure = 1}); histogram_tester_.ExpectUniqueSample( kGetAuthTokenResultForGeoHistogram, - IpProtectionTokenCacheManagerImpl::AuthTokenResultForGeo:: - kUnavailableCacheEmpty, - 1); + ip_protection::AuthTokenResultForGeo::kUnavailableCacheEmpty, 1); } // `GetAuthToken()` returns a token on a cache containing unexpired tokens. @@ -404,7 +406,7 @@ mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1, kFutureExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); std::optional<BlindSignedAuthToken> token = ipp_proxy_a_token_cache_manager_->GetAuthToken(); @@ -426,7 +428,7 @@ mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1, kFutureExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); std::optional<BlindSignedAuthToken> token = @@ -440,9 +442,7 @@ HistogramState{.success = 1, .failure = 0, .generated = 1}); histogram_tester_.ExpectUniqueSample( kGetAuthTokenResultForGeoHistogram, - IpProtectionTokenCacheManagerImpl::AuthTokenResultForGeo:: - kAvailableForCurrentGeo, - 1); + ip_protection::AuthTokenResultForGeo::kAvailableForCurrentGeo, 1); } // `GetAuthToken()` requested for geo not available while other tokens are @@ -455,7 +455,7 @@ // Cache contains Mountain view geo tokens. mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1, kFutureExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Requesting token from geo that is not Mountain View. @@ -467,8 +467,7 @@ HistogramState{.success = 0, .failure = 1, .generated = 1}); histogram_tester_.ExpectUniqueSample( kGetAuthTokenResultForGeoHistogram, - IpProtectionTokenCacheManagerImpl::AuthTokenResultForGeo:: - kUnavailableButCacheContainsTokens, + ip_protection::AuthTokenResultForGeo::kUnavailableButCacheContainsTokens, 1); } @@ -478,7 +477,7 @@ mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, TokenBatch(1, kPastExpiration)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); EXPECT_FALSE(ipp_proxy_a_token_cache_manager_->GetAuthToken()); ExpectHistogramState( @@ -493,7 +492,7 @@ // Expired tokens added. mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1, kPastExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); EXPECT_FALSE( ipp_proxy_a_token_cache_manager_->GetAuthToken(kMountainViewGeoId)); @@ -529,7 +528,7 @@ mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1, kFutureExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); EXPECT_EQ(ipp_proxy_a_token_cache_manager_->CurrentGeo(), kMountainViewGeoId); @@ -543,7 +542,7 @@ mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(cache_low_water_mark_ - 1, kFutureExpiration)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); ASSERT_TRUE(ipp_proxy_a_token_cache_manager_->IsAuthTokenAvailable( @@ -568,7 +567,7 @@ const base::TimeDelta kBackoff = base::Seconds(10); mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, base::Time::Now() + kBackoff); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); ASSERT_FALSE(ipp_proxy_a_token_cache_manager_->IsAuthTokenAvailable( @@ -590,7 +589,7 @@ .expiration = kFutureExpiration, .geo_hint = kMountainViewGeo}); mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, std::move(tokens)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); auto got_token = @@ -610,7 +609,7 @@ std::vector<BlindSignedAuthToken> tokens = TokenBatch(1, kFutureExpiration, kMountainViewGeo); mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, std::move(tokens)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); auto got_token = @@ -627,7 +626,7 @@ TEST_F(IpProtectionTokenCacheManagerImplTest, NullGetter) { MockIpProtectionConfigCache config_cache; auto ipp_token_cache_manager = IpProtectionTokenCacheManagerImpl( - &config_cache, nullptr, IpProtectionProxyLayer::kProxyA, + &config_cache, nullptr, ip_protection::ProxyLayer::kProxyA, /* disable_cache_management_for_testing=*/true); EXPECT_FALSE( @@ -647,7 +646,7 @@ // Fill the cache with 5 tokens. mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(5, kFutureExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Get four tokens from the batch. @@ -688,7 +687,7 @@ mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1024, kPastExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Try to get a token, which will incidentally record the expired tokens. @@ -720,7 +719,7 @@ // Fill the cache with 5 tokens. mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(5, kFutureExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyB); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyB); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Get four tokens from the batch. @@ -761,7 +760,7 @@ mock_.ExpectTryGetAuthTokensCall( expected_batch_size_, TokenBatch(1024, kPastExpiration, kMountainViewGeo)); - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyB); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyB); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Try to get a token, which will incidentally record the expired tokens. @@ -795,7 +794,7 @@ expected_batch_size_, TokenBatch(expected_batch_size_, kFutureExpiration, kMountainViewGeo)); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); EXPECT_TRUE(ipp_proxy_a_token_cache_manager_->IsAuthTokenAvailable( kMountainViewGeoId)); @@ -816,7 +815,7 @@ expected_batch_size_, TokenBatch(expected_batch_size_, kFutureExpiration, kMountainViewGeo)); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Spend tokens down to (but not below) the low-water mark. @@ -850,18 +849,18 @@ base::Time try_again_at = base::Time::Now() + base::Seconds(20); mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, try_again_at); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); base::Time try_again_at_2 = base::Time::Now() + base::Seconds(20); mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, try_again_at_2); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); EXPECT_EQ(base::Time::Now(), try_again_at); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); base::Time try_again_at_3 = base::Time::Now() + base::Seconds(20); mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, try_again_at_3); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); EXPECT_EQ(base::Time::Now(), try_again_at_2); } @@ -896,7 +895,7 @@ mock_.ExpectTryGetAuthTokensCall(expected_batch_size_, std::move(tokens)); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // After the first expiration, tokens should still be available and no @@ -947,7 +946,7 @@ expected_batch_size_, TokenBatch(expected_batch_size_, kFutureExpiration, kMountainViewGeo)); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Spend tokens down to (but not below) the low-water mark. @@ -970,7 +969,7 @@ ipp_proxy_a_token_cache_manager_->GetAuthToken(kMountainViewGeoId)); // Tokens should contain the new geo. - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // New geo should return a valid token. @@ -996,7 +995,7 @@ expected_batch_size_, TokenBatch(expected_batch_size_, kFutureExpiration, kMountainViewGeo)); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Spend tokens down to (but not below) the low-water mark. @@ -1018,7 +1017,7 @@ ipp_proxy_a_token_cache_manager_->GetAuthToken(kMountainViewGeoId)); // New tokens should contain new geo. - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Old Geo can still be used if tokens are available. @@ -1029,9 +1028,7 @@ // geo. histogram_tester_.ExpectBucketCount( kGetAuthTokenResultForGeoHistogram, - IpProtectionTokenCacheManagerImpl::AuthTokenResultForGeo:: - kAvailableForOtherCachedGeo, - 1); + ip_protection::AuthTokenResultForGeo::kAvailableForOtherCachedGeo, 1); } // Existing state with valid non-expired tokens. `SetCurrentGeo` is called @@ -1059,7 +1056,7 @@ expected_batch_size_, TokenBatch(expected_batch_size_, kFutureExpiration, kMountainViewGeo)); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Contains Valid Tokens. @@ -1104,7 +1101,7 @@ expected_batch_size_, TokenBatch(expected_batch_size_, kFutureExpiration, kMountainViewGeo)); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Cache should have valid tokens now. New Sunnyvale geo will be set to @@ -1170,7 +1167,7 @@ expected_batch_size_, TokenBatch(expected_batch_size_, kFutureExpiration, kMountainViewGeo)); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Spend tokens down to (but not below) the low-water mark. @@ -1189,7 +1186,7 @@ ASSERT_TRUE( ipp_proxy_a_token_cache_manager_->GetAuthToken(kMountainViewGeoId)); // Tokens should contain the new geo. - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Spend tokens down to (but not below) the low-water mark. @@ -1207,7 +1204,7 @@ // Triggers new token retrieval. ASSERT_TRUE(ipp_proxy_a_token_cache_manager_->GetAuthToken(kSunnyvaleGeoId)); // Tokens should contain the new geo. - CallTryGetAuthTokensAndWait(IpProtectionProxyLayer::kProxyA); + CallTryGetAuthTokensAndWait(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // There was a two geo changes not counting the prefill: Mountain View -> @@ -1243,7 +1240,7 @@ expected_batch_size_, TokenBatch(expected_batch_size_, kFutureExpiration, kMountainViewGeo)); ipp_proxy_a_token_cache_manager_->EnableCacheManagementForTesting(); - WaitForTryGetAuthTokensCompletion(IpProtectionProxyLayer::kProxyA); + WaitForTryGetAuthTokensCompletion(ip_protection::ProxyLayer::kProxyA); ASSERT_TRUE(mock_.GotAllExpectedMockCalls()); // Contains Valid Tokens.
diff --git a/services/network/public/cpp/ip_protection_data_types_mojom_traits.cc b/services/network/public/cpp/ip_protection_data_types_mojom_traits.cc index ad127123c..4d1cea89 100644 --- a/services/network/public/cpp/ip_protection_data_types_mojom_traits.cc +++ b/services/network/public/cpp/ip_protection_data_types_mojom_traits.cc
@@ -8,18 +8,17 @@ #include "mojo/public/cpp/bindings/struct_traits.h" namespace mojo { -bool StructTraits<network::mojom::GeoHintDataView, network::GeoHint>::Read( - network::mojom::GeoHintDataView data, - network::GeoHint* out) { +bool StructTraits<network::mojom::GeoHintDataView, ip_protection::GeoHint>:: + Read(network::mojom::GeoHintDataView data, ip_protection::GeoHint* out) { return data.ReadCountryCode(&out->country_code) && data.ReadIsoRegion(&out->iso_region) && data.ReadCityName(&out->city_name); } bool StructTraits<network::mojom::BlindSignedAuthTokenDataView, - network::BlindSignedAuthToken>:: + ip_protection::BlindSignedAuthToken>:: Read(network::mojom::BlindSignedAuthTokenDataView data, - network::BlindSignedAuthToken* out) { + ip_protection::BlindSignedAuthToken* out) { return data.ReadToken(&out->token) && data.ReadExpiration(&out->expiration) && data.ReadGeoHint(&out->geo_hint); }
diff --git a/services/network/public/cpp/ip_protection_data_types_mojom_traits.h b/services/network/public/cpp/ip_protection_data_types_mojom_traits.h index 01330bf..f6e72e0 100644 --- a/services/network/public/cpp/ip_protection_data_types_mojom_traits.h +++ b/services/network/public/cpp/ip_protection_data_types_mojom_traits.h
@@ -5,29 +5,30 @@ #ifndef SERVICES_NETWORK_PUBLIC_CPP_IP_PROTECTION_DATA_TYPES_MOJOM_TRAITS_H_ #define SERVICES_NETWORK_PUBLIC_CPP_IP_PROTECTION_DATA_TYPES_MOJOM_TRAITS_H_ +#include "components/ip_protection/common/ip_protection_data_types.h" #include "mojo/public/cpp/bindings/struct_traits.h" #include "mojo/public/mojom/base/time.mojom-shared.h" -#include "services/network/ip_protection/ip_protection_data_types.h" #include "services/network/public/mojom/network_context.mojom-shared.h" namespace mojo { -// Converts network::mojom::GeoHint to/from GeoHint, -// so that GeoHint can be used throughout the codebase without any -// direct reference to network::mojom::GeoHint. +// Converts network::mojom::GeoHint to/from ip_protection::GeoHint, +// so that ip_protection::GeoHint can be used throughout the codebase without +// any direct reference to network::mojom::GeoHint. template <> -struct StructTraits<network::mojom::GeoHintDataView, network::GeoHint> { - static const std::string& country_code(const network::GeoHint& r) { +struct StructTraits<network::mojom::GeoHintDataView, ip_protection::GeoHint> { + static const std::string& country_code(const ip_protection::GeoHint& r) { return r.country_code; } - static const std::string& iso_region(const network::GeoHint& r) { + static const std::string& iso_region(const ip_protection::GeoHint& r) { return r.iso_region; } - static const std::string& city_name(const network::GeoHint& r) { + static const std::string& city_name(const ip_protection::GeoHint& r) { return r.city_name; } // If Read() returns false, Mojo will discard the message. - static bool Read(network::mojom::GeoHintDataView data, network::GeoHint* out); + static bool Read(network::mojom::GeoHintDataView data, + ip_protection::GeoHint* out); }; // Converts network::mojom::BlindSignedAuthToken to/from BlindSignedAuthToken, @@ -35,21 +36,23 @@ // direct reference to network::mojom::BlindSignedAuthToken. template <> struct StructTraits<network::mojom::BlindSignedAuthTokenDataView, - network::BlindSignedAuthToken> { - static const std::string& token(const network::BlindSignedAuthToken& r) { + ip_protection::BlindSignedAuthToken> { + static const std::string& token( + const ip_protection::BlindSignedAuthToken& r) { return r.token; } - static const base::Time& expiration(const network::BlindSignedAuthToken& r) { + static const base::Time& expiration( + const ip_protection::BlindSignedAuthToken& r) { return r.expiration; } - static const network::GeoHint& geo_hint( - const network::BlindSignedAuthToken& r) { + static const ip_protection::GeoHint& geo_hint( + const ip_protection::BlindSignedAuthToken& r) { return r.geo_hint; } // If Read() returns false, Mojo will discard the message. static bool Read(network::mojom::BlindSignedAuthTokenDataView data, - network::BlindSignedAuthToken* out); + ip_protection::BlindSignedAuthToken* out); }; } // namespace mojo #endif // SERVICES_NETWORK_PUBLIC_CPP_IP_PROTECTION_DATA_TYPES_MOJOM_TRAITS_H_
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn index a0a795d..e682e5b 100644 --- a/services/network/public/mojom/BUILD.gn +++ b/services/network/public/mojom/BUILD.gn
@@ -1635,11 +1635,11 @@ types = [ { mojom = "network.mojom.GeoHint" - cpp = "::network::GeoHint" + cpp = "::ip_protection::GeoHint" }, { mojom = "network.mojom.BlindSignedAuthToken" - cpp = "::network::BlindSignedAuthToken" + cpp = "::ip_protection::BlindSignedAuthToken" }, ] traits_headers = [
diff --git a/services/webnn/dml/graph_impl_dml.cc b/services/webnn/dml/graph_impl_dml.cc index 82052aa2..33e59001 100644 --- a/services/webnn/dml/graph_impl_dml.cc +++ b/services/webnn/dml/graph_impl_dml.cc
@@ -749,9 +749,13 @@ std::vector<uint64_t> output_ids; }; -OperationConnectivity GetOperationConnectivity(const Operation* operation) { - std::vector<uint64_t> input_ids; - std::vector<uint64_t> output_ids; +void RetrieveOperationConnectivity( + const Operation* operation, + OperationConnectivity& out_operation_connectivity) { + std::vector<uint64_t>& input_ids = out_operation_connectivity.input_ids; + std::vector<uint64_t>& output_ids = out_operation_connectivity.output_ids; + input_ids.clear(); + output_ids.clear(); switch (operation->which()) { case Operation::Tag::kArgMinMax: { const auto& arg_min_max = operation->get_arg_min_max(); @@ -1096,9 +1100,6 @@ break; } } - - return OperationConnectivity{.input_ids = std::move(input_ids), - .output_ids = std::move(output_ids)}; } // The struct contains the information of graph fusion. In `CreateAndBuild` @@ -1224,11 +1225,13 @@ // Iterate from the end of operations instead from the beginning, so we // can easily get the total output edges count of a fusible base operation // before visiting it. + OperationConnectivity operation_connectivity; for (size_t operation_index = graph_info->operations.size(); operation_index-- > 0;) { const auto& operation = graph_info->operations[operation_index]; - const OperationConnectivity operation_connectivity = - GetOperationConnectivity(operation.get()); + RetrieveOperationConnectivity( + operation.get(), + /*out_operation_connectivity*/ operation_connectivity); for (uint64_t input_id : operation_connectivity.input_ids) { ++node_output_edge_counts.at(input_id);
diff --git a/testing/buildbot/README.md b/testing/buildbot/README.md index 545ffc5f..81501bb2d 100644 --- a/testing/buildbot/README.md +++ b/testing/buildbot/README.md
@@ -19,13 +19,6 @@ [tests in starlark]: /infra/config/targets#tests-in-starlark -*** note -**NOTE:** information in many of the .pyl files listed here will be migrated to -starlark in the near-to-medium future, so if you are accustomed to modifying -these files, see [here][tests in starlark] for information on files that have -been migrated. -*** - * <builder_group\>.json -- test configuration json files. These are used to configure what tests are run on what builders, in addition to specifying builder-specific arguments and parameters. They are autogenerated, mainly @@ -36,26 +29,16 @@ * [waterfalls.pyl](./waterfalls.pyl) -- describes the bots on the various waterfalls, and which test suites they run. By design, this file can only refer (by name) to test suites that are defined in test_suites.pyl. -* [test_suites.pyl](./test_suites.pyl) -- describes the test suites that are -referred to by waterfalls.pyl. A test suite describes groups of tests that are -run on one or more bots. This file is actually generated from starlark -definitions (see [here][tests in starlark]). * [mixins.pyl](./mixins.pyl) -- describes reusable bits of configuration that can be used to modify the expansion of tests from waterfalls.pyl into the -generated test specs. This file is actually generated from starlark definitions -(see [here][tests in starlark]). -* [variants.pyl](./variants.pyl) -- describes reusable bits of configuration -that can be used to expand a single test suite into multiple test specs so that -a test can be run under multiple configurations. This file is actually generated -from starlark definitions (see [here][tests in starlark]). +generated test specs. This file isn't actually used by when generating files in +this directory, instead it uses the one generated from starlark (see below). +This file needs to exist here for the generation of the targets json files in +the angle repo. * [test_suite_exceptions.pyl](./test_suite_exceptions.pyl) -- describes exceptions to the test suites, for example excluding a particular test from running on one bot. The goal is to have very few or no exceptions, which is why this information is factored into a separate file. -* [gn_isolate_map.pyl](./gn_isolate_map.pyl) -- maps Ninja build target names to -GN labels. Allows for certain overrides to get certain tests targets to work -with GN (and properly run when isolated). This file is actually generated from -starlark definitions (see [here][tests in starlark]). * [trybot_analyze_config.json](./trybot_analyze_config.json) -- used to provide exclusions to [the analyze step](https://www.chromium.org/developers/testing/commit-queue/chromium_trybot-json) @@ -65,6 +48,31 @@ * [check.py](./check.py) -- makes sure the buildbot configuration json satisifies certain criteria. +*** note +**NOTE:** this directory has been updated to get non-builder specific +information (mixins, test suites, variants and binary information) from files +generated by starlark. The following files are read from +[/infra/config/generated/testing](/infra/config/generated/testing) when +generating the .json files in this directory. Other uses of this script will +contain hand-written versions of these files in the same directory as their +waterfalls.pyl and test_suites_exceptions.pyl. See [here][tests in starlark] for +information on files that have been migrated. +*** + +* [test_suites.pyl](/infra/config/generated/testing/test_suites.pyl) -- +describes the test suites that are referred to by waterfalls.pyl. A test suite +describes groups of tests that are run on one or more bots. +* [mixins.pyl](/infra/config/generated/testing/mixins.pyl) -- describes reusable +bits of configuration that can be used to modify the expansion of tests from +waterfalls.pyl into the generated test specs. +* [variants.pyl](/infra/config/generated/testing/variants.pyl) -- describes +reusable bits of configuration that can be used to expand a single test suite +into multiple test specs so that a test can be run under multiple +configurations. +* [gn_isolate_map.pyl](/infra/config/generated/testing/gn_isolate_map.pyl) -- +maps Ninja build target names to GN labels. Allows for certain overrides to get +certain tests targets to work with GN (and properly run when isolated). + ## How the files are consumed ### Buildbot configuration json Logic in the
diff --git a/testing/buildbot/check.py b/testing/buildbot/check.py index a9a49ac..5511051 100755 --- a/testing/buildbot/check.py +++ b/testing/buildbot/check.py
@@ -150,7 +150,10 @@ parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__) parser.parse_args() - with open(os.path.join(THIS_DIR, 'gn_isolate_map.pyl')) as fp: + gn_isolate_map_pyl_path = os.path.normpath( + os.path.join(THIS_DIR, '..', '..', 'infra', 'config', 'generated', + 'testing', 'gn_isolate_map.pyl')) + with open(gn_isolate_map_pyl_path) as fp: gn_isolate_map = ast.literal_eval(fp.read()) ninja_targets = {k: v['label'] for k, v in gn_isolate_map.items()}
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 1316b710..9fb5260 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -10810,7 +10810,6 @@ "--recover-devices" ], "description": "Run with android_35_google_apis_x64", - "experiment_percentage": 100, "merge": { "args": [ "--bucket", @@ -13103,7 +13102,6 @@ "--recover-devices" ], "description": "Run with android_35_google_apis_x64", - "experiment_percentage": 100, "merge": { "args": [ "--bucket", @@ -13196,7 +13194,7 @@ "--webview-process-mode=multiple", "--emulator-debug-tags=all", "--avd-config=../../tools/android/avd/proto/android_35_google_apis_x64.textpb", - "--test-launcher-filter-file=../../testing/buildbot/filters/android.14.webview_instrumentation_test_apk.filter", + "--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter", "--gs-results-bucket=chromium-result-details", "--recover-devices" ],
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index c35c390..1b85492 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -455,6 +455,7 @@ data = [ "//testing/buildbot/filters/android.emulator.webview_instrumentation_test_apk.filter", "//testing/buildbot/filters/android.14.webview_instrumentation_test_apk.filter", + "//testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter", ] }
diff --git a/testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter b/testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter new file mode 100644 index 0000000..ea7f2d3 --- /dev/null +++ b/testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter
@@ -0,0 +1,13 @@ +# crbug.com/351017155 +-org.chromium.android_webview.test.VariationsSeedLoaderTest.testFinchSeedExpirationAgeFlag + +# crbug.com/354846826 +-org.chromium.android_webview.test.AwAutofillTest.testAutofillTriggersAfterReload +-org.chromium.android_webview.test.AwAutofillTest.testTouchingFormWithAdjustResize +-org.chromium.android_webview.test.AwAutofillTest.testTouchingPasswordFieldTriggerQuery + +# crbug.com/362633222 +-org.chromium.android_webview.test.ContextMenuTest.testDismissContextMenuOnBack + +# crbug.com/362627263 +-org.chromium.android_webview.test.PopupWindowTest.testSingleWindowModeJsInjection \ No newline at end of file
diff --git a/testing/buildbot/generate_buildbot_json.py b/testing/buildbot/generate_buildbot_json.py index b5b1f42..7a25a4d1 100755 --- a/testing/buildbot/generate_buildbot_json.py +++ b/testing/buildbot/generate_buildbot_json.py
@@ -366,19 +366,32 @@ args.pyl_files_dir = args.pyl_files_dir or THIS_DIR args.output_dir = args.output_dir or args.pyl_files_dir - def absolute_file_path(filename): + def pyl_dir_path(filename): return os.path.join(args.pyl_files_dir, filename) - args.waterfalls_pyl_path = absolute_file_path('waterfalls.pyl') - args.mixins_pyl_path = absolute_file_path('mixins.pyl') - args.test_suites_pyl_path = absolute_file_path('test_suites.pyl') - args.test_suite_exceptions_pyl_path = absolute_file_path( + args.waterfalls_pyl_path = pyl_dir_path('waterfalls.pyl') + args.test_suite_exceptions_pyl_path = pyl_dir_path( 'test_suite_exceptions.pyl') - args.gn_isolate_map_pyl_path = absolute_file_path('gn_isolate_map.pyl') - args.variants_pyl_path = absolute_file_path('variants.pyl') args.autoshard_exceptions_json_path = os.path.join( args.infra_config_dir, 'targets', 'autoshard_exceptions.json') + if args.pyl_files_dir == THIS_DIR: + + def infra_config_testing_path(filename): + return os.path.join(args.infra_config_dir, 'generated', 'testing', + filename) + + args.gn_isolate_map_pyl_path = infra_config_testing_path( + 'gn_isolate_map.pyl') + args.mixins_pyl_path = infra_config_testing_path('mixins.pyl') + args.test_suites_pyl_path = infra_config_testing_path('test_suites.pyl') + args.variants_pyl_path = infra_config_testing_path('variants.pyl') + else: + args.gn_isolate_map_pyl_path = pyl_dir_path('gn_isolate_map.pyl') + args.mixins_pyl_path = pyl_dir_path('mixins.pyl') + args.test_suites_pyl_path = pyl_dir_path('test_suites.pyl') + args.variants_pyl_path = pyl_dir_path('variants.pyl') + return args def print_line(self, line):
diff --git a/testing/buildbot/generate_buildbot_json_unittest.py b/testing/buildbot/generate_buildbot_json_unittest.py index f36c574..aa8970fc 100755 --- a/testing/buildbot/generate_buildbot_json_unittest.py +++ b/testing/buildbot/generate_buildbot_json_unittest.py
@@ -1856,7 +1856,7 @@ self.assertFalse(fbb.printed_lines) def test_load_multiple_isolate_map_files_with_duplicates(self): - self.args.isolate_map_files = ['gn_isolate_map.pyl'] + self.args.isolate_map_files = [self.args.gn_isolate_map_pyl_path] fbb = FakeBBGen(self.args, FOO_GTESTS_WATERFALL, REUSING_TEST_WITH_DIFFERENT_NAME, @@ -1875,7 +1875,7 @@ gn_isolate_map=GN_ISOLATE_MAP) fbb.load_configuration_files() isolate_dict = {} - isolate_map_1 = fbb.load_pyl_file('gn_isolate_map.pyl') + isolate_map_1 = fbb.load_pyl_file(self.args.gn_isolate_map_pyl_path) isolate_map_2 = fbb.load_pyl_file('gn_isolate_map2.pyl') isolate_dict.update(isolate_map_1) isolate_dict.update(isolate_map_2)
diff --git a/testing/buildbot/gn_isolate_map.pyl b/testing/buildbot/gn_isolate_map.pyl deleted file mode 100644 index 0d0201ed4..0000000 --- a/testing/buildbot/gn_isolate_map.pyl +++ /dev/null
@@ -1,2028 +0,0 @@ -# THIS IS A GENERATED FILE DO NOT EDIT!!! -# Instead: -# 1. Modify //infra/config/targets/binaries.star and/or //infra/config/targets/tests.star (for tests defined using targets.tests.junit_test) -# 2. Run //infra/config/main.star -# 3. Run //infra/config/scripts/sync-pyl-files.py - -{ - "absl_hardening_tests": { - "label": "//third_party/abseil-cpp:absl_hardening_tests", - "type": "console_test_launcher", - }, - "accessibility_unittests": { - "label": "//ui/accessibility:accessibility_unittests", - "type": "console_test_launcher", - }, - "android_browsertests": { - "label": "//chrome/test:android_browsertests", - "type": "windowed_test_launcher", - }, - "android_lint": { - "label": "//chrome/android:android_lint", - "type": "additional_compile_target", - }, - "android_sync_integration_tests": { - "label": "//chrome/test:android_sync_integration_tests", - "type": "windowed_test_launcher", - }, - "android_tools": { - "label": "//tools/android:android_tools", - "type": "additional_compile_target", - }, - "android_webview_junit_tests": { - "label": "//android_webview/test:android_webview_junit_tests", - "type": "generated_script", - }, - "android_webview_unittests": { - "label": "//android_webview/test:android_webview_unittests", - "type": "console_test_launcher", - }, - "angle_deqp_egl_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_egl_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_gles2_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_gles2_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_gles31_rotate180_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_gles31_rotate180_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_gles31_rotate270_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_gles31_rotate270_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_gles31_rotate90_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_gles31_rotate90_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_gles31_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_gles31_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_gles3_rotate180_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_gles3_rotate180_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_gles3_rotate270_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_gles3_rotate270_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_gles3_rotate90_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_gles3_rotate90_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_gles3_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_gles3_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_khr_gles2_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_khr_gles2_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_khr_gles31_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_khr_gles31_tests", - "type": "windowed_test_launcher", - }, - "angle_deqp_khr_gles3_tests": { - "label": "//third_party/angle/src/tests:angle_deqp_khr_gles3_tests", - "type": "windowed_test_launcher", - }, - "angle_end2end_tests": { - "label": "//third_party/angle/src/tests:angle_end2end_tests", - "type": "windowed_test_launcher", - }, - "angle_unittests": { - "label": "//third_party/angle/src/tests:angle_unittests", - "type": "windowed_test_launcher", - }, - "angle_white_box_tests": { - "label": "//third_party/angle/src/tests:angle_white_box_tests", - "type": "windowed_test_launcher", - }, - "app_shell_unittests": { - "label": "//extensions/shell:app_shell_unittests", - "type": "windowed_test_launcher", - }, - "ash_components_unittests": { - "label": "//ash/components:ash_components_unittests", - "type": "windowed_test_launcher", - }, - "ash_crosapi_tests": { - "label": "//chrome/test:ash_crosapi_tests", - "type": "windowed_test_launcher", - }, - "ash_pixeltests": { - "label": "//ash:ash_pixeltests", - "type": "windowed_test_launcher", - }, - "ash_unittests": { - "label": "//ash:ash_unittests", - "type": "windowed_test_launcher", - }, - "ash_webui_unittests": { - "label": "//ash/webui:ash_webui_unittests", - "type": "windowed_test_launcher", - }, - "aura_unittests": { - "label": "//ui/aura:aura_unittests", - "type": "windowed_test_launcher", - }, - "base_junit_tests": { - "label": "//base:base_junit_tests", - "type": "generated_script", - }, - "base_nocompile_tests": { - "label": "//base:base_nocompile_tests", - "type": "additional_compile_target", - }, - "base_perftests": { - "label": "//base:base_perftests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "skip_usage_check": True, - "args": [ - "base_perftests", - "--non-telemetry=true", - "--test-launcher-print-test-stdio=always", - "--test-launcher-jobs=1", - "--test-launcher-retry-limit=0", - ], - }, - "base_unittests": { - "label": "//base:base_unittests", - "type": "console_test_launcher", - }, - "blink_common_unittests": { - "label": "//third_party/blink/common:blink_common_unittests", - "type": "console_test_launcher", - }, - "blink_fuzzer_unittests": { - "label": "//third_party/blink/renderer/platform:blink_fuzzer_unittests", - "type": "console_test_launcher", - }, - "blink_heap_unittests": { - "label": "//third_party/blink/renderer/platform/heap:blink_heap_unittests", - "type": "console_test_launcher", - }, - "blink_platform_nocompile_tests": { - "label": "//third_party/blink/renderer/platform:blink_platform_nocompile_tests", - "type": "additional_compile_target", - }, - "blink_platform_unittests": { - "label": "//third_party/blink/renderer/platform:blink_platform_unittests", - "type": "console_test_launcher", - }, - "blink_probes_nocompile_tests": { - "label": "//third_party/blink/renderer/core/probe:blink_probes_nocompile_tests", - "type": "additional_compile_target", - }, - "blink_python_tests": { - "label": "//:blink_python_tests", - "type": "generated_script", - }, - "blink_pytype": { - "label": "//third_party/blink/tools:blink_pytype", - "type": "script", - "script": "//third_party/blink/tools/run_pytype.py", - }, - "blink_tests": { - "label": "//:blink_tests", - "type": "additional_compile_target", - }, - "blink_unittests": { - "label": "//third_party/blink/renderer/controller:blink_unittests", - "type": "console_test_launcher", - }, - "blink_web_tests": { - "label": "//:blink_web_tests", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, - "blink_wpt_tests": { - "label": "//:blink_wpt_tests", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, - "boringssl_crypto_tests": { - "label": "//third_party/boringssl:boringssl_crypto_tests", - "type": "console_test_launcher", - }, - "boringssl_ssl_tests": { - "label": "//third_party/boringssl:boringssl_ssl_tests", - "type": "console_test_launcher", - }, - "browser_tests": { - "label": "//chrome/test:browser_tests", - "type": "windowed_test_launcher", - }, - "build_junit_tests": { - "label": "//build/android:build_junit_tests", - "type": "generated_script", - }, - "build_rust_tests": { - "label": "//build/rust/tests:build_rust_tests", - "type": "generated_script", - }, - "capture_unittests": { - "label": "//media/capture:capture_unittests", - "type": "windowed_test_launcher", - }, - "captured_sites_interactive_tests": { - "label": "//chrome/test:captured_sites_interactive_tests", - "type": "windowed_test_launcher", - "args": [ - "--disable-extensions", - ], - }, - "cast_base_junit_tests": { - "label": "//chromecast/base:cast_base_junit_tests", - "type": "generated_script", - }, - "cast_junit_test_lists": { - "label": "//chromecast:cast_junit_test_lists", - "type": "additional_compile_target", - }, - "cast_runner_browsertests": { - "label": "//fuchsia_web/runners:cast_runner_browsertests", - "type": "console_test_launcher", - }, - "cast_runner_integration_tests": { - "label": "//fuchsia_web/runners:cast_runner_integration_tests", - "type": "console_test_launcher", - }, - "cast_runner_pkg": { - "label": "//fuchsia_web/runners:cast_runner_pkg", - "type": "additional_compile_target", - }, - "cast_runner_unittests": { - "label": "//fuchsia_web/runners:cast_runner_unittests", - "type": "console_test_launcher", - }, - "cast_shell": { - "label": "//chromecast:cast_shell", - "type": "additional_compile_target", - }, - "cast_shell_apk": { - "label": "//chromecast:cast_shell_apk", - "type": "additional_compile_target", - }, - "cast_shell_junit_tests": { - "label": "//chromecast/browser/android:cast_shell_junit_tests", - "type": "generated_script", - }, - "cast_test_lists": { - "label": "//chromecast:cast_test_lists", - "type": "additional_compile_target", - }, - "cast_unittests": { - "label": "//media/cast:cast_unittests", - "type": "windowed_test_launcher", - }, - "cc_unittests": { - "label": "//cc:cc_unittests", - "type": "windowed_test_launcher", - }, - "check_chrome_static_initializers": { - "label": "//chrome/android:check_chrome_static_initializers", - "type": "additional_compile_target", - }, - "chrome": { - "label": "//chrome:chrome", - "type": "additional_compile_target", - }, - "chrome/browser/media/router": { - "label": "//chrome/browser/media/router:router", - "type": "additional_compile_target", - }, - "chrome/browser/media/router:openscreen_unittests": { - "label": "//chrome/browser/media/router:openscreen_unittests", - "type": "additional_compile_target", - }, - "chrome/browser/media/router:unittests": { - "label": "//chrome/browser/media/router:unittests", - "type": "additional_compile_target", - }, - "chrome/enterprise_companion:all": { - "label": "//chrome/enterprise_companion:all", - "type": "additional_compile_target", - }, - "chrome/installer/linux": { - "label": "//chrome/installer/linux:linux", - "type": "additional_compile_target", - }, - "chrome/installer/mac": { - "label": "//chrome/installer/mac:mac", - "type": "additional_compile_target", - }, - "chrome/updater:all": { - "label": "//chrome/updater:all", - "type": "additional_compile_target", - }, - "chrome_all_tast_tests": { - "label": "//chromeos:chrome_all_tast_tests", - "type": "generated_script", - "args": [ - "--logs-dir=${ISOLATED_OUTDIR}", - ], - }, - "chrome_app_unittests": { - "label": "//chrome/test:chrome_app_unittests", - "type": "console_test_launcher", - }, - "chrome_criticalstaging_tast_tests": { - "label": "//chromeos:chrome_criticalstaging_tast_tests", - "type": "generated_script", - "args": [ - "--logs-dir=${ISOLATED_OUTDIR}", - ], - }, - "chrome_disabled_tast_tests": { - "label": "//chromeos:chrome_disabled_tast_tests", - "type": "generated_script", - "args": [ - "--logs-dir=${ISOLATED_OUTDIR}", - ], - }, - "chrome_elf_unittests": { - "label": "//chrome/chrome_elf:chrome_elf_unittests", - "type": "console_test_launcher", - }, - "chrome_ios_wpt": { - "label": "//ios/chrome/test/wpt:chrome_ios_wpt", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, - "chrome_java_test_pagecontroller_junit_tests": { - "label": "//chrome/test/android:chrome_java_test_pagecontroller_junit_tests", - "type": "generated_script", - }, - "chrome_java_test_wpr_tests": { - "label": "//chrome/test/android:chrome_java_test_wpr_tests", - "type": "console_test_launcher", - }, - "chrome_junit_tests": { - "label": "//chrome/android:chrome_junit_tests", - "type": "generated_script", - }, - "chrome_ml_unittests": { - "label": "//components/optimization_guide/internal:chrome_ml_unittests", - "type": "console_test_launcher", - }, - "chrome_nocompile_tests": { - "label": "//chrome/android:chrome_nocompile_tests", - "type": "additional_compile_target", - }, - "chrome_official_builder": { - "label": "//:chrome_official_builder", - "type": "additional_compile_target", - }, - "chrome_official_builder_no_unittests": { - "label": "//:chrome_official_builder_no_unittests", - "type": "additional_compile_target", - }, - "chrome_private_code_test": { - "label": "//chrome:chrome_private_code_test", - "type": "generated_script", - }, - "chrome_public_apk": { - "label": "//chrome/android:chrome_public_apk", - "type": "additional_compile_target", - }, - "chrome_public_apk_baseline_profile_generator": { - "label": "//chrome/test/android:chrome_public_apk_baseline_profile_generator", - "type": "console_test_launcher", - }, - "chrome_public_smoke_test": { - "label": "//chrome/android:chrome_public_smoke_test", - "type": "console_test_launcher", - }, - "chrome_public_test_apk": { - "label": "//chrome/android:chrome_public_test_apk", - "type": "console_test_launcher", - }, - "chrome_public_test_vr_apk": { - "label": "//chrome/android:chrome_public_test_vr_apk", - "type": "console_test_launcher", - }, - "chrome_public_unit_test_apk": { - "label": "//chrome/android:chrome_public_unit_test_apk", - "type": "console_test_launcher", - }, - "chrome_public_wpt": { - "label": "//chrome/android:chrome_public_wpt", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, - "chrome_sandbox": { - "label": "//sandbox/linux:chrome_sandbox", - "type": "additional_compile_target", - }, - "chrome_sizes": { - "label": "//chrome/test:chrome_sizes", - "type": "generated_script", - }, - "chrome_wpt_tests": { - "label": "//:chrome_wpt_tests", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, - "chromedriver": { - "label": "//chrome/test/chromedriver:chromedriver_server", - "type": "additional_compile_target", - }, - "chromedriver_group": { - "label": "//:chromedriver_group", - "type": "additional_compile_target", - }, - "chromedriver_py_tests": { - "label": "//chrome/test/chromedriver:chromedriver_py_tests", - "type": "script", - "script": "//testing/xvfb.py", - "args": [ - "../../testing/scripts/run_chromedriver_tests.py", - "../../chrome/test/chromedriver/test/run_py_tests.py", - "--chromedriver=chromedriver", - "--log-path=${ISOLATED_OUTDIR}/chrome.chromedriver.log", - "--browser-name=chrome", - ], - }, - "chromedriver_py_tests_headless_shell": { - "label": "//chrome/test/chromedriver:chromedriver_py_tests_headless_shell", - "type": "script", - "script": "//testing/scripts/run_chromedriver_tests.py", - "args": [ - "../../chrome/test/chromedriver/test/run_py_tests.py", - "--chromedriver=chromedriver", - "--log-path=${ISOLATED_OUTDIR}/chrome-headless-shell.chromedriver.log", - "--browser-name=chrome-headless-shell", - ], - }, - "chromedriver_replay_unittests": { - "label": "//chrome/test/chromedriver:chromedriver_replay_unittests", - "type": "script", - "script": "//chrome/test/chromedriver/log_replay/client_replay_unittest.py", - }, - "chromedriver_unittests": { - "label": "//chrome/test/chromedriver:chromedriver_unittests", - "type": "windowed_test_launcher", - }, - "chromeos_components_unittests": { - "label": "//chromeos/components:chromeos_components_unittests", - "type": "console_test_launcher", - }, - "chromeos_integration_tests": { - "label": "//chrome/test:chromeos_integration_tests", - "type": "windowed_test_launcher", - }, - "chromeos_unittests": { - "label": "//chromeos:chromeos_unittests", - "type": "console_test_launcher", - }, - "chromium_builder_asan": { - "label": "//:chromium_builder_asan", - "type": "additional_compile_target", - }, - "chromium_builder_perf": { - "label": "//:chromium_builder_perf", - "type": "additional_compile_target", - }, - "chromiumos_preflight": { - "label": "//:chromiumos_preflight", - "type": "additional_compile_target", - }, - "command_buffer_perftests": { - "label": "//gpu:command_buffer_perftests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "args": [ - "command_buffer_perftests", - "--non-telemetry=true", - "--adb-path", - "src/third_party/android_sdk/public/platform-tools/adb", - ], - }, - "components/media_router/common/providers/cast/certificate": { - "label": "//components/media_router/common/providers/cast/certificate", - "type": "additional_compile_target", - }, - "components/media_router/common/providers/cast/certificate:unit_tests": { - "label": "//components/media_router/common/providers/cast/certificate:unit_tests", - "type": "additional_compile_target", - }, - "components/media_router/common/providers/cast/channel": { - "label": "//components/media_router/common/providers/cast/channel:cast_channel", - "type": "additional_compile_target", - }, - "components/media_router/common/providers/cast/channel:unit_tests": { - "label": "//components/media_router/common/providers/cast/channel:unit_tests", - "type": "additional_compile_target", - }, - "components/mirroring/browser": { - "label": "//components/mirroring/browser:browser", - "type": "additional_compile_target", - }, - "components/mirroring/service:mirroring_service": { - "label": "//components/mirroring/service:mirrroring_service", - "type": "additional_compile_target", - }, - "components/mirroring:mirroring_tests": { - "label": "//components/mirroring:mirroring_tests", - "type": "additional_compile_target", - }, - "components/mirroring:mirroring_unittests": { - "label": "//components/mirroring:mirroring_unittests", - "type": "additional_compile_target", - }, - "components/openscreen_platform": { - "label": "//components/openscreen_platform", - "type": "additional_compile_target", - }, - "components_browsertests": { - "label": "//components:components_browsertests", - "type": "windowed_test_launcher", - }, - "components_junit_tests": { - "label": "//components:components_junit_tests", - "type": "generated_script", - }, - "components_perftests": { - "label": "//components:components_perftests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "args": [ - "--xvfb", - "--non-telemetry=true", - "components_perftests", - ], - }, - "components_unittests": { - "label": "//components:components_unittests", - "type": "windowed_test_launcher", - }, - "compositor_unittests": { - "label": "//ui/compositor:compositor_unittests", - "type": "windowed_test_launcher", - }, - "content_browsertests": { - "label": "//content/test:content_browsertests", - "type": "windowed_test_launcher", - }, - "content_junit_tests": { - "label": "//content/public/android:content_junit_tests", - "type": "generated_script", - }, - "content_nocompile_tests": { - "label": "//content/test:content_nocompile_tests", - "type": "additional_compile_target", - }, - "content_shell_crash_test": { - "label": "//content/shell:content_shell_crash_test", - "type": "script", - "script": "//testing/scripts/content_shell_crash_test.py", - }, - "content_shell_test_apk": { - "label": "//content/shell/android:content_shell_test_apk", - "type": "console_test_launcher", - }, - "content_unittests": { - "label": "//content/test:content_unittests", - "type": "windowed_test_launcher", - }, - "courgette_unittests": { - "label": "//courgette:courgette_unittests", - "type": "console_test_launcher", - }, - "cq_medium_tast_tests": { - "label": "//chromeos:cq_medium_tast_tests", - "type": "generated_script", - "args": [ - "--logs-dir=${ISOLATED_OUTDIR}", - ], - }, - "crashpad_tests": { - "label": "//third_party/crashpad/crashpad:crashpad_tests", - "type": "console_test_launcher", - }, - "cronet_package": { - "label": "//components/cronet:cronet_package", - "type": "additional_compile_target", - }, - "cronet_package_ci": { - "label": "//components/cronet/android:cronet_package_ci", - "type": "additional_compile_target", - }, - "cronet_perf_test_apk": { - "label": "//components/cronet/android:cronet_perf_test_apk", - "type": "additional_compile_target", - }, - "cronet_sample_test_apk": { - "label": "//components/cronet/android:cronet_sample_test_apk", - "type": "console_test_launcher", - }, - "cronet_sizes": { - "label": "//components/cronet/android:cronet_sizes", - "type": "generated_script", - }, - "cronet_smoketests_apk": { - "label": "//components/cronet/android:cronet_smoketests_apk", - "type": "console_test_launcher", - }, - "cronet_smoketests_missing_native_library_instrumentation_apk": { - "label": "//components/cronet/android:cronet_smoketests_missing_native_library_instrumentation_apk", - "type": "console_test_launcher", - }, - "cronet_smoketests_platform_only_instrumentation_apk": { - "label": "//components/cronet/android:cronet_smoketests_platform_only_instrumentation_apk", - "type": "console_test_launcher", - }, - "cronet_test_instrumentation_apk": { - "label": "//components/cronet/android:cronet_test_instrumentation_apk", - "type": "console_test_launcher", - }, - "cronet_tests": { - "label": "//components/cronet:cronet_tests", - "type": "console_test_launcher", - }, - "cronet_tests_android": { - "label": "//components/cronet/android:cronet_tests_android", - "type": "console_test_launcher", - }, - "cronet_unittests": { - "label": "//components/cronet:cronet_unittests", - "type": "console_test_launcher", - }, - "cronet_unittests_android": { - "label": "//components/cronet/android:cronet_unittests_android", - "type": "console_test_launcher", - }, - "crypto_unittests": { - "label": "//crypto:crypto_unittests", - "type": "console_test_launcher", - }, - "ct_telemetry_perf_tests_without_chrome": { - "label": "//chrome/test:ct_telemetry_perf_tests_without_chrome", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "args": [ - "../../tools/perf/run_benchmark", - ], - }, - "dawn_end2end_tests": { - "label": "//third_party/dawn/src/dawn/tests:dawn_end2end_tests", - "type": "windowed_test_launcher", - }, - "dawn_perf_tests": { - "label": "//third_party/dawn/src/dawn/tests:dawn_perf_tests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "args": [ - "dawn_perf_tests", - "--non-telemetry=true", - "--test-launcher-print-test-stdio=always", - "--test-launcher-jobs=1", - "--test-launcher-retry-limit=0", - ], - }, - "dbus_unittests": { - "label": "//dbus:dbus_unittests", - "type": "windowed_test_launcher", - }, - "delayloads_unittests": { - "label": "//chrome/test:delayloads_unittests", - "type": "console_test_launcher", - }, - "device_junit_tests": { - "label": "//device:device_junit_tests", - "type": "generated_script", - }, - "device_unittests": { - "label": "//device:device_unittests", - "type": "console_test_launcher", - }, - "disk_usage_tast_test": { - "label": "//chromeos:disk_usage_tast_test", - "type": "generated_script", - "args": [ - "--logs-dir=${ISOLATED_OUTDIR}", - ], - }, - "display_unittests": { - "label": "//ui/display:display_unittests", - "type": "console_test_launcher", - }, - "elevation_service_unittests": { - "label": "//chrome/elevation_service:elevation_service_unittests", - "type": "windowed_test_launcher", - }, - "empty_main": { - "label": "//testing:empty_main", - "type": "additional_compile_target", - }, - "enterprise_companion_integration_tests": { - "label": "//chrome/enterprise_companion:enterprise_companion_integration_tests", - "type": "script", - "script": "//testing/scripts/run_telemetry_as_googletest.py", - "args": [ - "test_service/enterprise_companion_integration_tests_launcher.py", - "--test-output-dir=${ISOLATED_OUTDIR}", - "--test-launcher-bot-mode", - "--gtest_shuffle", - ], - }, - "enterprise_companion_tests": { - "label": "//chrome/enterprise_companion:enterprise_companion_tests", - "type": "console_test_launcher", - "args": [ - "--gtest_shuffle", - ], - }, - "env_chromium_unittests": { - "label": "//third_party/leveldatabase:env_chromium_unittests", - "type": "console_test_launcher", - }, - "events_unittests": { - "label": "//ui/events:events_unittests", - "type": "windowed_test_launcher", - }, - "exo_unittests": { - "label": "//components/exo:exo_unittests", - "type": "windowed_test_launcher", - }, - "extensions_browsertests": { - "label": "//extensions:extensions_browsertests", - "type": "windowed_test_launcher", - }, - "extensions_unittests": { - "label": "//extensions:extensions_unittests", - "type": "windowed_test_launcher", - }, - "fake_libva_driver_unittest": { - "label": "//media/gpu/vaapi/test/fake_libva_driver:fake_libva_driver_unittest", - "type": "console_test_launcher", - }, - "filesystem_service_unittests": { - "label": "//components/services/filesystem:filesystem_service_unittests", - "type": "console_test_launcher", - }, - "flatbuffers_unittests": { - "label": "//third_party/flatbuffers:flatbuffers_unittests", - "type": "script", - "script": "//testing/scripts/run_flatbuffers_unittests.py", - }, - "fuchsia_pytype": { - "label": "//testing:fuchsia_pytype", - "type": "script", - "script": "//build/fuchsia/test/run_pytype.py", - }, - "fuchsia_sizes": { - "label": "//tools/fuchsia/size_tests:fuchsia_sizes", - "type": "generated_script", - }, - "fuzzing_unittests": { - "label": "//testing/libfuzzer/tests:fuzzing_unittests", - "type": "console_test_launcher", - }, - "gcm_unit_tests": { - "label": "//google_apis/gcm:gcm_unit_tests", - "type": "console_test_launcher", - }, - "gcp_unittests": { - "label": "//chrome/credential_provider/test:gcp_unittests", - "type": "console_test_launcher", - }, - "gfx_unittests": { - "label": "//ui/gfx:gfx_unittests", - "type": "console_test_launcher", - }, - "gin_unittests": { - "label": "//gin:gin_unittests", - "type": "console_test_launcher", - }, - "gl_tests": { - "label": "//gpu:gl_tests", - "type": "windowed_test_launcher", - }, - "gl_unittests": { - "label": "//ui/gl:gl_unittests", - "type": "windowed_test_launcher", - }, - "gl_unittests_ozone": { - "label": "//ui/gl:gl_unittests_ozone", - "label_type": "group", - "type": "windowed_test_launcher", - "executable": "gl_unittests", - }, - "gn_all": { - "label": "//:gn_all", - "type": "additional_compile_target", - }, - "gold_common_pytype": { - "label": "//build:gold_common_pytype", - "type": "script", - "script": "//build/skia_gold_common/run_pytype.py", - }, - "google_apis_unittests": { - "label": "//google_apis:google_apis_unittests", - "type": "console_test_launcher", - }, - "gpu_perftests": { - "label": "//gpu:gpu_perftests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "skip_usage_check": True, - "args": [ - "gpu_perftests", - "--non-telemetry=true", - "--adb-path", - "src/third_party/android_sdk/public/platform-tools/adb", - ], - }, - "gpu_pytype": { - "label": "//content/test:gpu_pytype", - "type": "script", - "script": "//content/test/gpu/run_pytype.py", - }, - "gpu_unittests": { - "label": "//gpu:gpu_unittests", - "type": "windowed_test_launcher", - }, - "grit_python_unittests": { - "label": "//tools/grit:grit_python_unittests", - "type": "script", - "script": "//testing/scripts/run_isolated_script_test.py", - "args": [ - "../../tools/grit/grit/test_suite_all.py", - ], - }, - "gwp_asan_unittests": { - "label": "//components/gwp_asan:gwp_asan_unittests", - "type": "console_test_launcher", - }, - "headless_browsertests": { - "label": "//headless:headless_browsertests", - "type": "console_test_launcher", - }, - "headless_shell_wpt": { - "label": "//:headless_shell_wpt", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, - "headless_unittests": { - "label": "//headless:headless_unittests", - "type": "console_test_launcher", - }, - "image_processor_perf_test": { - "label": "//media/gpu/chromeos:image_processor_perf_test", - "type": "additional_compile_target", - }, - "install_static_unittests": { - "label": "//chrome/install_static:install_static_unittests", - "type": "console_test_launcher", - }, - "installer_util_unittests": { - "label": "//chrome/installer/util:installer_util_unittests", - "type": "console_test_launcher", - }, - "interactive_ui_tests": { - "label": "//chrome/test:interactive_ui_tests", - "type": "windowed_test_launcher", - "args": [ - "--snapshot-output-dir=${ISOLATED_OUTDIR}", - ], - }, - "ios/chrome/app:chrome": { - "label": "//ios/chrome/app:chrome", - "type": "additional_compile_target", - }, - "ios/chrome/test:all_fuzzer_tests": { - "label": "//ios/chrome/test:all_fuzzer_tests", - "type": "additional_compile_target", - }, - "ios_chrome_bookmarks_eg2tests_module": { - "label": "//ios/chrome/test/earl_grey2:ios_chrome_bookmarks_eg2tests_module", - "type": "generated_script", - }, - "ios_chrome_clusterfuzz_asan_build": { - "label": "//ios/chrome/test/wpt:ios_chrome_clusterfuzz_asan_build", - "type": "additional_compile_target", - }, - "ios_chrome_integration_eg2tests_module": { - "label": "//ios/chrome/test/earl_grey2:ios_chrome_integration_eg2tests_module", - "type": "generated_script", - }, - "ios_chrome_settings_eg2tests_module": { - "label": "//ios/chrome/test/earl_grey2:ios_chrome_settings_eg2tests_module", - "type": "generated_script", - }, - "ios_chrome_signin_eg2tests_module": { - "label": "//ios/chrome/test/earl_grey2:ios_chrome_signin_eg2tests_module", - "type": "generated_script", - }, - "ios_chrome_smoke_eg2tests_module": { - "label": "//ios/chrome/test/earl_grey2:ios_chrome_smoke_eg2tests_module", - "type": "generated_script", - }, - "ios_chrome_ui_eg2tests_module": { - "label": "//ios/chrome/test/earl_grey2:ios_chrome_ui_eg2tests_module", - "type": "generated_script", - }, - "ios_chrome_unittests": { - "label": "//ios/chrome/test:ios_chrome_unittests", - "type": "generated_script", - }, - "ios_chrome_web_eg2tests_module": { - "label": "//ios/chrome/test/earl_grey2:ios_chrome_web_eg2tests_module", - "type": "generated_script", - }, - "ios_components_unittests": { - "label": "//ios/components:ios_components_unittests", - "type": "generated_script", - }, - "ios_crash_xcuitests_module": { - "label": "//third_party/crashpad/crashpad/test/ios:ios_crash_xcuitests_module", - "type": "generated_script", - }, - "ios_net_unittests": { - "label": "//ios/net:ios_net_unittests", - "type": "generated_script", - }, - "ios_remoting_unittests": { - "label": "//remoting/ios:ios_remoting_unittests", - "type": "generated_script", - }, - "ios_testing_unittests": { - "label": "//ios/testing:ios_testing_unittests", - "type": "generated_script", - }, - "ios_web_inttests": { - "label": "//ios/web:ios_web_inttests", - "type": "generated_script", - }, - "ios_web_shell_eg2tests_module": { - "label": "//ios/web/shell/test:ios_web_shell_eg2tests_module", - "type": "generated_script", - }, - "ios_web_unittests": { - "label": "//ios/web:ios_web_unittests", - "type": "generated_script", - }, - "ios_web_view_inttests": { - "label": "//ios/web_view:ios_web_view_inttests", - "type": "generated_script", - }, - "ios_web_view_unittests": { - "label": "//ios/web_view:ios_web_view_unittests", - "type": "generated_script", - }, - "ipc_tests": { - "label": "//ipc:ipc_tests", - "type": "console_test_launcher", - }, - "jni_zero_sample_apk_test": { - "label": "//third_party/jni_zero/sample:jni_zero_sample_apk_test", - "type": "console_test_launcher", - }, - "junit_unit_tests": { - "label": "//testing/android/junit:junit_unit_tests", - "type": "generated_script", - }, - "keyboard_accessory_junit_tests": { - "label": "//chrome/android/features/keyboard_accessory:keyboard_accessory_junit_tests", - "type": "generated_script", - }, - "keyboard_unittests": { - "label": "//ash/keyboard/ui:keyboard_unittests", - "type": "windowed_test_launcher", - }, - "lacros_all_tast_tests": { - "label": "//chromeos/lacros:lacros_all_tast_tests", - "type": "generated_script", - "args": [ - "--logs-dir=${ISOLATED_OUTDIR}", - ], - }, - "lacros_chrome_browsertests": { - "label": "//chrome/test:lacros_chrome_browsertests", - "type": "windowed_test_launcher", - "args": [ - "--test-launcher-jobs=1", - ], - }, - "latency_unittests": { - "label": "//ui/latency:latency_unittests", - "type": "console_test_launcher", - }, - "leveldb_unittests": { - "label": "//third_party/leveldatabase:leveldb_unittests", - "type": "console_test_launcher", - }, - "libcups_unittests": { - "label": "//chrome/services/cups_proxy:libcups_unittests", - "type": "console_test_launcher", - }, - "libjingle_xmpp_unittests": { - "label": "//third_party/libjingle_xmpp:libjingle_xmpp_unittests", - "type": "console_test_launcher", - }, - "liburlpattern_unittests": { - "label": "//third_party/liburlpattern:liburlpattern_unittests", - "type": "console_test_launcher", - }, - "linux_symbols": { - "label": "//chrome:linux_symbols", - "type": "additional_compile_target", - }, - "load_library_perf_tests": { - "label": "//chrome/test:load_library_perf_tests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "skip_usage_check": True, - "args": [ - "load_library_perf_tests", - "--non-telemetry=true", - "--test-launcher-print-test-stdio=always", - ], - }, - "mac_signing_tests": { - "label": "//chrome/installer/mac:mac_signing_tests", - "type": "generated_script", - }, - "media_base_junit_tests": { - "label": "//media/base/android:media_base_junit_tests", - "type": "generated_script", - }, - "media_perftests": { - "label": "//media:media_perftests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "skip_usage_check": True, - "args": [ - "media_perftests", - "--non-telemetry=true", - "--single-process-tests", - "--test-launcher-retry-limit=0", - "--isolated-script-test-filter=*::-*_unoptimized::*_unaligned::*unoptimized_aligned", - ], - }, - "media_router_e2e_tests": { - "label": "//chrome/test/media_router:media_router_e2e_tests", - "type": "script", - "script": "//chrome/test/media_router/internal/media_router_tests.py", - "args": [ - "--test_binary", - "./interactive_ui_tests", - ], - }, - "media_unittests": { - "label": "//media:media_unittests", - "type": "windowed_test_launcher", - }, - "message_center_unittests": { - "label": "//ui/message_center:message_center_unittests", - "type": "windowed_test_launcher", - }, - "midi_unittests": { - "label": "//media/midi:midi_unittests", - "type": "windowed_test_launcher", - }, - "mini_installer": { - "label": "//chrome/installer/mini_installer:mini_installer", - "type": "additional_compile_target", - }, - "mini_installer_tests": { - "label": "//chrome/test/mini_installer:mini_installer_tests", - "type": "script", - "script": "//testing/scripts/run_isolated_script_test.py", - "args": [ - "../../chrome/test/mini_installer/run_mini_installer_tests.py", - "--output-dir=${ISOLATED_OUTDIR}", - ], - }, - "minidump_uploader_test": { - "label": "//components/minidump_uploader:minidump_uploader_test", - "type": "console_test_launcher", - }, - "model_validation_tests": { - "label": "//components/optimization_guide/internal/testing:model_validation_tests", - "type": "generated_script", - }, - "model_validation_tests_light": { - "label": "//components/optimization_guide/internal/testing:model_validation_tests_light", - "type": "generated_script", - }, - "module_installer_junit_tests": { - "label": "//components/module_installer/android:module_installer_junit_tests", - "type": "generated_script", - }, - "mojo_python_unittests": { - "label": "//mojo/public/tools:mojo_python_unittests", - "type": "script", - "script": "//testing/scripts/run_isolated_script_test.py", - "args": [ - "../../mojo/public/tools/run_all_python_unittests.py", - ], - }, - "mojo_rust": { - "label": "//mojo/public/rust:mojo_rust", - "type": "additional_compile_target", - }, - "mojo_rust_integration_unittests": { - "label": "//mojo/public/rust:mojo_rust_integration_unittests", - "type": "console_test_launcher", - }, - "mojo_rust_unittests": { - "label": "//mojo/public/rust:mojo_rust_unittests", - "type": "console_test_launcher", - }, - "mojo_test_apk": { - "label": "//mojo/public/java/system:mojo_test_apk", - "type": "console_test_launcher", - }, - "mojo_unittests": { - "label": "//mojo:mojo_unittests", - "type": "console_test_launcher", - }, - "monochrome_public_apk_checker": { - "label": "//chrome/android/monochrome:monochrome_public_apk_checker", - "type": "script", - "script": "//testing/scripts/run_isolated_script_test.py", - "args": [ - "../../chrome/android/monochrome/scripts/monochrome_python_tests.py", - "--chrome-apk", - "apks/ChromePublic.apk", - "--chrome-pathmap", - "apks/ChromePublic.apk.pathmap.txt", - "--system-webview-apk", - "apks/SystemWebView.apk", - "--system-webview-pathmap", - "apks/SystemWebView.apk.pathmap.txt", - "--monochrome-apk", - "apks/MonochromePublic.apk", - "--monochrome-pathmap", - "apks/MonochromePublic.apk.pathmap.txt", - ], - }, - "monochrome_public_bundle_smoke_test": { - "label": "//chrome/android:monochrome_public_bundle_smoke_test", - "type": "console_test_launcher", - }, - "monochrome_public_smoke_test": { - "label": "//chrome/android:monochrome_public_smoke_test", - "type": "console_test_launcher", - }, - "monochrome_public_test_ar_apk": { - "label": "//chrome/android:monochrome_public_test_ar_apk", - "type": "console_test_launcher", - }, - "nacl_helper": { - "label": "//components/nacl/loader:nacl_helper", - "type": "additional_compile_target", - "skip_usage_check": True, - }, - "nacl_helper_bootstrap": { - "label": "//native_client/src/trusted/service_runtime/linux:bootstrap", - "type": "additional_compile_target", - "skip_usage_check": True, - }, - "nacl_loader_unittests": { - "label": "//components/nacl/loader:nacl_loader_unittests", - "type": "console_test_launcher", - }, - "native_theme_unittests": { - "label": "//ui/native_theme:native_theme_unittests", - "type": "windowed_test_launcher", - }, - "net_junit_tests": { - "label": "//net/android:net_junit_tests", - "type": "generated_script", - }, - "net_perftests": { - "label": "//net:net_perftests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "skip_usage_check": True, - "args": [ - "net_perftests", - "--non-telemetry=true", - ], - }, - "net_unittests": { - "label": "//net:net_unittests", - "type": "console_test_launcher", - }, - "notification_helper_unittests": { - "label": "//chrome/notification_helper:notification_helper_unittests", - "type": "windowed_test_launcher", - }, - "ondevice_model_benchmark": { - "label": "//components/optimization_guide/internal:ondevice_model_benchmark", - "type": "additional_compile_target", - }, - "ondevice_model_example": { - "label": "//components/optimization_guide/internal:ondevice_model_example", - "type": "additional_compile_target", - }, - "ondevice_quality_tests": { - "label": "//components/optimization_guide/internal/testing:ondevice_quality_tests", - "type": "generated_script", - }, - "ondevice_stability_tests": { - "label": "//components/optimization_guide/internal/testing:ondevice_stability_tests", - "type": "generated_script", - }, - "ondevice_stability_tests_light": { - "label": "//components/optimization_guide/internal/testing:ondevice_stability_tests_light", - "type": "generated_script", - }, - "openscreen_unittests": { - "label": "//chrome/browser/media/router:openscreen_unittests", - "type": "console_test_launcher", - }, - "optimization_guide_gpu_unittests": { - "label": "//components/optimization_guide/internal:optimization_guide_gpu_unittests", - "type": "console_test_launcher", - }, - "optimization_guide_unittests": { - "label": "//components/optimization_guide/internal:optimization_guide_unittests", - "type": "console_test_launcher", - }, - "ozone_gl_unittests": { - "label": "//ui/ozone/gl:ozone_gl_unittests", - "type": "console_test_launcher", - }, - "ozone_unittests": { - "label": "//ui/ozone:ozone_unittests", - "type": "console_test_launcher", - }, - "ozone_x11_unittests": { - "label": "//ui/ozone:ozone_x11_unittests", - "type": "windowed_test_launcher", - }, - "paint_preview_junit_tests": { - "label": "//components/paint_preview/player/android:paint_preview_junit_tests", - "type": "generated_script", - }, - "password_check_junit_tests": { - "label": "//chrome/browser/password_check/android:password_check_junit_tests", - "type": "generated_script", - }, - "password_manager_junit_tests": { - "label": "//chrome/browser/password_manager/android:password_manager_junit_tests", - "type": "generated_script", - }, - "pdf_fuzzers": { - "label": "//pdf/pdfium/fuzzers:pdf_fuzzers", - "type": "additional_compile_target", - }, - "pdf_unittests": { - "label": "//pdf:pdf_unittests", - "type": "console_test_launcher", - }, - "pdfium_test": { - "label": "//third_party/pdfium/testing:pdfium_test", - "type": "additional_compile_target", - }, - "perfetto_unittests": { - "label": "//third_party/perfetto:perfetto_unittests", - "type": "console_test_launcher", - }, - "performance_browser_tests": { - "label": "//chrome/test:performance_browser_tests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "skip_usage_check": True, - "args": [ - "browser_tests", - "--non-telemetry=true", - "--full-performance-run", - "--test-launcher-jobs=1", - "--test-launcher-retry-limit=0", - "--test-launcher-print-test-stdio=always", - "--ui-test-action-timeout=60000", - "--ui-test-action-max-timeout=60000", - "--test-launcher-timeout=60000", - "--gtest_filter=*/TabCapturePerformanceTest.*:*/CastV2PerformanceTest.*", - ], - }, - "performance_test_suite": { - "label": "//chrome/test:performance_test_suite", - "type": "generated_script", - }, - "performance_test_suite_android_clank_trichrome_bundle": { - "label": "//chrome/test:performance_test_suite_android_clank_trichrome_bundle", - "type": "generated_script", - }, - "performance_test_suite_android_clank_trichrome_chrome_google_64_32_bundle": { - "label": "//chrome/test:performance_test_suite_android_clank_trichrome_chrome_google_64_32_bundle", - "type": "generated_script", - }, - "performance_test_suite_eve": { - "label": "//chrome/test:performance_test_suite_eve", - "type": "generated_script", - }, - "performance_test_suite_octopus": { - "label": "//chrome/test:performance_test_suite_octopus", - "type": "generated_script", - }, - "performance_web_engine_test_suite": { - "label": "//content/test:performance_web_engine_test_suite", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "args": [ - "../../content/test/gpu/run_telemetry_benchmark_fuchsia.py", - "--per-test-logs-dir", - ], - }, - "performance_webview_test_suite": { - "label": "//chrome/test:performance_webview_test_suite", - "type": "script", - "script": "//third_party/catapult/devil/devil/android/tools/system_app.py", - "args": [ - "remove", - "--package", - "com.android.webview", - "com.google.android.webview", - "-v", - "--", - "../../testing/scripts/run_performance_tests.py", - "../../tools/perf/run_benchmark", - ], - }, - "polymer_tools_python_unittests": { - "label": "//tools/polymer:polymer_tools_python_unittests", - "type": "script", - "script": "//testing/scripts/run_isolated_script_test.py", - "args": [ - "../../tools/polymer/run_polymer_tools_tests.py", - ], - }, - "postmortem-metadata": { - "label": "//v8:postmortem-metadata", - "type": "additional_compile_target", - }, - "power_sampler_unittests": { - "label": "//tools/mac/power:power_sampler_unittests", - "type": "console_test_launcher", - }, - "ppapi_unittests": { - "label": "//ppapi:ppapi_unittests", - "type": "console_test_launcher", - }, - "previous_version_mini_installer": { - "label": "//chrome/installer/mini_installer:previous_version_mini_installer", - "type": "additional_compile_target", - }, - "printing_unittests": { - "label": "//printing:printing_unittests", - "type": "console_test_launcher", - }, - "private_code_failure_test": { - "label": "//build/private_code_test:private_code_failure_test", - "type": "generated_script", - }, - "profile_provider_unittest": { - "label": "//chrome/browser/metrics/perf:profile_provider_unittest", - "type": "console_test_launcher", - }, - "pthreadpool_unittests": { - "label": "//third_party/pthreadpool:pthreadpool_unittests", - "type": "console_test_launcher", - }, - "push_apps_to_background_apk": { - "label": "//tools/android/push_apps_to_background:push_apps_to_background_apk", - "type": "additional_compile_target", - }, - "remoting/client:client": { - "label": "//remoting/client:client", - "type": "additional_compile_target", - }, - "remoting/host:host": { - "label": "//remoting/host:host", - "type": "additional_compile_target", - }, - "remoting_unittests": { - "label": "//remoting:remoting_unittests", - "type": "windowed_test_launcher", - }, - "resource_sizes_chromecast": { - "label": "//chromecast:resource_sizes_chromecast", - "type": "generated_script", - }, - "resource_sizes_cronet_sample_apk": { - "label": "//components/cronet/android:resource_sizes_cronet_sample_apk", - "type": "generated_script", - }, - "resource_sizes_lacros_chrome": { - "label": "//chromeos/lacros:resource_sizes_lacros_chrome", - "type": "generated_script", - }, - "rust_build_tests": { - "label": "//build/rust/tests", - "type": "additional_compile_target", - }, - "rust_gtest_interop_unittests": { - "label": "//testing/rust_gtest_interop:rust_gtest_interop_unittests", - "type": "console_test_launcher", - }, - "sandbox_linux_unittests": { - "label": "//sandbox/linux:sandbox_linux_unittests", - "type": "console_test_launcher", - }, - "sandbox_unittests": { - "label": "//sandbox:sandbox_unittests", - "type": "console_test_launcher", - }, - "sbox_integration_tests": { - "label": "//sandbox/win:sbox_integration_tests", - "type": "console_test_launcher", - }, - "sbox_unittests": { - "label": "//sandbox/win:sbox_unittests", - "type": "console_test_launcher", - }, - "sbox_validation_tests": { - "label": "//sandbox/win:sbox_validation_tests", - "type": "console_test_launcher", - }, - "services_junit_tests": { - "label": "//services:services_junit_tests", - "type": "generated_script", - }, - "services_unittests": { - "label": "//services:services_unittests", - "type": "windowed_test_launcher", - }, - "setup_unittests": { - "label": "//chrome/installer/setup:setup_unittests", - "type": "console_test_launcher", - }, - "shell_dialogs_unittests": { - "label": "//ui/shell_dialogs:shell_dialogs_unittests", - "type": "console_test_launcher", - "args": [ - "--test-launcher-jobs=1", - ], - }, - "shell_encryption_unittests": { - "label": "//third_party/shell-encryption:shell_encryption_unittests", - "type": "console_test_launcher", - }, - "skia_unittests": { - "label": "//skia:skia_unittests", - "type": "console_test_launcher", - }, - "snapshot_unittests": { - "label": "//ui/snapshot:snapshot_unittests", - "type": "windowed_test_launcher", - }, - "sql_unittests": { - "label": "//sql:sql_unittests", - "type": "console_test_launcher", - }, - "storage_unittests": { - "label": "//storage:storage_unittests", - "type": "console_test_launcher", - }, - "strip_lacros_files": { - "label": "//chrome:strip_lacros_files", - "type": "additional_compile_target", - }, - "symupload": { - "label": "//third_party/breakpad:symupload", - "type": "additional_compile_target", - }, - "sync_integration_tests": { - "label": "//chrome/test:sync_integration_tests", - "type": "windowed_test_launcher", - }, - "sync_performance_tests": { - "label": "//chrome/test:sync_performance_tests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "skip_usage_check": True, - "args": [ - "sync_performance_tests", - "--non-telemetry=true", - "--test-launcher-print-test-stdio=always", - "--test-launcher-jobs=1", - "--test-launcher-retry-limit=0", - ], - }, - "system_webview_apk": { - "label": "//android_webview:system_webview_apk", - "type": "additional_compile_target", - }, - "system_webview_shell_apk": { - "label": "//android_webview/tools/system_webview_shell:system_webview_shell_apk", - "type": "additional_compile_target", - }, - "system_webview_shell_layout_test_apk": { - "label": "//android_webview/tools/system_webview_shell:system_webview_shell_layout_test_apk", - "type": "console_test_launcher", - }, - "system_webview_wpt": { - "label": "//android_webview/test:system_webview_wpt", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, - "telemetry_gpu_integration_test": { - "label": "//chrome/test:telemetry_gpu_integration_test", - "type": "generated_script", - }, - "telemetry_gpu_integration_test_android_chrome": { - "label": "//chrome/test:telemetry_gpu_integration_test_android_chrome", - "type": "generated_script", - }, - "telemetry_gpu_integration_test_android_webview": { - "label": "//chrome/test:telemetry_gpu_integration_test_android_webview", - "type": "script", - "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py", - "args": [ - "../../content/test/gpu/run_gpu_integration_test.py", - ], - }, - "telemetry_gpu_integration_test_fuchsia": { - "label": "//content/test:telemetry_gpu_integration_test_fuchsia", - "type": "script", - "script": "//testing/scripts/run_gpu_integration_test_as_googletest.py", - "args": [ - "../../content/test/gpu/run_gpu_integration_test_fuchsia.py", - "--logs-dir", - "${ISOLATED_OUTDIR}", - ], - }, - "telemetry_gpu_integration_test_scripts_only": { - "label": "//chrome/test:telemetry_gpu_integration_test_scripts_only", - "type": "additional_compile_target", - }, - "telemetry_gpu_unittests": { - "label": "//chrome/test:telemetry_gpu_unittests", - "type": "script", - "script": "//testing/scripts/run_telemetry_as_googletest.py", - "args": [ - "../../content/test/gpu/run_unittests.py", - "-v", - ], - }, - "telemetry_perf_unittests": { - "label": "//chrome/test:telemetry_perf_unittests", - "type": "generated_script", - }, - "telemetry_perf_unittests_android_chrome": { - "label": "//chrome/test:telemetry_perf_unittests_android_chrome", - "type": "script", - "script": "//testing/scripts/run_telemetry_as_googletest.py", - "args": [ - "../../tools/perf/run_tests", - "-v", - ], - }, - "telemetry_perf_unittests_android_monochrome": { - "label": "//chrome/test:telemetry_perf_unittests_android_monochrome", - "type": "script", - "script": "//testing/scripts/run_telemetry_as_googletest.py", - "args": [ - "../../tools/perf/run_tests", - "-v", - ], - }, - "telemetry_unittests": { - "label": "//chrome/test:telemetry_unittests", - "type": "script", - "script": "//testing/scripts/run_telemetry_as_googletest.py", - "args": [ - "--xvfb", - "../../tools/perf/run_telemetry_tests", - "-v", - "--jobs=1", - "--chrome-root", - "../../", - ], - }, - "test_cpp_including_rust_unittests": { - "label": "//build/rust/tests/test_cpp_including_rust:test_cpp_including_rust_unittests", - "type": "console_test_launcher", - }, - "test_env_py_unittests": { - "label": "//testing:test_env_py_unittests", - "type": "generated_script", - }, - "test_serde_json_lenient": { - "label": "//build/rust/tests/test_serde_json_lenient:test_serde_json_lenient", - "type": "console_test_launcher", - }, - "testing_pytype": { - "label": "//testing:testing_pytype", - "type": "script", - "script": "//testing/run_pytype.py", - }, - "touch_to_fill_junit_tests": { - "label": "//chrome/browser/touch_to_fill/password_manager/android:touch_to_fill_junit_tests", - "type": "generated_script", - }, - "trace_processor_shell": { - "label": "//third_party/perfetto/src/trace_processor:trace_processor_shell", - "type": "additional_compile_target", - }, - "tracing_perftests": { - "label": "//components/tracing:tracing_perftests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "skip_usage_check": True, - "args": [ - "tracing_perftests", - "--non-telemetry=true", - "--test-launcher-print-test-stdio=always", - "--adb-path", - "src/third_party/android_sdk/public/platform-tools/adb", - ], - }, - "traffic_annotation_auditor_dependencies": { - "label": "//:traffic_annotation_auditor_dependencies", - "type": "additional_compile_target", - }, - "traffic_annotation_proto": { - "label": "//chrome/browser/privacy:traffic_annotation_proto", - "type": "additional_compile_target", - }, - "trichrome_chrome_bundle_smoke_test": { - "label": "//chrome/android:trichrome_chrome_bundle_smoke_test", - "type": "console_test_launcher", - }, - "trichrome_webview_wpt_64": { - "label": "//android_webview/test:trichrome_webview_wpt_64", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, - "ui_android_unittests": { - "label": "//ui/android:ui_android_unittests", - "type": "console_test_launcher", - }, - "ui_base_unittests": { - "label": "//ui/base:ui_base_unittests", - "type": "windowed_test_launcher", - }, - "ui_chromeos_unittests": { - "label": "//ui/chromeos:ui_chromeos_unittests", - "type": "windowed_test_launcher", - }, - "ui_junit_tests": { - "label": "//ui:ui_junit_tests", - "type": "generated_script", - }, - "ui_touch_selection_unittests": { - "label": "//ui/touch_selection:ui_touch_selection_unittests", - "type": "windowed_test_launcher", - }, - "ui_unittests": { - "label": "//ui/tests:ui_unittests", - "type": "console_test_launcher", - }, - "unit_tests": { - "label": "//chrome/test:unit_tests", - "type": "windowed_test_launcher", - }, - "updater_tests": { - "label": "//chrome/updater:updater_tests", - "type": "console_test_launcher", - "args": [ - "--gtest_shuffle", - "--test-launcher-timeout=180000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000", - ], - }, - "updater_tests_system": { - "label": "//chrome/updater:updater_tests_system", - "type": "console_test_launcher", - "args": [ - "--gtest_shuffle", - "--test-launcher-timeout=180000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000", - "--exclude-paths-from-win-defender", - ], - }, - "updater_tests_win_uac": { - "label": "//chrome/updater:updater_tests_win_uac", - "type": "script", - "script": "//testing/scripts/run_telemetry_as_googletest.py", - "args": [ - "test_service/run_command_as_standard_user.py", - "--command=updater_tests.exe", - "--test-launcher-bot-mode", - "--cfi-diag=0", - "--gtest_shuffle", - "--test-launcher-timeout=180000", - "--ui-test-action-max-timeout=45000", - "--ui-test-action-timeout=40000", - ], - }, - "upload_trace_processor": { - "label": "//tools/perf/core/perfetto_binary_roller:upload_trace_processor", - "type": "generated_script", - }, - "url_unittests": { - "label": "//url:url_unittests", - "type": "console_test_launcher", - }, - "usage_time_limit_unittests": { - "label": "//chrome/browser/ash/child_accounts/time_limit_consistency_test:usage_time_limit_unittests", - "type": "console_test_launcher", - }, - "v4l2_stateless_decoder": { - "label": "//media/gpu/v4l2:v4l2_stateless_decoder", - "type": "additional_compile_target", - }, - "v4l2_unittest": { - "label": "//media/gpu/v4l2:v4l2_unittest", - "type": "additional_compile_target", - }, - "vaapi_unittest": { - "label": "//media/gpu/vaapi:vaapi_unittest", - "type": "console_test_launcher", - }, - "variations_desktop_smoke_tests": { - "label": "//chrome/test/variations:variations_desktop_smoke_tests", - "type": "generated_script", - }, - "variations_smoke_tests": { - "label": "//chrome/test:variations_smoke_tests", - "type": "generated_script", - }, - "video_decode_accelerator_perf_tests": { - "label": "//media/gpu/test:video_decode_accelerator_perf_tests", - "type": "additional_compile_target", - }, - "video_decode_accelerator_tests": { - "label": "//media/gpu/test:video_decode_accelerator_tests", - "type": "console_test_launcher", - }, - "video_encode_accelerator_perf_tests": { - "label": "//media/gpu/test:video_encode_accelerator_perf_tests", - "type": "additional_compile_target", - }, - "video_encode_accelerator_tests": { - "label": "//media/gpu/test:video_encode_accelerator_tests", - "type": "additional_compile_target", - }, - "views_examples_unittests": { - "label": "//ui/views/examples:views_examples_unittests", - "type": "windowed_test_launcher", - }, - "views_perftests": { - "label": "//ui/views:views_perftests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "args": [ - "--xvfb", - "--non-telemetry=true", - "views_perftests", - ], - }, - "views_unittests": { - "label": "//ui/views:views_unittests", - "type": "windowed_test_launcher", - }, - "viz_unittests": { - "label": "//components/viz:viz_unittests", - "type": "windowed_test_launcher", - }, - "vr_android_unittests": { - "label": "//chrome/browser/android/vr:vr_android_unittests", - "type": "console_test_launcher", - }, - "vr_common_perftests": { - "label": "//chrome/browser/vr:vr_common_perftests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "args": [ - "vr_common_perftests", - "--non-telemetry=true", - "--adb-path", - "src/third_party/android_sdk/public/platform-tools/adb", - ], - }, - "vr_common_unittests": { - "label": "//chrome/browser/vr:vr_common_unittests", - "type": "console_test_launcher", - }, - "vr_perf_tests": { - "label": "//tools/perf/contrib/vr_benchmarks:vr_perf_tests", - "type": "script", - "script": "//testing/scripts/run_performance_tests.py", - "args": [ - "../../tools/perf/run_benchmark", - ], - }, - "vrcore_fps_test": { - "label": "//chrome/test/vr/perf:vrcore_fps_test", - "type": "script", - "script": "//chrome/test/vr/perf/vrcore_fps/run_vrcore_fps_test.py", - "args": [ - "-v", - ], - }, - "vulkan_tests": { - "label": "//gpu/vulkan:vulkan_tests", - "type": "windowed_test_launcher", - }, - "wayland_client_perftests": { - "label": "//components/exo/wayland:wayland_client_perftests", - "type": "windowed_test_launcher", - }, - "wayland_client_tests": { - "label": "//components/exo/wayland:wayland_client_tests", - "type": "windowed_test_launcher", - }, - "web_engine_browsertests": { - "label": "//fuchsia_web/webengine:web_engine_browsertests", - "type": "console_test_launcher", - }, - "web_engine_integration_tests": { - "label": "//fuchsia_web/webengine:web_engine_integration_tests", - "type": "console_test_launcher", - }, - "web_engine_shell_pkg": { - "label": "//fuchsia_web/shell:web_engine_shell_pkg", - "type": "additional_compile_target", - }, - "web_engine_unittests": { - "label": "//fuchsia_web/webengine:web_engine_unittests", - "type": "console_test_launcher", - }, - "webapk_client_junit_tests": { - "label": "//chrome/android/webapk/libs/client:webapk_client_junit_tests", - "type": "generated_script", - }, - "webapk_shell_apk_h2o_junit_tests": { - "label": "//chrome/android/webapk/shell_apk:webapk_shell_apk_h2o_junit_tests", - "type": "generated_script", - }, - "webapk_shell_apk_junit_tests": { - "label": "//chrome/android/webapk/shell_apk:webapk_shell_apk_junit_tests", - "type": "generated_script", - }, - "webgpu_blink_web_tests": { - "label": "//:webgpu_blink_web_tests", - "type": "generated_script", - "args": [ - "--results-directory", - "${ISOLATED_OUTDIR}", - ], - }, - "webview_64_cts_tests": { - "label": "//android_webview/test:webview_64_cts_tests", - "type": "script", - "script": "//android_webview/tools/run_cts.py", - "args": [ - "--skip-expected-failures", - "--use-webview-provider", - "apks/SystemWebView64.apk", - "--apk-under-test", - "apks/SystemWebView64.apk", - "--use-apk-under-test-flags-file", - "-v", - "--output-directory", - ".", - ], - }, - "webview_cts_tests": { - "label": "//android_webview/test:webview_cts_tests", - "type": "script", - "script": "//android_webview/tools/run_cts.py", - "args": [ - "--skip-expected-failures", - "--use-webview-provider", - "apks/SystemWebView.apk", - "--apk-under-test", - "apks/SystemWebView.apk", - "--use-apk-under-test-flags-file", - "-v", - "--output-directory", - ".", - ], - }, - "webview_instrumentation_test_apk": { - "label": "//android_webview/test:webview_instrumentation_test_apk", - "type": "console_test_launcher", - }, - "webview_trichrome_64_cts_hostside_tests": { - "label": "//android_webview/test:webview_trichrome_64_cts_hostside_tests", - "type": "script", - "script": "//android_webview/tools/run_cts.py", - "args": [ - "--cts-gcs-path", - "../../android_webview/tools/cts_config/webview_cts_hostside_gcs_path.json", - "--skip-expected-failures", - "--additional-apk", - "apks/TrichromeLibrary64.apk", - "--use-webview-provider", - "apks/TrichromeWebView64.apk", - "--module-apk", - "CtsHostsideWebViewTests.apk", - ], - }, - "webview_trichrome_64_cts_tests": { - "label": "//android_webview/test:webview_trichrome_64_cts_tests", - "type": "script", - "script": "//android_webview/tools/run_cts.py", - "args": [ - "--skip-expected-failures", - "--additional-apk", - "apks/TrichromeLibrary64.apk", - "--use-webview-provider", - "apks/TrichromeWebView64.apk", - "--apk-under-test", - "apks/TrichromeWebView64.apk", - "--use-apk-under-test-flags-file", - "-v", - "--output-directory", - ".", - ], - }, - "webview_trichrome_cts_tests": { - "label": "//android_webview/test:webview_trichrome_cts_tests", - "type": "script", - "script": "//android_webview/tools/run_cts.py", - "args": [ - "--skip-expected-failures", - "--additional-apk", - "apks/TrichromeLibrary.apk", - "--use-webview-provider", - "apks/TrichromeWebView.apk", - "--apk-under-test", - "apks/TrichromeWebView.apk", - "--use-apk-under-test-flags-file", - "-v", - "--output-directory", - ".", - ], - }, - "webview_ui_test_app_test_apk": { - "label": "//android_webview/tools/automated_ui_tests:webview_ui_test_app_test_apk", - "type": "console_test_launcher", - }, - "wm_unittests": { - "label": "//ui/wm:wm_unittests", - "type": "windowed_test_launcher", - }, - "wtf_unittests": { - "label": "//third_party/blink/renderer/platform/wtf:wtf_unittests", - "type": "console_test_launcher", - }, - "xr_browser_tests": { - "label": "//chrome/test:xr_browser_tests", - "type": "windowed_test_launcher", - "executable": "run_xr_browser_tests.py", - "executable_suffix": "", - "args": [ - "--enable-gpu", - "--test-launcher-bot-mode", - "--test-launcher-jobs=1", - "--test-launcher-retry-limit=0", - "--enable-pixel-output-in-tests", - ], - }, - "xvfb_py_unittests": { - "label": "//testing:xvfb_py_unittests", - "type": "generated_script", - }, - "zlib_unittests": { - "label": "//third_party/zlib:zlib_unittests", - "type": "console_test_launcher", - "args": [ - "--test-launcher-timeout=400000", - ], - }, - "zucchini_unittests": { - "label": "//components/zucchini:zucchini_unittests", - "type": "console_test_launcher", - }, -}
diff --git a/testing/buildbot/mixins.pyl b/testing/buildbot/mixins.pyl index 6439579..d9e77db 100644 --- a/testing/buildbot/mixins.pyl +++ b/testing/buildbot/mixins.pyl
@@ -2,7 +2,10 @@ # Instead: # 1. Modify //infra/config/targets/mixins.star # 2. Run //infra/config/main.star -# 3. Run //infra/config/scripts/sync-pyl-files.py + +# The copy of this file in //testing/buildbot is not read by generate_buildbot_json.py, +# but must be present for downstream uses. It can be kept in sync by running +# //infra/config/scripts/sync-pyl-files.py. { '10-x86-emulator': {
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index 68269ba..ec3019b 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1187,10 +1187,6 @@ '--test-launcher-filter-file=../../testing/buildbot/filters/android.device.cc_unittests.filter', ], }, - 'android-15-x64-fyi-rel': { - # TODO(crbug.com/343210417) : Remove once fixed. - 'experiment_percentage': 100, - }, 'android-pie-arm64-rel': { 'ci_only': True, }, @@ -4532,10 +4528,6 @@ '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_11.viz_unittests.filter', ], }, - 'android-15-x64-fyi-rel': { - # TODO(crbug.com/343210417) : Remove once fixed. - 'experiment_percentage': 100, - }, 'android-pie-arm64-rel': { 'ci_only': True, }, @@ -5295,7 +5287,7 @@ }, 'android-15-x64-fyi-rel': { 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/android.14.webview_instrumentation_test_apk.filter', + '--test-launcher-filter-file=../../testing/buildbot/filters/android.emulator_15.webview_instrumentation_test_apk.filter', ], 'swarming': { 'shards': 12,
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl deleted file mode 100644 index 645e5486..0000000 --- a/testing/buildbot/test_suites.pyl +++ /dev/null
@@ -1,8117 +0,0 @@ -# THIS IS A GENERATED FILE DO NOT EDIT!!! -# Instead: -# 1. Modify //infra/config/targets/basic_suites.star, //infra/config/targets/compound_suites.star and/or //infra/config/targets/matrix_compound_suites.star -# 2. Run //infra/config/main.star -# 3. Run //infra/config/scripts/sync-pyl-files.py - -{ - 'basic_suites': { - - 'android_ar_gtests': { - 'monochrome_public_test_ar_apk': {}, - 'vr_android_unittests': {}, - }, - - 'android_ci_only_fieldtrial_webview_tests': { - 'webview_trichrome_64_cts_tests_no_field_trial': { - 'test': 'webview_trichrome_64_cts_tests', - 'mixins': [ - 'webview_cts_archive', - ], - 'args': [ - '--disable-field-trial-config', - '--store-tombstones', - ], - 'ci_only': True, - 'swarming': { - 'shards': 2, - }, - }, - 'webview_ui_test_app_test_apk_no_field_trial': { - 'test': 'webview_ui_test_app_test_apk', - 'args': [ - '--disable-field-trial-config', - ], - 'ci_only': True, - }, - }, - - 'android_emulator_specific_chrome_public_tests': { - 'chrome_public_test_apk': { - 'mixins': [ - 'skia_gold_test', - 'emulator-8-cores', - ], - 'swarming': { - 'shards': 20, - }, - }, - 'chrome_public_unit_test_apk': { - 'mixins': [ - 'skia_gold_test', - ], - 'swarming': { - 'shards': 4, - }, - }, - }, - - 'android_emulator_specific_network_enabled_content_browsertests': { - 'content_browsertests_with_emulator_network': { - 'test': 'content_browsertests', - 'mixins': [ - 'emulator-enable-network', - ], - 'args': [ - '--gtest_filter=QuicConnectionMigrationTest.*', - ], - }, - }, - - 'android_hardware_specific_gtests': { - 'cc_unittests': {}, - 'viz_unittests': {}, - }, - - 'android_isolated_scripts': { - 'content_shell_crash_test': { - 'args': [ - '--platform=android', - ], - 'resultdb': { - 'enable': True, - 'result_format': 'single', - }, - }, - }, - - 'android_limited_capacity_gtests': { - 'android_browsertests': {}, - 'blink_platform_unittests': { - 'mixins': [ - 'skia_gold_test', - ], - }, - 'content_browsertests': { - 'swarming': { - 'shards': 20, - }, - }, - 'webview_instrumentation_test_apk_multiple_process_mode': { - 'test': 'webview_instrumentation_test_apk', - 'args': [ - '--webview-process-mode=multiple', - ], - 'swarming': { - 'shards': 6, - }, - }, - }, - - 'android_monochrome_smoke_tests': { - 'monochrome_public_bundle_smoke_test': {}, - 'monochrome_public_smoke_test': {}, - }, - - 'android_pie_rel_reduced_capacity_gtests': { - 'android_browsertests': {}, - 'blink_platform_unittests': { - 'mixins': [ - 'skia_gold_test', - ], - }, - 'cc_unittests': {}, - 'content_browsertests': { - 'swarming': { - 'shards': 20, - }, - }, - 'viz_unittests': {}, - 'webview_instrumentation_test_apk_multiple_process_mode': { - 'test': 'webview_instrumentation_test_apk', - 'args': [ - '--webview-process-mode=multiple', - ], - 'swarming': { - 'shards': 5, - }, - }, - }, - - 'android_rel_isolated_scripts': { - 'android_blink_wpt_tests': { - 'test': 'chrome_public_wpt', - 'results_handler': 'layout tests', - 'swarming': { - 'shards': 4, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - 'experiment_percentage': 100, - }, - 'private_code_failure_test': {}, - 'webview_blink_wpt_tests': { - 'test': 'trichrome_webview_wpt_64', - 'results_handler': 'layout tests', - 'swarming': { - 'shards': 4, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - 'experiment_percentage': 100, - }, - }, - - 'android_smoke_tests': { - 'chrome_public_smoke_test': {}, - }, - - 'android_specific_chromium_gtests': { - 'android_browsertests': { - 'swarming': { - 'shards': 4, - }, - }, - 'android_sync_integration_tests': { - 'args': [ - '--test-launcher-batch-limit=1', - ], - 'swarming': { - 'shards': 1, - }, - }, - 'android_webview_unittests': {}, - 'content_shell_test_apk': { - 'swarming': { - 'shards': 3, - }, - }, - 'gl_tests_validating': { - 'test': 'gl_tests', - 'args': [ - '--use-cmd-decoder=validating', - ], - }, - 'gl_unittests': {}, - 'mojo_test_apk': {}, - 'ui_android_unittests': {}, - 'webview_instrumentation_test_apk_multiple_process_mode': { - 'test': 'webview_instrumentation_test_apk', - 'args': [ - '--webview-process-mode=multiple', - ], - 'swarming': { - 'shards': 5, - }, - }, - }, - - 'android_specific_coverage_java_tests': { - 'content_shell_test_apk': { - 'swarming': { - 'shards': 3, - }, - }, - 'mojo_test_apk': {}, - 'webview_instrumentation_test_apk_multiple_process_mode': { - 'test': 'webview_instrumentation_test_apk', - 'args': [ - '--webview-process-mode=multiple', - ], - 'swarming': { - 'shards': 5, - }, - }, - 'webview_instrumentation_test_apk_single_process_mode': { - 'test': 'webview_instrumentation_test_apk', - 'args': [ - '--webview-process-mode=single', - ], - 'swarming': { - 'shards': 3, - }, - }, - }, - - 'android_trichrome_smoke_tests': { - 'trichrome_chrome_bundle_smoke_test': {}, - }, - - 'android_webview_gpu_telemetry_tests': { - 'android_webview_pixel_skia_gold_test': { - 'telemetry_test_name': 'pixel', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - ], - }, - }, - - 'android_wpr_record_replay_tests': { - 'chrome_java_test_wpr_tests': { - 'mixins': [ - 'skia_gold_test', - ], - }, - }, - - 'ash_pixel_gtests': { - 'ash_pixeltests': { - 'mixins': [ - 'skia_gold_test', - ], - 'args': [ - '--enable-pixel-output-in-tests', - ], - }, - }, - - 'aura_gtests': { - 'aura_unittests': {}, - 'compositor_unittests': {}, - 'wm_unittests': {}, - }, - - 'bfcache_android_specific_gtests': { - 'bf_cache_android_browsertests': { - 'test': 'android_browsertests', - 'args': [ - '--disable-features=BackForwardCache', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'bfcache_generic_gtests': { - 'bf_cache_content_browsertests': { - 'test': 'content_browsertests', - 'args': [ - '--disable-features=BackForwardCache', - ], - 'swarming': { - 'shards': 20, - }, - }, - }, - - 'bfcache_linux_specific_gtests': { - 'bf_cache_browser_tests': { - 'test': 'browser_tests', - 'args': [ - '--disable-features=BackForwardCache', - ], - 'swarming': { - 'shards': 10, - }, - }, - }, - - 'blink_unittests_suite': { - 'blink_unit_tests': { - 'test': 'blink_unittests', - }, - }, - - 'blink_web_tests_ppapi_isolated_scripts': { - 'ppapi_blink_web_tests': { - 'test': 'blink_web_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--num-retries=3', - '--test-list=../../third_party/blink/web_tests/TestLists/ppapi', - ], - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'cast_junit_tests': { - 'cast_base_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - }, - 'cast_shell_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - }, - }, - - 'chrome_android_finch_smoke_tests': { - 'variations_android_smoke_tests': { - 'test': 'variations_desktop_smoke_tests', - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--target-platform=android', - ], - }, - 'variations_webview_smoke_tests': { - 'test': 'variations_desktop_smoke_tests', - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--target-platform=webview', - ], - }, - }, - - 'chrome_finch_smoke_tests': { - 'variations_desktop_smoke_tests': { - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - ], - 'chromeos_args': [ - '--target-platform=cros', - ], - 'lacros_args': [ - '--target-platform=lacros', - ], - }, - }, - - 'chrome_isolated_script_tests': { - 'chrome_sizes': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - }, - }, - 'variations_smoke_tests': { - 'mixins': [ - 'skia_gold_test', - ], - 'resultdb': { - 'enable': True, - 'result_format': 'single', - }, - }, - }, - - 'chrome_private_code_test_isolated_scripts': { - 'chrome_private_code_test': {}, - }, - - 'chrome_profile_generator_tests': { - 'chrome_public_apk_profile_tests': { - 'test': 'chrome_public_apk_baseline_profile_generator', - 'ci_only': True, - 'experiment_percentage': 100, - }, - }, - - 'chrome_public_tests': { - 'chrome_public_test_apk': { - 'mixins': [ - 'skia_gold_test', - ], - 'swarming': { - 'shards': 19, - }, - }, - 'chrome_public_unit_test_apk': { - 'mixins': [ - 'skia_gold_test', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'chrome_public_wpt_suite': { - 'chrome_public_wpt': { - 'results_handler': 'layout tests', - 'args': [ - '--no-wpt-internal', - ], - 'swarming': { - 'shards': 36, - 'expiration': 18000, - 'hard_timeout': 14400, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'chrome_sizes_android': { - 'chrome_sizes': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'remove_mixins': [ - 'bullhead', - 'marshmallow', - 'oreo_fleet', - 'pie_fleet', - 'walleye', - ], - 'args': [ - '--platform=android', - ], - 'swarming': { - 'dimensions': { - 'cpu': 'x86-64', - 'os': 'Ubuntu-22.04', - }, - }, - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - }, - }, - }, - - 'chrome_sizes_suite': { - 'chrome_sizes': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - }, - }, - }, - - 'chromedriver_py_tests_isolated_scripts': { - 'chromedriver_py_tests': { - 'args': [ - '--test-type=integration', - ], - 'resultdb': { - 'enable': True, - }, - }, - 'chromedriver_py_tests_headless_shell': { - 'args': [ - '--test-type=integration', - ], - 'resultdb': { - 'enable': True, - }, - }, - 'chromedriver_replay_unittests': {}, - }, - - 'chromeos_annotation_scripts': { - 'check_network_annotations': { - 'script': 'check_network_annotations.py', - }, - }, - - 'chromeos_arm_gtests': { - 'video_decode_accelerator_tests_v4l2': { - 'test': 'video_decode_accelerator_tests', - 'args': [ - '--as-root', - '--validator_type=none', - '../../media/test/data/test-25fps.vp9', - '../../media/test/data/test-25fps.vp9.json', - ], - 'ci_only': True, - 'experiment_percentage': 100, - }, - }, - - 'chromeos_browser_all_tast_tests': { - 'chrome_all_tast_tests': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--tast-retries=1', - ], - 'swarming': { - 'shards': 10, - 'io_timeout': 3600, - 'idempotent': False, - }, - }, - }, - - 'chromeos_browser_criticalstaging_tast_tests': { - 'chrome_criticalstaging_tast_tests': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'ci_only': True, - 'swarming': { - 'shards': 2, - 'io_timeout': 3600, - 'idempotent': False, - }, - 'experiment_percentage': 100, - }, - }, - - 'chromeos_browser_disabled_tast_tests': { - 'chrome_disabled_tast_tests': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'ci_only': True, - 'swarming': { - 'shards': 2, - 'io_timeout': 3600, - 'idempotent': False, - }, - 'experiment_percentage': 100, - }, - }, - - 'chromeos_browser_integration_tests': { - 'disk_usage_tast_test': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--strip-chrome', - ], - 'swarming': { - 'idempotent': False, - }, - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - }, - }, - }, - - 'chromeos_chrome_all_tast_tests': { - 'chrome_all_tast_tests': { - 'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS', - 'test_level_retries': 1, - 'timeout_sec': 14400, - 'shards': 15, - }, - }, - - 'chromeos_chrome_cq_medium_tast_tests': { - 'cq_medium_tast_tests': { - 'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS', - 'test_level_retries': 2, - 'timeout_sec': 3600, - 'shards': 5, - }, - }, - - 'chromeos_chrome_criticalstaging_tast_tests': { - 'chrome_criticalstaging_tast_tests': { - 'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS', - 'test_level_retries': 2, - 'ci_only': True, - 'timeout_sec': 14400, - 'shards': 3, - 'experiment_percentage': 100, - }, - }, - - 'chromeos_chrome_disabled_tast_tests': { - 'chrome_disabled_tast_tests': { - 'tast_expr': 'STUB_STRING_TO_RUN_TAST_TESTS', - 'test_level_retries': 1, - 'ci_only': True, - 'timeout_sec': 14400, - 'shards': 2, - 'experiment_percentage': 100, - }, - }, - - 'chromeos_device_only_gtests': { - 'base_unittests': {}, - }, - - 'chromeos_integration_tests_suite': { - 'chromeos_integration_tests': {}, - }, - - 'chromeos_isolated_scripts': { - 'telemetry_perf_unittests': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--browser=cros-chrome', - '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote', - '--xvfb', - '--typ-max-failures=3', - ], - 'swarming': { - 'shards': 12, - 'idempotent': False, - }, - }, - 'telemetry_unittests': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--jobs=1', - '--browser=cros-chrome', - '$$MAGIC_SUBSTITUTION_ChromeOSTelemetryRemote', - '--typ-max-failures=3', - ], - 'swarming': { - 'shards': 24, - 'idempotent': False, - }, - }, - }, - - 'chromeos_js_code_coverage_browser_tests_suite': { - 'chromeos_js_code_coverage_browser_tests': { - 'test': 'browser_tests', - 'swarming': { - 'shards': 32, - }, - }, - }, - - 'chromeos_system_friendly_gtests': { - 'aura_unittests': { - 'args': [ - '--ozone-platform=headless', - ], - }, - 'base_unittests': {}, - 'capture_unittests': { - 'args': [ - '--test-launcher-jobs=1', - '--gtest_filter=-*UsingRealWebcam_CaptureMjpeg*', - ], - }, - 'cc_unittests': {}, - 'crypto_unittests': {}, - 'display_unittests': {}, - 'fake_libva_driver_unittest': { - 'args': [ - '--env-var', - 'LIBVA_DRIVERS_PATH', - './', - '--env-var', - 'LIBVA_DRIVER_NAME', - 'libfake', - ], - 'experiment_percentage': 100, - }, - 'google_apis_unittests': {}, - 'ipc_tests': {}, - 'latency_unittests': {}, - 'libcups_unittests': {}, - 'media_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.media_unittests.filter', - ], - }, - 'midi_unittests': {}, - 'mojo_unittests': {}, - 'net_unittests': { - 'args': [ - '--vpython-dir=../../vpython_dir_linux_amd64', - '--gtest_filter=-PythonUtils.PythonRunTime', - ], - 'swarming': { - 'shards': 3, - 'cipd_packages': [ - { - 'cipd_package': 'infra/3pp/tools/cpython3/linux-amd64', - 'location': 'vpython_dir_linux_amd64', - 'revision': 'version:2@3.8.10.chromium.34', - }, - { - 'cipd_package': 'infra/tools/luci/vpython3/linux-amd64', - 'location': 'vpython_dir_linux_amd64', - 'revision': 'git_revision:6ee2ba6ba03b09d8d8763f524aa77edf1945ca92', - }, - { - 'cipd_package': 'infra/tools/cipd/linux-amd64', - 'location': 'vpython_dir_linux_amd64', - 'revision': 'git_revision:200dbdf0e967e81388359d3f85f095d39b35db67', - }, - ], - }, - }, - 'ozone_gl_unittests': { - 'args': [ - '--stop-ui', - ], - }, - 'ozone_unittests': {}, - 'pdf_unittests': {}, - 'printing_unittests': {}, - 'profile_provider_unittest': { - 'args': [ - '--stop-ui', - '--test-launcher-jobs=1', - ], - }, - 'rust_gtest_interop_unittests': {}, - 'sql_unittests': {}, - 'url_unittests': {}, - 'video_decode_accelerator_tests_fake_vaapi': { - 'test': 'video_decode_accelerator_tests', - 'args': [ - '--env-var', - 'LIBVA_DRIVERS_PATH', - './', - '--env-var', - 'LIBVA_DRIVER_NAME', - 'libfake', - '../../media/test/data/test-25fps.vp9', - '../../media/test/data/test-25fps.vp9.json', - ], - 'ci_only': True, - }, - }, - - 'chromeos_system_friendly_gtests_fails_vmlab': { - 'fake_libva_driver_unittest': { - 'args': [ - '--env-var', - 'LIBVA_DRIVERS_PATH', - './', - '--env-var', - 'LIBVA_DRIVER_NAME', - 'libfake', - ], - 'experiment_percentage': 100, - }, - 'video_decode_accelerator_tests_fake_vaapi': { - 'test': 'video_decode_accelerator_tests', - 'args': [ - '--env-var', - 'LIBVA_DRIVERS_PATH', - './', - '--env-var', - 'LIBVA_DRIVER_NAME', - 'libfake', - '../../media/test/data/test-25fps.vp9', - '../../media/test/data/test-25fps.vp9.json', - ], - 'ci_only': True, - }, - }, - - 'chromeos_system_friendly_gtests_vmlab': { - 'aura_unittests': { - 'args': [ - '--ozone-platform=headless', - ], - }, - 'base_unittests': {}, - 'capture_unittests': { - 'args': [ - '--test-launcher-jobs=1', - '--gtest_filter=-*UsingRealWebcam_CaptureMjpeg*', - ], - }, - 'cc_unittests': {}, - 'crypto_unittests': {}, - 'display_unittests': {}, - 'google_apis_unittests': {}, - 'ipc_tests': {}, - 'latency_unittests': {}, - 'libcups_unittests': {}, - 'media_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.betty.media_unittests.filter', - ], - }, - 'midi_unittests': {}, - 'mojo_unittests': {}, - 'net_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.betty.net_unittests.filter', - ], - }, - 'ozone_gl_unittests': { - 'args': [ - '--stop-ui', - ], - }, - 'ozone_unittests': {}, - 'pdf_unittests': {}, - 'printing_unittests': {}, - 'profile_provider_unittest': { - 'args': [ - '--stop-ui', - '--test-launcher-jobs=1', - ], - }, - 'rust_gtest_interop_unittests': {}, - 'sql_unittests': {}, - 'url_unittests': {}, - }, - - 'chromeos_vaapi_fakelib_gtests': { - 'vaapi_unittest': { - 'mixins': [ - 'vaapi_unittest_args', - 'vaapi_unittest_libfake_args', - ], - }, - }, - - 'chromeos_vaapi_gtests': { - 'vaapi_unittest': { - 'mixins': [ - 'vaapi_unittest_args', - ], - }, - }, - - 'chromium_android_scripts': { - 'check_network_annotations': { - 'script': 'check_network_annotations.py', - }, - }, - - 'chromium_android_webkit_gtests': { - 'blink_heap_unittests': {}, - 'webkit_unit_tests': { - 'test': 'blink_unittests', - }, - }, - - 'chromium_dev_android_gtests': { - 'chrome_public_smoke_test': {}, - }, - - 'chromium_dev_linux_gtests': { - 'base_unittests': { - 'swarming': { - 'dimensions': { - 'cores': '8', - }, - }, - }, - 'browser_tests': { - 'swarming': { - 'shards': 8, - 'dimensions': { - 'cores': '8', - }, - }, - }, - 'content_browsertests': { - 'swarming': { - 'shards': 5, - 'dimensions': { - 'cores': '8', - }, - }, - }, - 'content_unittests': { - 'swarming': { - 'dimensions': { - 'cores': '2', - }, - }, - }, - 'interactive_ui_tests': { - 'swarming': { - 'shards': 3, - 'dimensions': { - 'cores': '8', - }, - }, - }, - 'net_unittests': { - 'swarming': { - 'dimensions': { - 'cores': '8', - }, - }, - }, - 'rust_gtest_interop_unittests': {}, - 'unit_tests': { - 'swarming': { - 'dimensions': { - 'cores': '2', - }, - }, - }, - }, - - 'chromium_dev_mac_gtests': { - 'base_unittests': {}, - 'content_unittests': {}, - 'net_unittests': {}, - 'rust_gtest_interop_unittests': {}, - 'unit_tests': {}, - }, - - 'chromium_dev_win_gtests': { - 'base_unittests': {}, - 'content_browsertests': { - 'swarming': { - 'shards': 4, - }, - }, - 'content_unittests': {}, - 'interactive_ui_tests': { - 'swarming': { - 'shards': 3, - }, - }, - 'net_unittests': {}, - 'rust_gtest_interop_unittests': {}, - 'unit_tests': {}, - }, - - 'chromium_gtests': { - 'absl_hardening_tests': {}, - 'angle_unittests': { - 'android_args': [ - '-v', - ], - 'use_isolated_scripts_api': True, - }, - 'base_unittests': {}, - 'blink_common_unittests': {}, - 'blink_heap_unittests': {}, - 'blink_platform_unittests': { - 'mixins': [ - 'skia_gold_test', - ], - }, - 'boringssl_crypto_tests': {}, - 'boringssl_ssl_tests': {}, - 'capture_unittests': { - 'args': [ - '--gtest_filter=-*UsingRealWebcam*', - ], - }, - 'cast_unittests': {}, - 'components_browsertests': {}, - 'components_unittests': { - 'swarming': { - 'shards': 3, - }, - 'android_swarming': { - 'shards': 6, - }, - }, - 'content_browsertests': { - 'swarming': { - 'shards': 8, - }, - 'android_swarming': { - 'shards': 15, - }, - }, - 'content_unittests': { - 'android_swarming': { - 'shards': 3, - }, - }, - 'crashpad_tests': {}, - 'crypto_unittests': {}, - 'env_chromium_unittests': { - 'ci_only': True, - }, - 'events_unittests': {}, - 'fuzzing_unittests': {}, - 'gcm_unit_tests': {}, - 'gin_unittests': {}, - 'google_apis_unittests': {}, - 'gpu_unittests': {}, - 'gwp_asan_unittests': {}, - 'ipc_tests': {}, - 'latency_unittests': {}, - 'leveldb_unittests': { - 'ci_only': True, - }, - 'libjingle_xmpp_unittests': {}, - 'liburlpattern_unittests': {}, - 'media_unittests': {}, - 'midi_unittests': {}, - 'mojo_unittests': {}, - 'net_unittests': { - 'android_swarming': { - 'shards': 3, - }, - }, - 'perfetto_unittests': {}, - 'services_unittests': {}, - 'shell_dialogs_unittests': {}, - 'skia_unittests': {}, - 'sql_unittests': {}, - 'storage_unittests': {}, - 'ui_base_unittests': {}, - 'ui_touch_selection_unittests': {}, - 'url_unittests': {}, - 'webkit_unit_tests': { - 'test': 'blink_unittests', - 'android_swarming': { - 'shards': 6, - }, - }, - 'wtf_unittests': {}, - 'zlib_unittests': {}, - }, - - 'chromium_gtests_for_devices_with_graphical_output': { - 'cc_unittests': {}, - 'device_unittests': {}, - 'display_unittests': {}, - 'gfx_unittests': {}, - 'unit_tests': { - 'android_swarming': { - 'shards': 2, - }, - }, - 'viz_unittests': {}, - }, - - 'chromium_gtests_for_linux_and_chromeos_only': { - 'dbus_unittests': {}, - }, - - 'chromium_gtests_for_linux_and_mac_only': { - 'openscreen_unittests': {}, - }, - - 'chromium_gtests_for_linux_only': { - 'ozone_unittests': {}, - 'ozone_x11_unittests': {}, - }, - - 'chromium_gtests_for_win_and_linux_only': { - 'pthreadpool_unittests': { - 'ci_only': True, - }, - }, - - 'chromium_ios_scripts': { - 'check_static_initializers': { - 'script': 'check_static_initializers.py', - }, - }, - - 'chromium_junit_tests_scripts': { - 'android_webview_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'base_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'build_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'chrome_java_test_pagecontroller_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'chrome_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'components_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'content_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'device_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'junit_unit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'keyboard_accessory_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'media_base_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'module_installer_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'net_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'paint_preview_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'password_check_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'password_manager_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'services_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'touch_to_fill_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'ui_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'webapk_client_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'webapk_shell_apk_h2o_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - 'webapk_shell_apk_junit_tests': { - 'mixins': [ - 'x86-64', - 'linux-jammy', - 'junit-swarming-emulator', - ], - 'remove_mixins': [ - 'emulator-4-cores', - 'nougat-x86-emulator', - 'oreo-x86-emulator', - 'walleye', - 'pie_fleet', - ], - }, - }, - - 'chromium_linux_scripts': { - 'check_network_annotations': { - 'script': 'check_network_annotations.py', - }, - 'check_static_initializers': { - 'script': 'check_static_initializers.py', - }, - 'checkdeps': { - 'script': 'checkdeps.py', - }, - 'checkperms': { - 'script': 'checkperms.py', - }, - 'metrics_python_tests': { - 'script': 'metrics_python_tests.py', - }, - 'webkit_lint': { - 'script': 'blink_lint_expectations.py', - }, - }, - - 'chromium_mac_scripts': { - 'check_static_initializers': { - 'script': 'check_static_initializers.py', - }, - 'metrics_python_tests': { - 'script': 'metrics_python_tests.py', - }, - 'webkit_lint': { - 'script': 'blink_lint_expectations.py', - }, - }, - - 'chromium_multiscreen_gtests': { - 'multiscreen_interactive_ui_tests': { - 'test': 'interactive_ui_tests', - 'args': [ - '--gtest_filter=*MultiScreen*:*VirtualDisplayUtil*', - ], - 'swarming': { - 'dimensions': { - 'pool': 'chromium.tests.multiscreen', - }, - }, - }, - }, - - 'chromium_web_tests_brfetch_isolated_scripts': { - 'brfetch_blink_web_tests': { - 'test': 'blink_web_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=background-resource-fetch', - '--skipped=always', - '--num-retries=3', - ], - 'ci_only': True, - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - 'experiment_percentage': 100, - }, - 'brfetch_blink_wpt_tests': { - 'test': 'blink_wpt_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=background-resource-fetch', - '--skipped=always', - '--num-retries=3', - ], - 'ci_only': True, - 'swarming': { - 'shards': 3, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - 'experiment_percentage': 100, - }, - 'brfetch_headless_shell_wpt_tests': { - 'test': 'headless_shell_wpt', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=background-resource-fetch', - '--skipped=always', - '--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - '--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/headless_shell.filter', - ], - 'ci_only': True, - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - 'experiment_percentage': 100, - }, - }, - - 'chromium_web_tests_graphite_isolated_scripts': { - 'graphite_enabled_blink_web_tests': { - 'test': 'blink_web_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=enable-skia-graphite', - '--skipped=always', - '--timeout-ms=20000', - '--num-retries=3', - ], - 'swarming': { - 'shards': 2, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'graphite_enabled_blink_wpt_tests': { - 'test': 'blink_wpt_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=enable-skia-graphite', - '--skipped=always', - '--timeout-ms=20000', - '--num-retries=3', - ], - 'swarming': { - 'shards': 7, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'graphite_enabled_headless_shell_wpt_tests': { - 'test': 'headless_shell_wpt', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=enable-skia-graphite', - '--skipped=always', - '--timeout-multiplier=2', - '--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - '--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/headless_shell.filter', - ], - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'chromium_web_tests_high_dpi_isolated_scripts': { - 'high_dpi_blink_web_tests': { - 'test': 'blink_web_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=highdpi', - '--skipped=always', - '--num-retries=3', - ], - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'high_dpi_blink_wpt_tests': { - 'test': 'blink_wpt_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=highdpi', - '--skipped=always', - '--num-retries=3', - ], - 'swarming': { - 'shards': 3, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'high_dpi_headless_shell_wpt_tests': { - 'test': 'headless_shell_wpt', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=highdpi', - '--skipped=always', - '--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - '--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/headless_shell.filter', - ], - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'chromium_webkit_isolated_scripts': { - 'blink_web_tests': { - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--num-retries=3', - ], - 'swarming': { - 'shards': 5, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'blink_wpt_tests': { - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--num-retries=3', - ], - 'swarming': { - 'shards': 7, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'chrome_wpt_tests': { - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - ], - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'headless_shell_wpt_tests': { - 'test': 'headless_shell_wpt', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--test-type', - 'testharness', - 'reftest', - 'crashtest', - 'print-reftest', - '--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - '--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/headless_shell.filter', - ], - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'chromium_win_scripts': { - 'check_network_annotations': { - 'script': 'check_network_annotations.py', - }, - 'metrics_python_tests': { - 'script': 'metrics_python_tests.py', - }, - 'webkit_lint': { - 'script': 'blink_lint_expectations.py', - }, - }, - - 'clang_tot_gtests': { - 'base_unittests': {}, - }, - - 'client_v8_chromium_gtests': { - 'app_shell_unittests': {}, - 'browser_tests': { - 'swarming': { - 'shards': 10, - }, - }, - 'chrome_app_unittests': {}, - 'chromedriver_unittests': {}, - 'components_browsertests': {}, - 'components_unittests': {}, - 'compositor_unittests': {}, - 'content_browsertests': {}, - 'content_unittests': {}, - 'device_unittests': {}, - 'extensions_browsertests': {}, - 'extensions_unittests': {}, - 'gcm_unit_tests': {}, - 'gin_unittests': {}, - 'google_apis_unittests': {}, - 'gpu_unittests': {}, - 'headless_browsertests': {}, - 'headless_unittests': {}, - 'interactive_ui_tests': {}, - 'net_unittests': {}, - 'pdf_unittests': {}, - 'remoting_unittests': {}, - 'services_unittests': {}, - 'sync_integration_tests': { - 'swarming': { - 'shards': 3, - }, - }, - 'unit_tests': {}, - }, - - 'client_v8_chromium_isolated_scripts': { - 'content_shell_crash_test': { - 'resultdb': { - 'enable': True, - 'result_format': 'single', - }, - }, - 'telemetry_gpu_unittests': { - 'swarming': { - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - 'telemetry_perf_unittests': { - 'args': [ - '--xvfb', - '--extra-browser-args=--enable-crashpad', - ], - 'swarming': { - 'shards': 12, - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - 'telemetry_unittests': { - 'args': [ - '--jobs=1', - '--extra-browser-args=--disable-gpu', - ], - 'swarming': { - 'shards': 4, - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'components_perftests_isolated_scripts': { - 'components_perftests': { - 'args': [ - '--gtest-benchmark-name=components_perftests', - ], - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - 'args': [ - '--smoke-test-mode', - ], - }, - }, - }, - - 'cronet_clang_coverage_additional_gtests': { - 'absl_hardening_tests': {}, - 'crypto_unittests': {}, - 'zlib_unittests': {}, - }, - - 'cronet_gtests': { - 'cronet_sample_test_apk': {}, - 'cronet_smoketests_apk': {}, - 'cronet_smoketests_missing_native_library_instrumentation_apk': {}, - 'cronet_smoketests_platform_only_instrumentation_apk': {}, - 'cronet_test_instrumentation_apk': { - 'mixins': [ - 'emulator-enable-network', - ], - 'swarming': { - 'shards': 3, - }, - }, - 'cronet_tests_android': {}, - 'cronet_unittests_android': {}, - 'net_unittests': { - 'swarming': { - 'shards': 4, - }, - }, - }, - - 'cronet_resource_sizes': { - 'resource_sizes_cronet_sample_apk': { - 'swarming': { - 'dimensions': { - 'os': 'Ubuntu-22.04', - 'cpu': 'x86-64', - }, - }, - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - }, - 'resultdb': { - 'enable': True, - 'result_format': 'single', - }, - }, - }, - - 'cronet_sizes_suite': { - 'cronet_sizes': { - 'remove_mixins': [ - 'bullhead', - 'marshmallow', - 'oreo_fleet', - 'pie_fleet', - 'walleye', - ], - 'swarming': { - 'dimensions': { - 'os': 'Ubuntu-22.04', - 'cpu': 'x86-64', - }, - }, - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - }, - 'resultdb': { - 'enable': True, - 'result_format': 'single', - 'result_file': '${ISOLATED_OUTDIR}/sizes/test_results.json', - }, - }, - }, - - 'desktop_chromium_isolated_scripts': { - 'blink_python_tests': { - 'resultdb': { - 'enable': True, - }, - }, - 'blink_web_tests': { - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--num-retries=3', - ], - 'swarming': { - 'shards': 5, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'blink_wpt_tests': { - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--num-retries=3', - ], - 'swarming': { - 'shards': 7, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'chrome_wpt_tests': { - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - ], - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'content_shell_crash_test': { - 'resultdb': { - 'enable': True, - 'result_format': 'single', - }, - }, - 'flatbuffers_unittests': { - 'resultdb': { - 'enable': True, - 'result_format': 'single', - }, - }, - 'grit_python_unittests': { - 'resultdb': { - 'enable': True, - }, - }, - 'headless_shell_wpt_tests': { - 'test': 'headless_shell_wpt', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--test-type', - 'testharness', - 'reftest', - 'crashtest', - 'print-reftest', - '--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - '--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/headless_shell.filter', - ], - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'telemetry_gpu_unittests': { - 'swarming': { - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - 'telemetry_unittests': { - 'args': [ - '--jobs=1', - '--extra-browser-args=--disable-gpu', - ], - 'swarming': { - 'shards': 8, - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - 'views_perftests': { - 'args': [ - '--gtest-benchmark-name=views_perftests', - ], - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - 'args': [ - '--smoke-test-mode', - ], - }, - }, - }, - - 'desktop_chromium_mac_osxbeta_scripts': { - 'content_shell_crash_test': { - 'resultdb': { - 'enable': True, - 'result_format': 'single', - }, - }, - 'flatbuffers_unittests': { - 'resultdb': { - 'enable': True, - 'result_format': 'single', - }, - }, - 'grit_python_unittests': { - 'resultdb': { - 'enable': True, - }, - }, - 'telemetry_gpu_unittests': { - 'swarming': { - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - 'telemetry_unittests': { - 'args': [ - '--jobs=1', - '--extra-browser-args=--disable-gpu', - ], - 'swarming': { - 'shards': 8, - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - 'views_perftests': { - 'args': [ - '--gtest-benchmark-name=views_perftests', - ], - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - 'args': [ - '--smoke-test-mode', - ], - }, - }, - }, - - 'desktop_once_isolated_scripts': { - 'test_env_py_unittests': { - 'resultdb': { - 'enable': True, - }, - }, - 'xvfb_py_unittests': { - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'devtools_browser_tests_suite': { - 'devtools_browser_tests': { - 'test': 'browser_tests', - 'args': [ - '--gtest_filter=*DevTools*', - ], - 'swarming': { - 'shards': 1, - }, - }, - }, - - 'devtools_web_isolated_scripts': { - 'blink_web_tests': { - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--num-retries=3', - ], - 'swarming': { - 'shards': 5, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'enterprise_companion_gtests_linux': { - 'enterprise_companion_integration_tests': { - 'mixins': [ - 'updater-default-pool', - ], - }, - 'enterprise_companion_tests': { - 'mixins': [ - 'updater-default-pool', - ], - }, - }, - - 'enterprise_companion_gtests_mac': { - 'enterprise_companion_integration_tests': { - 'mixins': [ - 'updater-mac-pool', - ], - }, - 'enterprise_companion_tests': { - 'mixins': [ - 'updater-mac-pool', - ], - }, - }, - - 'enterprise_companion_gtests_win': { - 'enterprise_companion_integration_tests': { - 'mixins': [ - 'integrity_high', - 'updater-default-pool', - ], - }, - 'enterprise_companion_tests': { - 'mixins': [ - 'integrity_high', - 'updater-default-pool', - ], - }, - }, - - 'fieldtrial_android_tests': { - 'android_browsertests_no_fieldtrial': { - 'test': 'android_browsertests', - 'args': [ - '--disable-field-trial-config', - ], - 'ci_only': True, - 'swarming': { - 'shards': 3, - }, - }, - }, - - 'fieldtrial_browser_tests': { - 'browser_tests_no_field_trial': { - 'test': 'browser_tests', - 'args': [ - '--disable-field-trial-config', - ], - 'ci_only': True, - 'swarming': { - 'shards': 10, - }, - }, - 'components_browsertests_no_field_trial': { - 'test': 'components_browsertests', - 'args': [ - '--disable-field-trial-config', - ], - 'ci_only': True, - }, - 'interactive_ui_tests_no_field_trial': { - 'test': 'interactive_ui_tests', - 'args': [ - '--disable-field-trial-config', - ], - 'ci_only': True, - }, - 'sync_integration_tests_no_field_trial': { - 'test': 'sync_integration_tests', - 'args': [ - '--disable-field-trial-config', - ], - 'ci_only': True, - }, - }, - - 'finch_smoke_tests': { - 'base_unittests': {}, - }, - - 'fuchsia_chrome_gtests': { - 'absl_hardening_tests': {}, - 'accessibility_unittests': {}, - 'aura_unittests': {}, - 'base_unittests': {}, - 'blink_common_unittests': {}, - 'blink_fuzzer_unittests': {}, - 'blink_heap_unittests': {}, - 'blink_platform_unittests': { - 'mixins': [ - 'skia_gold_test', - ], - }, - 'blink_unittests': {}, - 'boringssl_crypto_tests': {}, - 'boringssl_ssl_tests': {}, - 'capture_unittests': {}, - 'cc_unittests': { - 'swarming': { - 'shards': 2, - }, - }, - 'components_browsertests': { - 'args': [ - '--test-arg=--disable-gpu', - '--test-arg=--headless', - '--test-arg=--ozone-platform=headless', - ], - }, - 'components_unittests': { - 'swarming': { - 'shards': 2, - }, - }, - 'compositor_unittests': {}, - 'content_browsertests': { - 'args': [ - '--test-arg=--disable-gpu', - '--test-arg=--headless', - '--test-arg=--ozone-platform=headless', - ], - 'swarming': { - 'shards': 14, - }, - }, - 'content_unittests': {}, - 'courgette_unittests': {}, - 'crypto_unittests': {}, - 'display_unittests': {}, - 'events_unittests': {}, - 'filesystem_service_unittests': {}, - 'gcm_unit_tests': {}, - 'gfx_unittests': {}, - 'gin_unittests': {}, - 'google_apis_unittests': {}, - 'gpu_unittests': {}, - 'gwp_asan_unittests': {}, - 'headless_browsertests': {}, - 'headless_unittests': {}, - 'ipc_tests': {}, - 'latency_unittests': {}, - 'media_unittests': {}, - 'message_center_unittests': {}, - 'midi_unittests': {}, - 'mojo_unittests': {}, - 'native_theme_unittests': {}, - 'net_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.net_unittests.filter', - ], - 'swarming': { - 'shards': 4, - }, - }, - 'ozone_gl_unittests': { - 'args': [ - '--test-arg=--ozone-platform=headless', - ], - }, - 'ozone_unittests': {}, - 'perfetto_unittests': {}, - 'services_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.services_unittests.filter', - ], - }, - 'shell_dialogs_unittests': {}, - 'skia_unittests': {}, - 'snapshot_unittests': {}, - 'sql_unittests': {}, - 'storage_unittests': {}, - 'ui_base_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.ui_base_unittests.filter', - ], - }, - 'ui_touch_selection_unittests': {}, - 'ui_unittests': {}, - 'url_unittests': {}, - 'views_examples_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_examples_unittests.filter', - ], - }, - 'views_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.views_unittests.filter', - ], - }, - 'viz_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.viz_unittests.filter', - ], - }, - 'wm_unittests': {}, - 'wtf_unittests': {}, - 'zlib_unittests': {}, - }, - - 'fuchsia_sizes_tests': { - 'fuchsia_sizes': { - 'args': [ - '--sizes-path', - 'tools/fuchsia/size_tests/fyi_sizes_smoketest.json', - ], - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - }, - }, - }, - - 'fuchsia_web_engine_gtests': { - 'cast_runner_browsertests': {}, - 'cast_runner_integration_tests': {}, - 'cast_runner_unittests': {}, - 'web_engine_browsertests': {}, - 'web_engine_integration_tests': {}, - 'web_engine_unittests': {}, - }, - - 'gl_gtests_passthrough': { - 'gl_tests_passthrough': { - 'test': 'gl_tests', - 'args': [ - '--use-cmd-decoder=passthrough', - ], - 'linux_args': [ - '--no-xvfb', - ], - 'swarming': { - 'shards': 2, - }, - }, - 'gl_unittests': {}, - }, - - 'gpu_angle_fuchsia_unittests_isolated_scripts': { - 'angle_unittests': {}, - }, - - 'gpu_angle_ios_end2end_gtests': { - 'angle_end2end_tests': { - 'args': [ - '--release', - ], - 'use_isolated_scripts_api': True, - }, - }, - - 'gpu_angle_ios_white_box_gtests': { - 'angle_white_box_tests': { - 'args': [ - '--release', - ], - 'use_isolated_scripts_api': True, - }, - }, - - 'gpu_angle_unit_gtests': { - 'angle_unittests': { - 'android_args': [ - '-v', - ], - 'linux_args': [ - '--no-xvfb', - ], - 'use_isolated_scripts_api': True, - }, - }, - - 'gpu_command_buffer_perf_passthrough_isolated_scripts': { - 'passthrough_command_buffer_perftests': { - 'test': 'command_buffer_perftests', - 'args': [ - '--gtest-benchmark-name=passthrough_command_buffer_perftests', - '-v', - '--use-cmd-decoder=passthrough', - '--use-angle=gl-null', - '--fast-run', - ], - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - 'args': [ - '--smoke-test-mode', - ], - }, - }, - }, - - 'gpu_common_and_optional_telemetry_tests': { - 'info_collection_tests': { - 'telemetry_test_name': 'info_collection', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '$$MAGIC_SUBSTITUTION_GPUExpectedVendorId', - '$$MAGIC_SUBSTITUTION_GPUExpectedDeviceId', - '--extra-browser-args=--force_high_performance_gpu', - ], - }, - 'trace_test': { - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - }, - - 'gpu_common_gtests_passthrough': { - 'gl_tests_passthrough': { - 'test': 'gl_tests', - 'args': [ - '--use-cmd-decoder=passthrough', - '--use-gl=angle', - ], - 'chromeos_args': [ - '--stop-ui', - '$$MAGIC_SUBSTITUTION_ChromeOSGtestFilterFile', - ], - 'desktop_args': [ - '--use-gpu-in-tests', - ], - 'linux_args': [ - '--no-xvfb', - ], - 'swarming': { - 'shards': 2, - }, - }, - 'gl_unittests': { - 'mixins': [ - 'skia_gold_test', - ], - 'chromeos_args': [ - '--stop-ui', - '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.gl_unittests.filter', - ], - 'desktop_args': [ - '--use-gpu-in-tests', - ], - 'linux_args': [ - '--no-xvfb', - ], - }, - }, - - 'gpu_common_gtests_validating': { - 'gl_tests_validating': { - 'test': 'gl_tests', - 'args': [ - '--use-cmd-decoder=validating', - ], - 'chromeos_args': [ - '--stop-ui', - '$$MAGIC_SUBSTITUTION_ChromeOSGtestFilterFile', - ], - 'desktop_args': [ - '--use-gpu-in-tests', - ], - 'linux_args': [ - '--no-xvfb', - ], - }, - 'gl_unittests': { - 'mixins': [ - 'skia_gold_test', - ], - 'chromeos_args': [ - '--stop-ui', - '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.gl_unittests.filter', - ], - 'desktop_args': [ - '--use-gpu-in-tests', - ], - 'linux_args': [ - '--no-xvfb', - ], - }, - }, - - 'gpu_dawn_common_isolated_scripts': { - 'telemetry_gpu_unittests': { - 'swarming': { - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'gpu_dawn_gtests': { - 'dawn_end2end_implicit_device_sync_tests': { - 'test': 'dawn_end2end_tests', - 'mixins': [ - 'dawn_end2end_gpu_test', - ], - 'args': [ - '--enable-implicit-device-sync', - ], - 'linux_args': [ - '--no-xvfb', - ], - 'ci_only': True, - 'swarming': { - 'shards': 2, - }, - }, - 'dawn_end2end_skip_validation_tests': { - 'test': 'dawn_end2end_tests', - 'mixins': [ - 'dawn_end2end_gpu_test', - ], - 'args': [ - '--enable-toggles=skip_validation', - ], - 'linux_args': [ - '--no-xvfb', - ], - 'swarming': { - 'shards': 2, - }, - }, - 'dawn_end2end_tests': { - 'mixins': [ - 'dawn_end2end_gpu_test', - ], - 'linux_args': [ - '--no-xvfb', - ], - 'swarming': { - 'shards': 2, - }, - }, - 'dawn_end2end_wire_tests': { - 'test': 'dawn_end2end_tests', - 'mixins': [ - 'dawn_end2end_gpu_test', - ], - 'args': [ - '--use-wire', - ], - 'linux_args': [ - '--no-xvfb', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'gpu_dawn_gtests_no_dxc': { - 'dawn_end2end_no_dxc_tests': { - 'test': 'dawn_end2end_tests', - 'mixins': [ - 'dawn_end2end_gpu_test', - ], - 'args': [ - '--disable-toggles=use_dxc', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'gpu_dawn_gtests_no_dxc_with_validation': { - 'dawn_end2end_no_dxc_validation_layers_tests': { - 'test': 'dawn_end2end_tests', - 'mixins': [ - 'dawn_end2end_gpu_test', - ], - 'args': [ - '--disable-toggles=use_dxc', - '--enable-backend-validation', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'gpu_dawn_gtests_with_validation': { - 'dawn_end2end_validation_layers_tests': { - 'test': 'dawn_end2end_tests', - 'mixins': [ - 'dawn_end2end_gpu_test', - ], - 'args': [ - '--enable-backend-validation', - ], - 'linux_args': [ - '--no-xvfb', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'gpu_dawn_perf_smoke_isolated_scripts': { - 'dawn_perf_tests': { - 'args': [ - '--override-steps=1', - '--gtest-benchmark-name=dawn_perf_tests', - '-v', - ], - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - 'args': [ - '--smoke-test-mode', - ], - }, - }, - }, - - 'gpu_dawn_web_platform_webgpu_cts_force_swiftshader': { - 'webgpu_swiftshader_web_platform_cts_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-webgpu-adapter=swiftshader', - '--test-filter=*web_platform*', - ], - 'swarming': { - 'shards': 2, - }, - }, - 'webgpu_swiftshader_web_platform_cts_with_validation_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-webgpu-adapter=swiftshader', - '--test-filter=*web_platform*', - '--enable-dawn-backend-validation', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'gpu_dawn_webgpu_blink_web_tests': { - 'webgpu_blink_web_tests': { - 'mixins': [ - 'has_native_resultdb_integration', - 'webgpu_cts', - ], - 'args': [ - '--flag-specific=webgpu', - ], - }, - 'webgpu_blink_web_tests_with_backend_validation': { - 'test': 'webgpu_blink_web_tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'webgpu_cts', - ], - 'args': [ - '--flag-specific=webgpu-with-backend-validation', - '--timeout-ms=30000', - ], - }, - }, - - 'gpu_dawn_webgpu_blink_web_tests_force_swiftshader': { - 'webgpu_swiftshader_blink_web_tests': { - 'test': 'webgpu_blink_web_tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'webgpu_cts', - ], - 'args': [ - '--flag-specific=webgpu-swiftshader', - ], - }, - 'webgpu_swiftshader_blink_web_tests_with_backend_validation': { - 'test': 'webgpu_blink_web_tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'webgpu_cts', - ], - 'args': [ - '--flag-specific=webgpu-swiftshader-with-backend-validation', - '--timeout-ms=30000', - ], - }, - }, - - 'gpu_dawn_webgpu_compat_cts': { - 'webgpu_cts_compat_tests': { - 'telemetry_test_name': 'webgpu_compat_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - ], - 'args': [ - '--extra-browser-args=--enable-features=WebGPUExperimentalFeatures --use-webgpu-adapter=opengles', - ], - 'android_args': [ - '--extra-browser-args=--use-angle=gles-egl', - ], - 'linux_args': [ - '--extra-browser-args=--use-angle=gl', - ], - 'swarming': { - 'shards': 14, - }, - 'android_swarming': { - 'shards': 36, - }, - }, - }, - - 'gpu_dawn_webgpu_cts': { - 'webgpu_cts_dedicated_worker_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-worker=dedicated', - ], - 'swarming': { - 'shards': 1, - }, - 'android_swarming': { - 'shards': 2, - }, - }, - 'webgpu_cts_service_worker_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-worker=service', - ], - 'swarming': { - 'shards': 1, - }, - 'android_swarming': { - 'shards': 2, - }, - }, - 'webgpu_cts_shared_worker_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-worker=shared', - ], - 'swarming': { - 'shards': 1, - }, - 'android_swarming': { - 'shards': 2, - }, - }, - 'webgpu_cts_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'swarming': { - 'shards': 14, - }, - 'android_swarming': { - 'shards': 36, - }, - }, - 'webgpu_cts_with_validation_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--enable-dawn-backend-validation', - ], - 'swarming': { - 'shards': 14, - }, - 'android_swarming': { - 'shards': 36, - }, - }, - }, - - 'gpu_dawn_webgpu_cts_asan': { - 'webgpu_cts_dedicated_worker_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-worker=dedicated', - ], - 'swarming': { - 'shards': 1, - }, - }, - 'webgpu_cts_fxc_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-fxc', - ], - 'swarming': { - 'shards': 8, - }, - }, - 'webgpu_cts_service_worker_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-worker=service', - ], - 'swarming': { - 'shards': 1, - }, - }, - 'webgpu_cts_shared_worker_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-worker=shared', - ], - 'swarming': { - 'shards': 1, - }, - }, - 'webgpu_cts_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'swarming': { - 'shards': 8, - }, - }, - }, - - 'gpu_dawn_webgpu_cts_fxc': { - 'webgpu_cts_fxc_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--use-fxc', - ], - 'ci_only': True, - 'swarming': { - 'shards': 14, - }, - }, - 'webgpu_cts_fxc_with_validation_tests': { - 'telemetry_test_name': 'webgpu_cts', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - 'webgpu_telemetry_cts', - 'linux_vulkan', - ], - 'args': [ - '--enable-dawn-backend-validation', - '--use-fxc', - ], - 'ci_only': True, - 'swarming': { - 'shards': 14, - }, - }, - }, - - 'gpu_default_and_optional_win_media_foundation_specific_gtests': { - 'media_foundation_browser_tests': { - 'test': 'browser_tests', - 'args': [ - '--gtest_filter=MediaFoundationEncryptedMediaTest*', - '--use-gpu-in-tests', - ], - }, - }, - - 'gpu_default_and_optional_win_specific_gtests': { - 'xr_browser_tests': { - 'args': [ - '--ignore-runtime-requirements=*', - ], - }, - }, - - 'gpu_desktop_specific_gtests': { - 'tab_capture_end2end_tests': { - 'test': 'browser_tests', - 'args': [ - '--enable-gpu', - '--test-launcher-bot-mode', - '--test-launcher-jobs=1', - '--gtest_filter=TabCaptureApiPixelTest.EndToEnd*', - ], - 'linux_args': [ - '--no-xvfb', - ], - }, - }, - - 'gpu_fyi_and_optional_non_linux_gtests': { - 'gpu_unittests': {}, - }, - - 'gpu_fyi_and_optional_win_specific_gtests': { - 'services_webnn_unittests': { - 'test': 'services_unittests', - 'args': [ - '--gtest_filter=WebNN*', - '--use-gpu-in-tests', - ], - }, - }, - - 'gpu_fyi_mac_specific_gtests': { - 'services_unittests': { - 'args': [ - '--gtest_filter=*Detection*', - '--use-gpu-in-tests', - ], - }, - }, - - 'gpu_fyi_vulkan_swiftshader_gtests': { - 'vulkan_swiftshader_content_browsertests': { - 'test': 'content_browsertests', - 'args': [ - '--enable-gpu', - '--test-launcher-bot-mode', - '--test-launcher-jobs=1', - '--test-launcher-filter-file=../../testing/buildbot/filters/vulkan.content_browsertests.filter', - '--enable-features=UiGpuRasterization,Vulkan', - '--use-vulkan=swiftshader', - '--enable-gpu-rasterization', - '--disable-software-compositing-fallback', - '--disable-vulkan-fallback-to-gl-for-testing', - '--disable-headless-mode', - ], - 'linux_args': [ - '--no-xvfb', - ], - }, - }, - - 'gpu_gl_passthrough_ganesh_telemetry_tests': { - 'context_lost_gl_passthrough_ganesh_tests': { - 'telemetry_test_name': 'context_lost', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite', - ], - }, - 'expected_color_pixel_gl_passthrough_ganesh_test': { - 'telemetry_test_name': 'expected_color', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite', - ], - }, - 'gpu_process_launch_tests': { - 'telemetry_test_name': 'gpu_process', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'hardware_accelerated_feature_tests': { - 'telemetry_test_name': 'hardware_accelerated_feature', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'pixel_skia_gold_gl_passthrough_ganesh_test': { - 'telemetry_test_name': 'pixel', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite', - ], - }, - 'screenshot_sync_gl_passthrough_ganesh_tests': { - 'telemetry_test_name': 'screenshot_sync', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite', - ], - }, - }, - - 'gpu_info_collection_telemetry_tests': { - 'info_collection_tests': { - 'telemetry_test_name': 'info_collection', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '$$MAGIC_SUBSTITUTION_GPUExpectedVendorId', - '$$MAGIC_SUBSTITUTION_GPUExpectedDeviceId', - '--extra-browser-args=--force_high_performance_gpu', - ], - }, - }, - - 'gpu_memory_buffer_impl_tests_suite': { - 'gpu_memory_buffer_impl_tests': { - 'test': 'gpu_unittests', - 'args': [ - '--enable-gpu', - '--use-gpu-in-tests', - '--gtest_filter=*GpuMemoryBufferImplTest*', - ], - 'lacros_args': [ - '--ozone-platform=wayland', - '--xvfb', - '--no-xvfb', - '--use-weston', - '--weston-use-gl', - ], - 'linux_args': [ - '--no-xvfb', - ], - }, - }, - - 'gpu_metal_passthrough_ganesh_telemetry_tests': { - 'context_lost_metal_passthrough_ganesh_tests': { - 'telemetry_test_name': 'context_lost', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite', - ], - }, - 'expected_color_pixel_metal_passthrough_ganesh_test': { - 'telemetry_test_name': 'expected_color', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite', - ], - }, - 'gpu_process_launch_tests': { - 'telemetry_test_name': 'gpu_process', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'hardware_accelerated_feature_tests': { - 'telemetry_test_name': 'hardware_accelerated_feature', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'pixel_skia_gold_metal_passthrough_ganesh_test': { - 'telemetry_test_name': 'pixel', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite', - ], - }, - 'screenshot_sync_metal_passthrough_ganesh_tests': { - 'telemetry_test_name': 'screenshot_sync', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite', - ], - }, - }, - - 'gpu_metal_passthrough_graphite_telemetry_tests': { - 'context_lost_metal_passthrough_graphite_tests': { - 'telemetry_test_name': 'context_lost', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite', - ], - }, - 'expected_color_pixel_metal_passthrough_graphite_test': { - 'telemetry_test_name': 'expected_color', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite', - ], - }, - 'gpu_process_launch_tests': { - 'telemetry_test_name': 'gpu_process', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'hardware_accelerated_feature_tests': { - 'telemetry_test_name': 'hardware_accelerated_feature', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'pixel_skia_gold_metal_passthrough_graphite_test': { - 'telemetry_test_name': 'pixel', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite', - ], - }, - 'screenshot_sync_metal_passthrough_graphite_tests': { - 'telemetry_test_name': 'screenshot_sync', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite', - ], - }, - }, - - 'gpu_noop_sleep_telemetry_test': { - 'noop_sleep_tests': { - 'telemetry_test_name': 'noop_sleep', - 'mixins': [ - 'gpu_integration_test_common_args', - ], - }, - }, - - 'gpu_passthrough_graphite_telemetry_tests': { - 'expected_color_pixel_passthrough_graphite_test': { - 'telemetry_test_name': 'expected_color', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --enable-features=SkiaGraphite', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - 'pixel_skia_gold_passthrough_graphite_test': { - 'telemetry_test_name': 'pixel', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --enable-features=SkiaGraphite', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - 'screenshot_sync_passthrough_graphite_tests': { - 'telemetry_test_name': 'screenshot_sync', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --enable-features=SkiaGraphite', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - }, - - 'gpu_passthrough_telemetry_tests': { - 'context_lost_passthrough_tests': { - 'telemetry_test_name': 'context_lost', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle', - ], - }, - 'expected_color_pixel_passthrough_test': { - 'telemetry_test_name': 'expected_color', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - 'gpu_process_launch_tests': { - 'telemetry_test_name': 'gpu_process', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'hardware_accelerated_feature_tests': { - 'telemetry_test_name': 'hardware_accelerated_feature', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'pixel_skia_gold_passthrough_test': { - 'telemetry_test_name': 'pixel', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - 'screenshot_sync_passthrough_tests': { - 'telemetry_test_name': 'screenshot_sync', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - }, - - 'gpu_pixel_passthrough_telemetry_tests': { - 'expected_color_pixel_passthrough_test': { - 'telemetry_test_name': 'expected_color', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle', - ], - }, - 'pixel_skia_gold_passthrough_test': { - 'telemetry_test_name': 'pixel', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle', - ], - }, - }, - - 'gpu_skia_renderer_vulkan_passthrough_telemetry_tests': { - 'vulkan_pixel_skia_gold_test': { - 'telemetry_test_name': 'pixel', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-vulkan=native --disable-vulkan-fallback-to-gl-for-testing --enable-features=Vulkan --use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - }, - - 'gpu_validating_telemetry_tests': { - 'context_lost_validating_tests': { - 'telemetry_test_name': 'context_lost', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=validating', - ], - }, - 'expected_color_pixel_validating_test': { - 'telemetry_test_name': 'expected_color', - 'mixins': [ - 'has_native_resultdb_integration', - 'skia_gold_test', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=validating', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - 'gpu_process_launch_tests': { - 'telemetry_test_name': 'gpu_process', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'hardware_accelerated_feature_tests': { - 'telemetry_test_name': 'hardware_accelerated_feature', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - 'pixel_skia_gold_validating_test': { - 'telemetry_test_name': 'pixel', - 'mixins': [ - 'has_native_resultdb_integration', - 'skia_gold_test', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--test-machine-name', - '${buildername}', - '--extra-browser-args=--use-cmd-decoder=validating', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - 'screenshot_sync_validating_tests': { - 'telemetry_test_name': 'screenshot_sync', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--dont-restore-color-profile-after-test', - '--extra-browser-args=--use-cmd-decoder=validating', - ], - 'android_args': [ - '--extra-browser-args=--force-online-connection-state-for-indicator', - ], - }, - }, - - 'gpu_vulkan_gtests': { - 'vulkan_tests': { - 'desktop_args': [ - '--use-gpu-in-tests', - ], - 'linux_args': [ - '--no-xvfb', - ], - }, - }, - - 'gpu_webcodecs_gl_passthrough_ganesh_telemetry_test': { - 'webcodecs_gl_passthrough_ganesh_tests': { - 'telemetry_test_name': 'webcodecs', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=gl --disable-features=SkiaGraphite', - ], - }, - }, - - 'gpu_webcodecs_metal_passthrough_ganesh_telemetry_test': { - 'webcodecs_metal_passthrough_ganesh_tests': { - 'telemetry_test_name': 'webcodecs', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --disable-features=SkiaGraphite', - ], - }, - }, - - 'gpu_webcodecs_metal_passthrough_graphite_telemetry_test': { - 'webcodecs_metal_passthrough_graphite_tests': { - 'telemetry_test_name': 'webcodecs', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=passthrough --use-gl=angle --use-angle=metal --enable-features=SkiaGraphite', - ], - }, - }, - - 'gpu_webcodecs_telemetry_test': { - 'webcodecs_tests': { - 'telemetry_test_name': 'webcodecs', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - }, - }, - - 'gpu_webcodecs_validating_telemetry_test': { - 'webcodecs_tests': { - 'telemetry_test_name': 'webcodecs', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=validating', - ], - }, - }, - - 'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests': { - 'webgl2_conformance_d3d11_passthrough_tests': { - 'telemetry_test_name': 'webgl2_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--webgl-conformance-version=2.0.1', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - '--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu', - ], - 'swarming': { - 'shards': 20, - }, - }, - }, - - 'gpu_webgl2_conformance_gl_passthrough_ganesh_telemetry_tests': { - 'webgl2_conformance_gl_passthrough_ganesh_tests': { - 'telemetry_test_name': 'webgl2_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--webgl-conformance-version=2.0.1', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - '--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu --disable-features=SkiaGraphite', - ], - 'swarming': { - 'shards': 20, - }, - }, - }, - - 'gpu_webgl2_conformance_gl_passthrough_telemetry_tests': { - 'webgl2_conformance_gl_passthrough_tests': { - 'telemetry_test_name': 'webgl2_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--webgl-conformance-version=2.0.1', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - '--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu', - ], - 'swarming': { - 'shards': 5, - }, - }, - }, - - 'gpu_webgl2_conformance_gles_passthrough_telemetry_tests': { - 'webgl2_conformance_gles_passthrough_tests': { - 'telemetry_test_name': 'webgl2_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--webgl-conformance-version=2.0.1', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - '--extra-browser-args=--use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu', - ], - 'swarming': { - 'shards': 20, - }, - }, - }, - - 'gpu_webgl2_conformance_metal_passthrough_graphite_telemetry_tests': { - 'webgl2_conformance_metal_passthrough_graphite_tests': { - 'telemetry_test_name': 'webgl2_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--webgl-conformance-version=2.0.1', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - '--extra-browser-args=--use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --enable-features=EGLDualGPURendering,ForceHighPerformanceGPUForWebGL,SkiaGraphite', - '--enable-metal-debug-layers', - ], - 'swarming': { - 'shards': 20, - }, - }, - }, - - 'gpu_webgl2_conformance_validating_telemetry_tests': { - 'webgl2_conformance_validating_tests': { - 'telemetry_test_name': 'webgl2_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--webgl-conformance-version=2.0.1', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - '--extra-browser-args=--use-cmd-decoder=validating --force_high_performance_gpu', - ], - 'swarming': { - 'shards': 20, - }, - }, - }, - - 'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests': { - 'webgl_conformance_d3d11_passthrough_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=d3d11 --use-cmd-decoder=passthrough --force_high_performance_gpu', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests': { - 'webgl_conformance_d3d9_passthrough_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=d3d9 --use-cmd-decoder=passthrough --force_high_performance_gpu', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'gpu_webgl_conformance_gl_passthrough_ganesh_telemetry_tests': { - 'webgl_conformance_gl_passthrough_ganesh_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu --disable-features=SkiaGraphite', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'gpu_webgl_conformance_gl_passthrough_telemetry_tests': { - 'webgl_conformance_gl_passthrough_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=gl --use-cmd-decoder=passthrough --force_high_performance_gpu', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'gpu_webgl_conformance_gles_passthrough_graphite_telemetry_tests': { - 'webgl_conformance_gles_passthrough_graphite_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu --enable-features=SkiaGraphite', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - ], - 'swarming': { - 'shards': 3, - }, - }, - }, - - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests': { - 'webgl_conformance_gles_passthrough_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=gles --use-cmd-decoder=passthrough --force_high_performance_gpu', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - ], - 'swarming': { - 'shards': 6, - }, - }, - }, - - 'gpu_webgl_conformance_metal_passthrough_ganesh_telemetry_tests': { - 'webgl_conformance_metal_passthrough_ganesh_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --enable-features=EGLDualGPURendering,ForceHighPerformanceGPUForWebGL --disable-features=SkiaGraphite', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - '--enable-metal-debug-layers', - ], - }, - }, - - 'gpu_webgl_conformance_metal_passthrough_graphite_telemetry_tests': { - 'webgl_conformance_metal_passthrough_graphite_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=metal --use-cmd-decoder=passthrough --enable-features=EGLDualGPURendering,ForceHighPerformanceGPUForWebGL,SkiaGraphite', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - '--enable-metal-debug-layers', - ], - }, - }, - - 'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests': { - 'webgl_conformance_swangle_passthrough_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough --force_high_performance_gpu', - '--test-filter=conformance/rendering/gl-drawelements.html', - ], - 'swarming': { - 'shards': 1, - }, - }, - }, - - 'gpu_webgl_conformance_swangle_passthrough_telemetry_tests': { - 'webgl_conformance_swangle_passthrough_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-gl=angle --use-angle=swiftshader --use-cmd-decoder=passthrough', - '--xvfb', - ], - 'swarming': { - 'shards': 1, - }, - }, - }, - - 'gpu_webgl_conformance_telemetry_tests': { - 'webgl_conformance_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--force_high_performance_gpu', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - ], - 'swarming': { - 'shards': 2, - }, - 'android_swarming': { - 'shards': 12, - }, - 'chromeos_swarming': { - 'shards': 20, - }, - }, - }, - - 'gpu_webgl_conformance_validating_telemetry_tests': { - 'webgl_conformance_validating_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-cmd-decoder=validating --force_high_performance_gpu', - '$$MAGIC_SUBSTITUTION_GPUWebGLRuntimeFile', - ], - 'swarming': { - 'shards': 2, - }, - 'android_swarming': { - 'shards': 6, - }, - }, - }, - - 'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests': { - 'webgl_conformance_vulkan_passthrough_tests': { - 'telemetry_test_name': 'webgl1_conformance', - 'mixins': [ - 'has_native_resultdb_integration', - 'gpu_integration_test_common_args', - ], - 'args': [ - '--extra-browser-args=--use-angle=vulkan --use-cmd-decoder=passthrough --force_high_performance_gpu', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'headless_browser_gtests': { - 'headless_browsertests': {}, - 'headless_unittests': {}, - }, - - 'headless_shell_wpt_tests_isolated_scripts': { - 'headless_shell_wpt_tests_include_all': { - 'test': 'headless_shell_wpt', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - ], - 'swarming': { - 'shards': 10, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'ios_blink_tests': { - 'absl_hardening_tests': {}, - 'angle_unittests': { - 'use_isolated_scripts_api': True, - }, - 'base_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.base_unittests.filter', - ], - }, - 'blink_common_unittests': {}, - 'blink_fuzzer_unittests': {}, - 'blink_heap_unittests': {}, - 'blink_platform_unittests': { - 'mixins': [ - 'skia_gold_test', - ], - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.blink_platform_unittests.filter', - ], - }, - 'boringssl_crypto_tests': {}, - 'boringssl_ssl_tests': {}, - 'capture_unittests': {}, - 'cast_unittests': {}, - 'cc_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.cc_unittests.filter', - '--use-gpu-in-tests', - ], - }, - 'components_browsertests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.use_blink.components_browsertests.filter', - ], - }, - 'components_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.use_blink.components_unittests.filter', - ], - }, - 'compositor_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.compositor_unittests.filter', - ], - }, - 'content_browsertests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.content_browsertests.filter', - ], - }, - 'content_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.content_unittests.filter', - ], - }, - 'crashpad_tests': {}, - 'crypto_unittests': {}, - 'device_unittests': {}, - 'display_unittests': {}, - 'env_chromium_unittests': {}, - 'events_unittests': {}, - 'gcm_unit_tests': {}, - 'gfx_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.gfx_unittests.filter', - ], - }, - 'gin_unittests': {}, - 'gl_unittests': {}, - 'google_apis_unittests': {}, - 'gpu_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.gpu_unittests.filter', - ], - }, - 'gwp_asan_unittests': {}, - 'latency_unittests': {}, - 'leveldb_unittests': {}, - 'libjingle_xmpp_unittests': {}, - 'liburlpattern_unittests': {}, - 'media_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.media_unittests.filter', - ], - }, - 'media_unittests_skia_graphite_dawn': { - 'test': 'media_unittests', - 'args': [ - '--test-launcher-bot-mode', - '--enable-features=SkiaGraphite', - '--skia-graphite-backend=dawn', - '--use-gpu-in-tests', - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.media_unittests.filter', - ], - }, - 'media_unittests_skia_graphite_metal': { - 'test': 'media_unittests', - 'args': [ - '--test-launcher-bot-mode', - '--enable-features=SkiaGraphite', - '--skia-graphite-backend=metal', - '--use-gpu-in-tests', - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.media_unittests.filter', - ], - }, - 'midi_unittests': {}, - 'mojo_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.mojo_unittests.filter', - ], - }, - 'native_theme_unittests': {}, - 'net_unittests': {}, - 'perfetto_unittests': {}, - 'printing_unittests': {}, - 'sandbox_unittests': {}, - 'services_unittests': {}, - 'shell_dialogs_unittests': {}, - 'skia_unittests': {}, - 'sql_unittests': {}, - 'storage_unittests': {}, - 'ui_base_unittests': { - 'args': [ - '--test-launcher-filter-file=testing/buildbot/filters/ios.ui_base_unittests.filter', - ], - }, - 'ui_touch_selection_unittests': {}, - 'ui_unittests': {}, - 'url_unittests': {}, - 'viz_unittests': { - 'args': [ - '--test-launcher-bot-mode', - '--test-launcher-filter-file=testing/buildbot/filters/ios.viz_unittests.filter', - '--use-gpu-in-tests', - ], - }, - 'wtf_unittests': {}, - 'zlib_unittests': {}, - }, - - 'ios_common_tests': { - 'absl_hardening_tests': {}, - 'boringssl_crypto_tests': {}, - 'boringssl_ssl_tests': {}, - 'crashpad_tests': {}, - 'crypto_unittests': {}, - 'google_apis_unittests': {}, - 'ios_components_unittests': {}, - 'ios_net_unittests': { - 'swarming': { - 'shards': 3, - }, - }, - 'ios_remoting_unittests': {}, - 'ios_testing_unittests': {}, - 'net_unittests': {}, - 'services_unittests': {}, - 'sql_unittests': {}, - 'url_unittests': {}, - }, - - 'ios_crash_xcuitests': { - 'ios_crash_xcuitests_module': {}, - }, - - 'ios_eg2_cq_tests': { - 'ios_chrome_integration_eg2tests_module': { - 'mixins': [ - 'ios_parallel_simulators', - ], - 'swarming': { - 'shards': 8, - }, - }, - 'ios_web_shell_eg2tests_module': {}, - }, - - 'ios_eg2_tests': { - 'ios_chrome_bookmarks_eg2tests_module': { - 'swarming': { - 'shards': 2, - }, - }, - 'ios_chrome_settings_eg2tests_module': { - 'mixins': [ - 'ios_parallel_simulators', - ], - 'swarming': { - 'shards': 4, - }, - }, - 'ios_chrome_signin_eg2tests_module': { - 'swarming': { - 'shards': 6, - }, - }, - 'ios_chrome_smoke_eg2tests_module': {}, - 'ios_chrome_ui_eg2tests_module': { - 'mixins': [ - 'ios_parallel_simulators', - ], - 'swarming': { - 'shards': 12, - }, - }, - 'ios_chrome_web_eg2tests_module': { - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'ios_remoting_fyi_unittests': { - 'ios_remoting_unittests': {}, - }, - - 'ios_screen_size_dependent_tests': { - 'base_unittests': {}, - 'components_unittests': {}, - 'gfx_unittests': {}, - 'ios_chrome_unittests': {}, - 'ios_web_inttests': {}, - 'ios_web_unittests': {}, - 'ios_web_view_inttests': {}, - 'ios_web_view_unittests': {}, - 'skia_unittests': {}, - 'ui_base_unittests': {}, - }, - - 'jni_zero_sample_apk_test_suite': { - 'jni_zero_sample_apk_test': {}, - }, - - 'js_code_coverage_browser_tests_suite': { - 'js_code_coverage_browser_tests': { - 'test': 'browser_tests', - 'swarming': { - 'shards': 16, - }, - }, - }, - - 'leak_detection_isolated_scripts': { - 'memory.leak_detection': { - 'test': 'performance_test_suite', - 'args': [ - '--pageset-repeat=1', - '--test-shard-map-filename=linux_leak_detection_shard_map.json', - '--upload-results', - '--output-format=histograms', - '--browser=release', - '--xvfb', - ], - 'swarming': { - 'shards': 10, - 'expiration': 36000, - 'hard_timeout': 10800, - 'io_timeout': 3600, - }, - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - 'args': [ - '--smoke-test-mode', - ], - }, - }, - }, - - 'linux_cfm_gtests': { - 'chromeos_unittests': {}, - 'unit_tests': {}, - }, - - 'linux_chromeos_lacros_gtests': { - 'chromeos_unittests': {}, - }, - - 'linux_chromeos_oobe_specific_tests': { - 'oobe_only_browser_tests': { - 'test': 'browser_tests', - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter', - ], - 'swarming': { - 'shards': 20, - }, - 'experiment_percentage': 100, - }, - }, - - 'linux_chromeos_specific_gtests': { - 'ash_components_unittests': {}, - 'ash_crosapi_tests': { - 'ci_only': True, - }, - 'ash_unittests': { - 'swarming': { - 'shards': 5, - }, - }, - 'ash_webui_unittests': {}, - 'aura_unittests': {}, - 'chromeos_components_unittests': {}, - 'exo_unittests': {}, - 'gl_unittests_ozone': {}, - 'keyboard_unittests': {}, - 'ozone_gl_unittests': { - 'args': [ - '--ozone-platform=headless', - ], - }, - 'ozone_unittests': {}, - 'ozone_x11_unittests': {}, - 'shell_encryption_unittests': {}, - 'ui_chromeos_unittests': {}, - 'usage_time_limit_unittests': { - 'experiment_percentage': 100, - }, - 'wayland_client_perftests': {}, - 'wayland_client_tests': {}, - }, - - 'linux_flavor_specific_chromium_gtests': { - 'sandbox_linux_unittests': {}, - }, - - 'linux_lacros_chrome_gtests': { - 'browser_tests': { - 'swarming': { - 'shards': 33, - }, - }, - 'interactive_ui_tests': { - 'swarming': { - 'shards': 6, - }, - }, - 'lacros_chrome_browsertests': { - 'swarming': { - 'shards': 6, - }, - }, - }, - - 'linux_specific_chromium_isolated_scripts': { - 'not_site_per_process_blink_web_tests': { - 'test': 'blink_web_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=disable-site-isolation-trials', - '--num-retries=3', - ], - 'swarming': { - 'shards': 8, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'not_site_per_process_blink_wpt_tests': { - 'test': 'blink_wpt_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=disable-site-isolation-trials', - '--num-retries=3', - ], - 'swarming': { - 'shards': 10, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'not_site_per_process_headless_shell_wpt_tests': { - 'test': 'headless_shell_wpt', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--flag-specific=disable-site-isolation-trials', - '--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - '--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/headless_shell.filter', - ], - 'swarming': { - 'shards': 1, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'webdriver_wpt_tests': { - 'test': 'chrome_wpt_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--test-type=wdspec', - ], - 'swarming': { - 'shards': 2, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'linux_specific_xr_gtests': { - 'xr_browser_tests': {}, - }, - - 'mac_lsan_fyi_gtests': { - 'absl_hardening_tests': {}, - 'accessibility_unittests': {}, - 'app_shell_unittests': {}, - 'base_unittests': {}, - 'blink_heap_unittests': {}, - 'blink_platform_unittests': { - 'mixins': [ - 'skia_gold_test', - ], - }, - 'blink_unittests': {}, - 'cc_unittests': {}, - 'components_unittests': {}, - 'content_unittests': {}, - 'crashpad_tests': {}, - 'cronet_unittests': {}, - 'device_unittests': {}, - 'net_unittests': {}, - }, - - 'mac_specific_chromium_gtests': { - 'power_sampler_unittests': {}, - 'sandbox_unittests': {}, - 'updater_tests': {}, - 'xr_browser_tests': {}, - }, - - 'mac_specific_isolated_scripts': { - 'mac_signing_tests': {}, - }, - - 'minidump_uploader_tests': { - 'minidump_uploader_test': {}, - }, - - 'model_validation_tests_light_suite': { - 'model_validation_tests_light': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--out_dir=.', - ], - 'linux_args': [ - '--use-xvfb', - ], - }, - }, - - 'model_validation_tests_suite': { - 'model_validation_tests': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--out_dir=.', - ], - 'linux_args': [ - '--chromedriver', - 'chromedriver', - '--binary', - 'chrome', - '--use-xvfb', - ], - 'mac_args': [ - '--chromedriver', - 'chromedriver', - '--binary', - 'Google Chrome.app/Contents/MacOS/Google Chrome', - ], - 'win_args': [ - '--chromedriver', - 'chromedriver.exe', - '--binary', - 'Chrome.exe', - ], - }, - }, - - 'mojo_python_unittests_isolated_scripts': { - 'mojo_python_unittests': { - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'monochrome_public_apk_checker_isolated_script': { - 'monochrome_public_apk_checker': { - 'remove_mixins': [ - 'bullhead', - 'marshmallow', - 'oreo_fleet', - 'pie_fleet', - 'walleye', - ], - 'swarming': { - 'dimensions': { - 'os': 'Ubuntu-22.04', - 'cpu': 'x86-64', - 'device_os': None, - 'device_os_flavor': None, - 'device_playstore_version': None, - 'device_type': None, - }, - }, - }, - }, - - 'network_service_fyi_gtests': { - 'network_service_web_request_proxy_browser_tests': { - 'test': 'browser_tests', - 'args': [ - '--enable-features=ForceWebRequestProxyForTest', - ], - 'swarming': { - 'shards': 15, - }, - }, - }, - - 'non_android_and_cast_and_chromeos_chromium_gtests': { - 'cronet_tests': {}, - 'cronet_unittests': {}, - 'headless_browsertests': {}, - 'headless_unittests': {}, - }, - - 'non_android_chromium_gtests': { - 'accessibility_unittests': {}, - 'app_shell_unittests': {}, - 'blink_fuzzer_unittests': {}, - 'browser_tests': { - 'swarming': { - 'shards': 10, - }, - }, - 'chrome_app_unittests': {}, - 'chromedriver_unittests': {}, - 'extensions_browsertests': {}, - 'extensions_unittests': {}, - 'filesystem_service_unittests': {}, - 'interactive_ui_tests': { - 'swarming': { - 'shards': 3, - }, - }, - 'message_center_unittests': {}, - 'nacl_loader_unittests': {}, - 'native_theme_unittests': {}, - 'pdf_unittests': {}, - 'ppapi_unittests': {}, - 'printing_unittests': {}, - 'remoting_unittests': {}, - 'snapshot_unittests': {}, - 'sync_integration_tests': { - 'swarming': { - 'shards': 3, - }, - }, - 'ui_unittests': {}, - 'views_unittests': {}, - }, - - 'non_android_chromium_gtests_no_nacl': { - 'accessibility_unittests': {}, - 'app_shell_unittests': {}, - 'blink_fuzzer_unittests': {}, - 'browser_tests': { - 'swarming': { - 'shards': 10, - }, - }, - 'chrome_app_unittests': {}, - 'chromedriver_unittests': {}, - 'extensions_browsertests': {}, - 'extensions_unittests': {}, - 'filesystem_service_unittests': {}, - 'interactive_ui_tests': { - 'swarming': { - 'shards': 3, - }, - }, - 'message_center_unittests': {}, - 'native_theme_unittests': {}, - 'pdf_unittests': {}, - 'printing_unittests': {}, - 'remoting_unittests': {}, - 'snapshot_unittests': {}, - 'sync_integration_tests': { - 'swarming': { - 'shards': 3, - }, - }, - 'ui_unittests': {}, - 'views_unittests': {}, - }, - - 'non_android_chromium_gtests_skia_gold': { - 'views_examples_unittests': { - 'mixins': [ - 'skia_gold_test', - ], - }, - }, - - 'ondevice_quality_tests_suite': { - 'ondevice_quality_tests': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'linux_args': [ - '--chromedriver', - 'chromedriver', - '--binary', - 'chrome', - '--no-xvfb', - ], - 'mac_args': [ - '--chromedriver', - 'chromedriver', - '--binary', - 'Google Chrome.app/Contents/MacOS/Google Chrome', - ], - 'win_args': [ - '--chromedriver', - 'chromedriver.exe', - '--binary', - 'Chrome.exe', - ], - 'experiment_percentage': 100, - }, - }, - - 'ondevice_stability_tests_suite': { - 'ondevice_stability_tests': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'linux_args': [ - '--chromedriver', - 'chromedriver', - '--binary', - 'chrome', - '--no-xvfb', - ], - 'mac_args': [ - '--chromedriver', - 'chromedriver', - '--binary', - 'Google Chrome.app/Contents/MacOS/Google Chrome', - ], - 'win_args': [ - '--chromedriver', - 'chromedriver.exe', - '--binary', - 'Chrome.exe', - ], - }, - 'ondevice_stability_tests_light': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'linux_args': [ - '--no-xvfb', - ], - }, - }, - - 'optimization_guide_android_gtests': { - 'optimization_guide_components_unittests': { - 'test': 'components_unittests', - 'args': [ - '--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*', - ], - }, - }, - - 'optimization_guide_cros_gtests': { - 'optimization_guide_browser_tests': { - 'test': 'browser_tests', - 'args': [ - '--gtest_filter=*OptimizationGuide*:*PageContentAnnotations*', - ], - }, - 'optimization_guide_components_unittests': { - 'test': 'components_unittests', - 'args': [ - '--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*', - ], - }, - }, - - 'optimization_guide_gpu_gtests': { - 'optimization_guide_gpu_unittests': { - 'linux_args': [ - '-use-xvfb', - ], - }, - }, - - 'optimization_guide_nogpu_gtests': { - 'chrome_ml_unittests': { - 'linux_args': [ - '--use-xvfb', - ], - }, - 'optimization_guide_browser_tests': { - 'test': 'browser_tests', - 'args': [ - '--gtest_filter=*OptimizationGuide*:*PageContentAnnotations*', - ], - 'linux_args': [ - '--use-xvfb', - ], - }, - 'optimization_guide_components_unittests': { - 'test': 'components_unittests', - 'args': [ - '--gtest_filter=*OptimizationGuide*:*PageEntities*:*EntityAnnotator*', - ], - 'linux_args': [ - '--use-xvfb', - ], - }, - 'optimization_guide_unittests': { - 'linux_args': [ - '--use-xvfb', - ], - }, - }, - - 'perfetto_gtests': { - 'base_unittests': {}, - 'browser_tests': { - 'args': [ - '--gtest_filter=ChromeTracingDelegateBrowserTest.*', - ], - }, - 'content_browsertests': { - 'swarming': { - 'shards': 8, - }, - 'android_swarming': { - 'shards': 15, - }, - }, - 'perfetto_unittests': {}, - 'services_unittests': {}, - }, - - 'perfetto_gtests_android': { - 'android_browsertests': { - 'args': [ - '--gtest_filter=StartupMetricsTest.*', - ], - }, - 'base_unittests': {}, - 'content_browsertests': { - 'swarming': { - 'shards': 8, - }, - 'android_swarming': { - 'shards': 15, - }, - }, - 'perfetto_unittests': {}, - 'services_unittests': {}, - }, - - 'performance_smoke_test_isolated_scripts': { - 'performance_test_suite': { - 'args': [ - '--pageset-repeat=1', - '--test-shard-map-filename=smoke_test_benchmark_shard_map.json', - ], - 'swarming': { - 'shards': 2, - 'hard_timeout': 960, - }, - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - 'args': [ - '--smoke-test-mode', - ], - }, - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'pixel_browser_tests_gtests': { - 'pixel_browser_tests': { - 'test': 'browser_tests', - 'mixins': [ - 'skia_gold_test', - ], - 'args': [ - '--browser-ui-tests-verify-pixels', - '--enable-pixel-output-in-tests', - '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter', - '--test-launcher-jobs=1', - ], - 'swarming': { - 'shards': 3, - }, - }, - 'pixel_interactive_ui_tests': { - 'test': 'interactive_ui_tests', - 'mixins': [ - 'skia_gold_test', - ], - 'args': [ - '--browser-ui-tests-verify-pixels', - '--enable-pixel-output-in-tests', - '--test-launcher-filter-file=../../testing/buildbot/filters/pixel_tests.filter', - ], - }, - }, - - 'pixel_experimental_browser_tests_gtests': { - 'pixel_experimental_browser_tests': { - 'test': 'browser_tests', - 'mixins': [ - 'skia_gold_test', - ], - 'args': [ - '--browser-ui-tests-verify-pixels', - '--enable-pixel-output-in-tests', - '--test-launcher-filter-file=../../testing/buildbot/filters/linux-chromeos.browser_tests.pixel_tests.filter', - ], - 'experiment_percentage': 100, - }, - }, - - 'private_code_failure_test_isolated_scripts': { - 'private_code_failure_test': {}, - }, - - 'pytype_tests': { - 'blink_pytype': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - }, - 'fuchsia_pytype': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - }, - 'gold_common_pytype': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - }, - 'gpu_pytype': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - }, - 'testing_pytype': { - 'mixins': [ - 'has_native_resultdb_integration', - ], - }, - }, - - 'rust_common_gtests': { - 'base_unittests': {}, - 'mojo_rust_integration_unittests': {}, - 'mojo_rust_unittests': {}, - 'rust_gtest_interop_unittests': {}, - 'test_cpp_including_rust_unittests': {}, - 'test_serde_json_lenient': {}, - }, - - 'rust_native_tests': { - 'build_rust_tests': {}, - }, - - 'site_isolation_android_fyi_gtests': { - 'site_per_process_android_browsertests': { - 'test': 'android_browsertests', - 'args': [ - '--site-per-process', - ], - 'swarming': { - 'shards': 1, - }, - }, - 'site_per_process_chrome_public_test_apk': { - 'test': 'chrome_public_test_apk', - 'mixins': [ - 'skia_gold_test', - 'has_native_resultdb_integration', - ], - 'args': [ - '--site-per-process', - ], - 'swarming': { - 'shards': 20, - }, - }, - 'site_per_process_chrome_public_unit_test_apk': { - 'test': 'chrome_public_unit_test_apk', - 'mixins': [ - 'skia_gold_test', - ], - 'args': [ - '--site-per-process', - ], - }, - 'site_per_process_components_browsertests': { - 'test': 'components_browsertests', - 'args': [ - '--site-per-process', - ], - }, - 'site_per_process_components_unittests': { - 'test': 'components_unittests', - 'args': [ - '--site-per-process', - ], - 'swarming': { - 'shards': 5, - }, - }, - 'site_per_process_content_browsertests': { - 'test': 'content_browsertests', - 'args': [ - '--site-per-process', - '--test-launcher-filter-file=../../testing/buildbot/filters/site_isolation_android.content_browsertests.filter', - ], - 'swarming': { - 'shards': 10, - }, - }, - 'site_per_process_content_shell_test_apk': { - 'test': 'content_shell_test_apk', - 'args': [ - '--site-per-process', - ], - 'swarming': { - 'shards': 3, - }, - }, - 'site_per_process_content_unittests': { - 'test': 'content_unittests', - 'args': [ - '--site-per-process', - ], - }, - 'site_per_process_unit_tests': { - 'test': 'unit_tests', - 'args': [ - '--site-per-process', - ], - 'swarming': { - 'shards': 10, - }, - }, - }, - - 'swangle_gtests': { - 'angle_deqp_egl_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_gles2_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_gles31_rotate180_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_gles31_rotate270_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_gles31_rotate90_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_gles31_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'swarming': { - 'shards': 10, - }, - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_gles3_rotate180_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_gles3_rotate270_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_gles3_rotate90_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_gles3_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'swarming': { - 'shards': 4, - }, - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_khr_gles2_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_khr_gles31_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_deqp_khr_gles3_tests': { - 'args': [ - '--use-angle=swiftshader', - ], - 'use_isolated_scripts_api': True, - }, - 'angle_end2end_tests': { - 'args': [ - '--gtest_filter=*Vulkan_SwiftShader*', - ], - 'swarming': { - 'shards': 2, - }, - 'use_isolated_scripts_api': True, - }, - }, - - 'system_webview_shell_instrumentation_tests': { - 'system_webview_shell_layout_test_apk': {}, - }, - - 'system_webview_wpt_suite': { - 'system_webview_wpt': { - 'results_handler': 'layout tests', - 'args': [ - '--no-wpt-internal', - ], - 'swarming': { - 'shards': 25, - 'expiration': 18000, - 'hard_timeout': 14400, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'telemetry_android_minidump_unittests_isolated_scripts': { - 'telemetry_chromium_minidump_unittests': { - 'test': 'telemetry_perf_unittests_android_chrome', - 'args': [ - 'BrowserMinidumpTest', - '--browser=android-chromium', - '-v', - '--passthrough', - '--retry-limit=2', - ], - 'resultdb': { - 'enable': True, - }, - }, - 'telemetry_monochrome_minidump_unittests': { - 'test': 'telemetry_perf_unittests_android_monochrome', - 'args': [ - 'BrowserMinidumpTest', - '--browser=android-chromium-monochrome', - '-v', - '--passthrough', - '--retry-limit=2', - ], - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'telemetry_desktop_minidump_unittests_isolated_scripts': { - 'telemetry_desktop_minidump_unittests': { - 'test': 'telemetry_perf_unittests', - 'args': [ - 'BrowserMinidumpTest', - '-v', - '--passthrough', - '--retry-limit=2', - ], - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'telemetry_perf_unittests_isolated_scripts': { - 'telemetry_perf_unittests': { - 'args': [ - '--extra-browser-args=--enable-crashpad', - ], - 'swarming': { - 'shards': 12, - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'telemetry_perf_unittests_isolated_scripts_android': { - 'telemetry_perf_unittests_android_chrome': { - 'args': [ - '--extra-browser-args=--enable-crashpad', - ], - 'swarming': { - 'shards': 12, - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'telemetry_perf_unittests_isolated_scripts_xvfb': { - 'telemetry_perf_unittests': { - 'args': [ - '--extra-browser-args=--enable-crashpad', - '--xvfb', - ], - 'swarming': { - 'shards': 12, - 'idempotent': False, - }, - 'resultdb': { - 'enable': True, - }, - }, - }, - - 'test_traffic_annotation_auditor_script': { - 'test_traffic_annotation_auditor': { - 'script': 'test_traffic_annotation_auditor.py', - }, - }, - - 'updater_gtests_linux': { - 'updater_tests': { - 'mixins': [ - 'updater-default-pool', - ], - }, - }, - - 'updater_gtests_mac': { - 'updater_tests': { - 'mixins': [ - 'updater-default-pool', - ], - }, - 'updater_tests_system': { - 'mixins': [ - 'updater-mac-pool', - ], - }, - }, - - 'updater_gtests_win': { - 'updater_tests': { - 'mixins': [ - 'integrity_high', - 'updater-default-pool', - ], - }, - 'updater_tests_system': { - 'mixins': [ - 'integrity_high', - 'updater-default-pool', - ], - }, - }, - - 'updater_gtests_win_uac': { - 'updater_tests_system': { - 'mixins': [ - 'integrity_high', - 'updater-win-uac-pool', - ], - }, - 'updater_tests_win_uac': { - 'mixins': [ - 'updater-win-uac-pool', - ], - }, - }, - - 'upload_perfetto': { - 'upload_trace_processor': {}, - }, - - 'vr_android_specific_chromium_tests': { - 'chrome_public_test_vr_apk': { - 'swarming': { - 'shards': 2, - }, - }, - 'vr_android_unittests': {}, - }, - - 'vr_platform_specific_chromium_gtests': { - 'vr_common_unittests': {}, - }, - - 'vulkan_swiftshader_isolated_scripts': { - 'vulkan_swiftshader_blink_web_tests': { - 'test': 'blink_web_tests', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--num-retries=3', - '--skipped=always', - '--flag-specific=skia-vulkan-swiftshader', - ], - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'webrtc_chromium_gtests': { - 'browser_tests': { - 'args': [ - '--gtest_filter=WebRtcStatsPerfBrowserTest.*:WebRtcVideoDisplayPerfBrowserTests*:WebRtcVideoQualityBrowserTests*:WebRtcVideoHighBitrateBrowserTest*:WebRtcWebcamBrowserTests*', - '--run-manual', - '--ui-test-action-max-timeout=300000', - '--test-launcher-timeout=350000', - '--test-launcher-jobs=1', - '--test-launcher-bot-mode', - '--test-launcher-print-test-stdio=always', - ], - }, - 'browser_tests_functional': { - 'test': 'browser_tests', - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/webrtc_functional.browser_tests.filter', - '--run-manual', - '--test-launcher-jobs=1', - ], - }, - 'content_browsertests': { - 'args': [ - '--gtest_filter=WebRtc*', - ], - }, - 'content_browsertests_sequential': { - 'test': 'content_browsertests', - 'args': [ - '--gtest_filter=UsingRealWebcam*', - '--run-manual', - '--test-launcher-jobs=1', - ], - }, - 'content_browsertests_stress': { - 'test': 'content_browsertests', - 'args': [ - '--gtest_filter=WebRtc*MANUAL*:-UsingRealWebcam*', - '--run-manual', - '--ui-test-action-max-timeout=110000', - '--test-launcher-timeout=120000', - ], - }, - 'content_unittests': { - 'args': [ - '--test-launcher-filter-file=../../testing/buildbot/filters/webrtc.content_unittests.filter', - ], - }, - 'remoting_unittests': { - 'args': [ - '--gtest_filter=Webrtc*', - ], - }, - }, - - 'webrtc_chromium_simple_gtests': { - 'content_browsertests': { - 'args': [ - '--gtest_filter=WebRtc*', - ], - }, - 'content_browsertests_sequential': { - 'test': 'content_browsertests', - 'args': [ - '--gtest_filter=UsingRealWebcam*', - '--run-manual', - '--test-launcher-jobs=1', - ], - }, - }, - - 'webrtc_chromium_wpt_tests': { - 'blink_wpt_tests': { - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - 'blink_tests_write_run_histories', - ], - 'args': [ - '--num-retries=3', - '-t', - 'Release', - 'external/wpt/webrtc', - 'external/wpt/webrtc-encoded-transform', - 'external/wpt/webrtc-extensions', - 'external/wpt/webrtc-priority', - 'external/wpt/webrtc-stats', - 'external/wpt/webrtc-svc', - ], - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - 'headless_shell_wpt_tests': { - 'test': 'headless_shell_wpt', - 'results_handler': 'layout tests', - 'mixins': [ - 'has_native_resultdb_integration', - ], - 'args': [ - '--test-type', - 'testharness', - 'reftest', - 'crashtest', - 'print-reftest', - '--inverted-test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/chrome.filter', - '--test-launcher-filter-file=../../third_party/blink/web_tests/TestLists/headless_shell.filter', - '-t', - 'Release', - 'external/wpt/webrtc', - 'external/wpt/webrtc-encoded-transform', - 'external/wpt/webrtc-extensions', - 'external/wpt/webrtc-priority', - 'external/wpt/webrtc-stats', - 'external/wpt/webrtc-svc', - ], - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'webview_64_cts_tests_gtest': { - 'webview_64_cts_tests': { - 'mixins': [ - 'webview_cts_archive', - ], - 'args': [ - '--store-tombstones', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'webview_bot_instrumentation_test_apk_bfcache_mutations_gtest': { - 'webview_instrumentation_test_apk_bfcache_mutations': { - 'test': 'webview_instrumentation_test_apk', - 'args': [ - '--use-apk-under-test-flags-file', - '--enable-features=WebViewBackForwardCache', - ], - 'swarming': { - 'shards': 12, - }, - }, - }, - - 'webview_bot_instrumentation_test_apk_gtest': { - 'webview_instrumentation_test_apk': { - 'args': [ - '--use-apk-under-test-flags-file', - ], - 'swarming': { - 'shards': 12, - }, - }, - }, - - 'webview_bot_instrumentation_test_apk_mutations_gtest': { - 'webview_instrumentation_test_apk_mutations': { - 'test': 'webview_instrumentation_test_apk', - 'args': [ - '--use-apk-under-test-flags-file', - '--webview-mutations-enabled', - ], - 'swarming': { - 'shards': 12, - }, - }, - }, - - 'webview_bot_instrumentation_test_apk_no_field_trial_gtest': { - 'webview_instrumentation_test_apk_no_field_trial': { - 'test': 'webview_instrumentation_test_apk', - 'args': [ - '--disable-field-trial-config', - '--use-apk-under-test-flags-file', - ], - 'swarming': { - 'shards': 12, - }, - }, - }, - - 'webview_bot_unittests_gtest': { - 'android_webview_unittests': {}, - }, - - 'webview_cts_tests_bfcache_mutations_gtest': { - 'webview_cts_tests_bfcache_mutations': { - 'test': 'webview_cts_tests', - 'mixins': [ - 'webview_cts_archive', - ], - 'args': [ - '--use-apk-under-test-flags-file', - '--enable-features=WebViewBackForwardCache', - '--store-tombstones', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'webview_cts_tests_gtest': { - 'webview_cts_tests': { - 'mixins': [ - 'webview_cts_archive', - ], - 'args': [ - '--store-tombstones', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'webview_cts_tests_gtest_no_field_trial': { - 'webview_cts_tests_no_field_trial': { - 'test': 'webview_cts_tests', - 'mixins': [ - 'webview_cts_archive', - ], - 'args': [ - '--disable-field-trial-config', - '--store-tombstones', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'webview_instrumentation_test_apk_single_process_mode_gtests': { - 'webview_instrumentation_test_apk_single_process_mode': { - 'test': 'webview_instrumentation_test_apk', - 'args': [ - '--webview-process-mode=single', - ], - 'swarming': { - 'shards': 3, - }, - }, - }, - - 'webview_trichrome_64_cts_field_trial_tests': { - 'webview_trichrome_64_cts_tests': { - 'mixins': [ - 'webview_cts_archive', - ], - 'args': [ - '--store-data-dependencies-in-temp', - '--store-tombstones', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'webview_trichrome_64_cts_hostside_tests_suite': { - 'webview_trichrome_64_cts_hostside_tests': { - 'mixins': [ - 'webview_cts_archive', - ], - }, - }, - - 'webview_trichrome_64_cts_tests_no_field_trial_suite': { - 'webview_trichrome_64_cts_tests_no_field_trial': { - 'test': 'webview_trichrome_64_cts_tests', - 'mixins': [ - 'webview_cts_archive', - ], - 'args': [ - '--disable-field-trial-config', - '--store-tombstones', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'webview_trichrome_64_cts_tests_suite': { - 'webview_trichrome_64_cts_tests': { - 'mixins': [ - 'webview_cts_archive', - ], - 'args': [ - '--store-tombstones', - ], - 'swarming': { - 'shards': 2, - }, - }, - }, - - 'webview_trichrome_cts_tests_suite': { - 'webview_trichrome_cts_tests': { - 'mixins': [ - 'webview_cts_archive', - ], - 'args': [ - '--store-tombstones', - ], - }, - }, - - 'webview_ui_instrumentation_tests': { - 'webview_ui_test_app_test_apk': {}, - }, - - 'webview_ui_instrumentation_tests_no_field_trial': { - 'webview_ui_test_app_test_apk_no_field_trial': { - 'test': 'webview_ui_test_app_test_apk', - 'args': [ - '--disable-field-trial-config', - ], - }, - }, - - 'win_specific_chromium_gtests': { - 'chrome_elf_unittests': {}, - 'courgette_unittests': {}, - 'delayloads_unittests': {}, - 'elevation_service_unittests': {}, - 'gcp_unittests': {}, - 'install_static_unittests': {}, - 'installer_util_unittests': { - 'swarming': { - 'dimensions': { - 'integrity': 'high', - }, - }, - }, - 'notification_helper_unittests': {}, - 'sbox_integration_tests': { - 'swarming': { - 'dimensions': { - 'integrity': 'high', - }, - }, - }, - 'sbox_unittests': {}, - 'sbox_validation_tests': {}, - 'setup_unittests': { - 'swarming': { - 'dimensions': { - 'integrity': 'high', - }, - }, - }, - 'updater_tests': {}, - 'updater_tests_system': {}, - 'zucchini_unittests': {}, - }, - - 'win_specific_isolated_scripts': { - 'mini_installer_tests': { - 'swarming': { - 'dimensions': { - 'integrity': 'high', - }, - }, - }, - 'polymer_tools_python_unittests': { - 'experiment_percentage': 0, - }, - }, - - 'win_specific_xr_perf_tests': { - 'xr.webxr.static': { - 'test': 'vr_perf_tests', - 'args': [ - '--benchmarks=xr.webxr.static', - '-v', - '--upload-results', - '--output-format=histograms', - '--browser=release_x64', - ], - 'merge': { - 'script': '//tools/perf/process_perf_results.py', - }, - 'experiment_percentage': 100, - }, - }, - - 'wpt_tests_ios_suite': { - 'wpt_tests_ios': { - 'test': 'chrome_ios_wpt', - 'results_handler': 'layout tests', - 'args': [ - '--no-wpt-internal', - ], - 'swarming': { - 'shards': 36, - 'expiration': 18000, - 'hard_timeout': 14400, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - 'experiment_percentage': 100, - }, - }, - - 'wpt_web_tests_android': { - 'android_blink_wpt_tests': { - 'test': 'chrome_public_wpt', - 'results_handler': 'layout tests', - 'swarming': { - 'shards': 4, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - - 'wpt_web_tests_webview': { - 'webview_blink_wpt_tests': { - 'test': 'trichrome_webview_wpt_64', - 'results_handler': 'layout tests', - 'swarming': { - 'shards': 4, - }, - 'merge': { - 'script': '//third_party/blink/tools/merge_web_test_results.py', - 'args': [ - '--verbose', - ], - }, - }, - }, - }, - - 'compound_suites': { - - 'android_10_rel_gtests': [ - 'android_ar_gtests', - 'android_trichrome_smoke_tests', - 'vr_android_specific_chromium_tests', - ], - - 'android_12_dbg_emulator_gtests': [ - 'android_trichrome_smoke_tests', - ], - - 'android_cronet_clang_coverage_gtests': [ - 'cronet_clang_coverage_additional_gtests', - 'cronet_gtests', - ], - - 'android_oreo_emulator_gtests': [ - 'android_emulator_specific_chrome_public_tests', - 'android_emulator_specific_network_enabled_content_browsertests', - 'android_monochrome_smoke_tests', - 'android_smoke_tests', - 'android_specific_chromium_gtests', - 'android_wpr_record_replay_tests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'linux_flavor_specific_chromium_gtests', - 'system_webview_shell_instrumentation_tests', - 'webview_cts_tests_gtest', - 'webview_instrumentation_test_apk_single_process_mode_gtests', - 'webview_ui_instrumentation_tests', - ], - - 'android_pie_coverage_instrumentation_tests': [ - 'android_smoke_tests', - 'android_specific_coverage_java_tests', - 'chrome_public_tests', - 'vr_android_specific_chromium_tests', - 'webview_ui_instrumentation_tests', - ], - - 'android_pie_rel_emulator_gtests': [ - 'android_emulator_specific_chrome_public_tests', - 'android_monochrome_smoke_tests', - 'android_smoke_tests', - 'android_specific_chromium_gtests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'linux_flavor_specific_chromium_gtests', - 'system_webview_shell_instrumentation_tests', - 'webview_cts_tests_gtest', - 'webview_instrumentation_test_apk_single_process_mode_gtests', - 'webview_ui_instrumentation_tests', - ], - - 'android_pie_rel_gtests': [ - 'android_monochrome_smoke_tests', - 'android_pie_rel_reduced_capacity_gtests', - 'android_smoke_tests', - 'chrome_public_tests', - 'system_webview_shell_instrumentation_tests', - 'webview_64_cts_tests_gtest', - 'webview_instrumentation_test_apk_single_process_mode_gtests', - 'webview_ui_instrumentation_tests', - ], - - 'bfcache_android_gtests': [ - 'bfcache_android_specific_gtests', - 'bfcache_generic_gtests', - 'webview_bot_instrumentation_test_apk_bfcache_mutations_gtest', - 'webview_cts_tests_bfcache_mutations_gtest', - ], - - 'bfcache_linux_gtests': [ - 'bfcache_generic_gtests', - 'bfcache_linux_specific_gtests', - ], - - 'chrome_linux_isolated_script_tests': [ - 'chrome_isolated_script_tests', - 'chrome_private_code_test_isolated_scripts', - ], - - 'chromeos_vm_gtests': [ - 'chromeos_integration_tests_suite', - 'chromeos_system_friendly_gtests', - 'chromeos_vaapi_fakelib_gtests', - ], - - 'chromeos_vm_tast': [ - 'chromeos_browser_all_tast_tests', - 'chromeos_browser_criticalstaging_tast_tests', - 'chromeos_browser_disabled_tast_tests', - 'chromeos_browser_integration_tests', - ], - - 'chromium_android_gtests': [ - 'android_smoke_tests', - 'android_specific_chromium_gtests', - 'chrome_public_tests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'linux_flavor_specific_chromium_gtests', - 'vr_android_specific_chromium_tests', - 'vr_platform_specific_chromium_gtests', - 'webview_instrumentation_test_apk_single_process_mode_gtests', - ], - - 'chromium_dbg_isolated_scripts': [ - 'desktop_chromium_isolated_scripts', - 'performance_smoke_test_isolated_scripts', - 'telemetry_perf_unittests_isolated_scripts', - ], - - 'chromium_linux_and_gl_and_vulkan_gtests': [ - 'aura_gtests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_linux_and_chromeos_only', - 'chromium_gtests_for_linux_and_mac_only', - 'chromium_gtests_for_linux_only', - 'chromium_gtests_for_win_and_linux_only', - 'gl_gtests_passthrough', - 'gpu_fyi_vulkan_swiftshader_gtests', - 'linux_flavor_specific_chromium_gtests', - 'linux_specific_xr_gtests', - 'non_android_and_cast_and_chromeos_chromium_gtests', - 'non_android_chromium_gtests_no_nacl', - 'vr_platform_specific_chromium_gtests', - ], - - 'chromium_linux_and_gl_gtests': [ - 'aura_gtests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_linux_and_chromeos_only', - 'chromium_gtests_for_linux_and_mac_only', - 'chromium_gtests_for_linux_only', - 'chromium_gtests_for_win_and_linux_only', - 'gl_gtests_passthrough', - 'linux_flavor_specific_chromium_gtests', - 'linux_specific_xr_gtests', - 'non_android_and_cast_and_chromeos_chromium_gtests', - 'non_android_chromium_gtests_no_nacl', - 'vr_platform_specific_chromium_gtests', - ], - - 'chromium_linux_blink_rel_isolated_scripts': [ - 'chromium_web_tests_high_dpi_isolated_scripts', - 'chromium_webkit_isolated_scripts', - 'linux_specific_chromium_isolated_scripts', - 'vulkan_swiftshader_isolated_scripts', - ], - - 'chromium_linux_gtests': [ - 'aura_gtests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_linux_and_chromeos_only', - 'chromium_gtests_for_linux_and_mac_only', - 'chromium_gtests_for_linux_only', - 'chromium_gtests_for_win_and_linux_only', - 'linux_flavor_specific_chromium_gtests', - 'linux_specific_xr_gtests', - 'non_android_and_cast_and_chromeos_chromium_gtests', - 'non_android_chromium_gtests_no_nacl', - 'vr_platform_specific_chromium_gtests', - ], - - 'chromium_linux_rel_isolated_scripts': [ - 'chromedriver_py_tests_isolated_scripts', - 'chromium_web_tests_high_dpi_isolated_scripts', - 'desktop_chromium_isolated_scripts', - 'linux_specific_chromium_isolated_scripts', - 'mojo_python_unittests_isolated_scripts', - 'pytype_tests', - 'telemetry_perf_unittests_isolated_scripts', - 'vulkan_swiftshader_isolated_scripts', - ], - - 'chromium_linux_rel_isolated_scripts_code_coverage': [ - 'chromedriver_py_tests_isolated_scripts', - 'chromium_web_tests_high_dpi_isolated_scripts', - 'desktop_chromium_isolated_scripts', - 'gpu_dawn_webgpu_blink_web_tests', - 'linux_specific_chromium_isolated_scripts', - 'mojo_python_unittests_isolated_scripts', - 'pytype_tests', - 'telemetry_perf_unittests_isolated_scripts_xvfb', - 'vulkan_swiftshader_isolated_scripts', - ], - - 'chromium_linux_rel_isolated_scripts_once': [ - 'chromedriver_py_tests_isolated_scripts', - 'chromium_web_tests_brfetch_isolated_scripts', - 'chromium_web_tests_high_dpi_isolated_scripts', - 'desktop_chromium_isolated_scripts', - 'desktop_once_isolated_scripts', - 'linux_specific_chromium_isolated_scripts', - 'mojo_python_unittests_isolated_scripts', - 'pytype_tests', - 'telemetry_perf_unittests_isolated_scripts', - 'vulkan_swiftshader_isolated_scripts', - ], - - 'chromium_mac_gtests': [ - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_linux_and_mac_only', - 'mac_specific_chromium_gtests', - 'non_android_and_cast_and_chromeos_chromium_gtests', - 'non_android_chromium_gtests_no_nacl', - ], - - 'chromium_mac_gtests_no_nacl': [ - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_linux_and_mac_only', - 'mac_specific_chromium_gtests', - 'non_android_and_cast_and_chromeos_chromium_gtests', - 'non_android_chromium_gtests_no_nacl', - ], - - 'chromium_mac_osxbeta_rel_isolated_scripts': [ - 'chromedriver_py_tests_isolated_scripts', - 'components_perftests_isolated_scripts', - 'desktop_chromium_mac_osxbeta_scripts', - 'mac_specific_isolated_scripts', - 'mojo_python_unittests_isolated_scripts', - 'telemetry_perf_unittests_isolated_scripts', - ], - - 'chromium_mac_rel_isolated_scripts': [ - 'chromedriver_py_tests_isolated_scripts', - 'components_perftests_isolated_scripts', - 'desktop_chromium_isolated_scripts', - 'mac_specific_isolated_scripts', - 'mojo_python_unittests_isolated_scripts', - 'telemetry_perf_unittests_isolated_scripts', - ], - - 'chromium_mac_rel_isolated_scripts_and_sizes': [ - 'chrome_sizes_suite', - 'chromedriver_py_tests_isolated_scripts', - 'components_perftests_isolated_scripts', - 'desktop_chromium_isolated_scripts', - 'mac_specific_isolated_scripts', - 'mojo_python_unittests_isolated_scripts', - 'telemetry_perf_unittests_isolated_scripts', - ], - - 'chromium_mac_rel_isolated_scripts_code_coverage': [ - ], - - 'chromium_mac_rel_isolated_scripts_once': [ - 'chromedriver_py_tests_isolated_scripts', - 'components_perftests_isolated_scripts', - 'desktop_chromium_isolated_scripts', - 'desktop_once_isolated_scripts', - 'mac_specific_isolated_scripts', - 'mojo_python_unittests_isolated_scripts', - 'telemetry_perf_unittests_isolated_scripts', - ], - - 'chromium_multiscreen_gtests_fyi': [ - 'chromium_multiscreen_gtests', - ], - - 'chromium_win10_gtests': [ - 'aura_gtests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_win_and_linux_only', - 'fieldtrial_browser_tests', - 'non_android_and_cast_and_chromeos_chromium_gtests', - 'non_android_chromium_gtests_no_nacl', - 'non_android_chromium_gtests_skia_gold', - 'pixel_browser_tests_gtests', - 'vr_platform_specific_chromium_gtests', - 'win_specific_chromium_gtests', - ], - - 'chromium_win_dbg_isolated_scripts': [ - 'chromedriver_py_tests_isolated_scripts', - 'components_perftests_isolated_scripts', - 'desktop_chromium_isolated_scripts', - 'performance_smoke_test_isolated_scripts', - 'telemetry_perf_unittests_isolated_scripts', - ], - - 'chromium_win_gtests': [ - 'aura_gtests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_win_and_linux_only', - 'non_android_and_cast_and_chromeos_chromium_gtests', - 'non_android_chromium_gtests_no_nacl', - 'vr_platform_specific_chromium_gtests', - 'win_specific_chromium_gtests', - ], - - 'chromium_win_rel_isolated_scripts': [ - 'chromedriver_py_tests_isolated_scripts', - 'components_perftests_isolated_scripts', - 'desktop_chromium_isolated_scripts', - 'mojo_python_unittests_isolated_scripts', - 'telemetry_desktop_minidump_unittests_isolated_scripts', - 'telemetry_perf_unittests_isolated_scripts', - 'win_specific_isolated_scripts', - ], - - 'chromium_win_rel_isolated_scripts_code_coverage': [ - 'gpu_dawn_webgpu_blink_web_tests', - ], - - 'chromium_win_rel_isolated_scripts_once': [ - 'chromedriver_py_tests_isolated_scripts', - 'components_perftests_isolated_scripts', - 'desktop_chromium_isolated_scripts', - 'desktop_once_isolated_scripts', - 'mojo_python_unittests_isolated_scripts', - 'telemetry_desktop_minidump_unittests_isolated_scripts', - 'telemetry_perf_unittests_isolated_scripts', - 'win_specific_isolated_scripts', - ], - - 'cronet_dbg_isolated_scripts': [ - 'cronet_sizes_suite', - ], - - 'cronet_rel_isolated_scripts': [ - 'cronet_resource_sizes', - 'cronet_sizes_suite', - ], - - 'devtools_gtests': [ - 'blink_unittests_suite', - 'devtools_browser_tests_suite', - ], - - 'fuchsia_arm64_isolated_scripts': [ - 'fuchsia_sizes_tests', - 'gpu_angle_fuchsia_unittests_isolated_scripts', - ], - - 'fuchsia_gtests': [ - 'fuchsia_chrome_gtests', - 'fuchsia_web_engine_gtests', - ], - - 'fuchsia_isolated_scripts': [ - 'chromium_webkit_isolated_scripts', - 'gpu_angle_fuchsia_unittests_isolated_scripts', - ], - - 'gpu_angle_linux_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_webgl2_conformance_gl_passthrough_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', - ], - - 'gpu_angle_mac_telemetry_tests': [ - 'gpu_info_collection_telemetry_tests', - 'gpu_webgl2_conformance_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webgl2_conformance_metal_passthrough_graphite_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webgl_conformance_metal_passthrough_ganesh_telemetry_tests', - 'gpu_webgl_conformance_metal_passthrough_graphite_telemetry_tests', - 'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests', - ], - - 'gpu_angle_win_intel_nvidia_telemetry_tests': [ - 'gpu_info_collection_telemetry_tests', - 'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests', - 'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests', - ], - - 'gpu_chromeos_telemetry_tests': [ - 'gpu_webgl_conformance_telemetry_tests', - ], - - 'gpu_common_android_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_validating_telemetry_tests', - 'gpu_webgl_conformance_validating_telemetry_tests', - ], - - 'gpu_common_gl_passthrough_ganesh_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_ganesh_telemetry_tests', - ], - - 'gpu_common_linux_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webgl_conformance_telemetry_tests', - ], - - 'gpu_common_metal_passthrough_graphite_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_metal_passthrough_graphite_telemetry_tests', - 'gpu_webgl_conformance_metal_passthrough_graphite_telemetry_tests', - ], - - 'gpu_common_win_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests', - ], - - 'gpu_dawn_android_compat_telemetry_tests': [ - 'gpu_dawn_webgpu_compat_cts', - 'gpu_dawn_webgpu_cts', - ], - - 'gpu_dawn_android_isolated_scripts': [ - 'gpu_dawn_perf_smoke_isolated_scripts', - 'gpu_dawn_webgpu_blink_web_tests', - ], - - 'gpu_dawn_android_telemetry_tests': [ - 'gpu_dawn_webgpu_cts', - ], - - 'gpu_dawn_asan_isolated_scripts': [ - 'gpu_dawn_common_isolated_scripts', - 'gpu_dawn_perf_smoke_isolated_scripts', - 'gpu_dawn_webgpu_blink_web_tests', - 'gpu_dawn_webgpu_blink_web_tests_force_swiftshader', - ], - - 'gpu_dawn_compat_telemetry_tests': [ - 'gpu_dawn_web_platform_webgpu_cts_force_swiftshader', - 'gpu_dawn_webgpu_compat_cts', - 'gpu_dawn_webgpu_cts', - ], - - 'gpu_dawn_integration_asan_gtests_passthrough': [ - 'gpu_common_gtests_passthrough', - 'gpu_dawn_gtests', - 'gpu_dawn_gtests_no_dxc', - ], - - 'gpu_dawn_integration_gtests_passthrough': [ - 'gpu_common_gtests_passthrough', - 'gpu_dawn_gtests', - 'gpu_dawn_gtests_with_validation', - ], - - 'gpu_dawn_integration_gtests_passthrough_win_x64': [ - 'gpu_common_gtests_passthrough', - 'gpu_dawn_gtests', - 'gpu_dawn_gtests_no_dxc', - 'gpu_dawn_gtests_no_dxc_with_validation', - 'gpu_dawn_gtests_with_validation', - ], - - 'gpu_dawn_isolated_scripts': [ - 'gpu_dawn_common_isolated_scripts', - 'gpu_dawn_perf_smoke_isolated_scripts', - 'gpu_dawn_webgpu_blink_web_tests', - 'gpu_dawn_webgpu_blink_web_tests_force_swiftshader', - ], - - 'gpu_dawn_telemetry_tests': [ - 'gpu_dawn_web_platform_webgpu_cts_force_swiftshader', - 'gpu_dawn_webgpu_cts', - ], - - 'gpu_dawn_telemetry_tests_fxc': [ - 'gpu_dawn_web_platform_webgpu_cts_force_swiftshader', - 'gpu_dawn_webgpu_cts_fxc', - ], - - 'gpu_dawn_telemetry_win_x64_tests': [ - 'gpu_dawn_web_platform_webgpu_cts_force_swiftshader', - 'gpu_dawn_webgpu_cts', - 'gpu_dawn_webgpu_cts_fxc', - ], - - 'gpu_dawn_tsan_gtests': [ - 'gpu_dawn_gtests', - ], - - 'gpu_desktop_passthrough_gtests': [ - 'gpu_angle_unit_gtests', - 'gpu_common_gtests_passthrough', - 'gpu_desktop_specific_gtests', - ], - - 'gpu_fyi_android_gtests': [ - 'gpu_angle_unit_gtests', - 'gpu_common_gtests_passthrough', - 'gpu_common_gtests_validating', - 'gpu_fyi_and_optional_non_linux_gtests', - ], - - 'gpu_fyi_android_shieldtv_gtests': [ - 'gpu_angle_unit_gtests', - 'gpu_common_gtests_passthrough', - 'gpu_common_gtests_validating', - 'gpu_fyi_and_optional_non_linux_gtests', - ], - - 'gpu_fyi_android_webgl2_and_gold_telemetry_tests': [ - 'gpu_validating_telemetry_tests', - 'gpu_webgl2_conformance_gles_passthrough_telemetry_tests', - 'gpu_webgl2_conformance_validating_telemetry_tests', - ], - - 'gpu_fyi_chromeos_release_gtests': [ - 'gpu_common_gtests_passthrough', - ], - - 'gpu_fyi_chromeos_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webcodecs_telemetry_test', - 'gpu_webgl2_conformance_gles_passthrough_telemetry_tests', - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests', - ], - - 'gpu_fyi_lacros_release_gtests': [ - 'gpu_memory_buffer_impl_tests_suite', - ], - - 'gpu_fyi_lacros_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webcodecs_telemetry_test', - 'gpu_webgl2_conformance_gles_passthrough_telemetry_tests', - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests', - ], - - 'gpu_fyi_linux_debug_gtests': [ - 'gpu_common_gtests_passthrough', - ], - - 'gpu_fyi_linux_debug_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', - ], - - 'gpu_fyi_linux_release_gtests': [ - 'gpu_angle_unit_gtests', - 'gpu_common_gtests_passthrough', - 'gpu_desktop_specific_gtests', - 'gpu_memory_buffer_impl_tests_suite', - 'gpu_vulkan_gtests', - ], - - 'gpu_fyi_linux_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webgl2_conformance_gl_passthrough_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', - ], - - 'gpu_fyi_linux_release_vulkan_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_skia_renderer_vulkan_passthrough_telemetry_tests', - 'gpu_webgl2_conformance_gl_passthrough_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_telemetry_tests', - ], - - 'gpu_fyi_mac_debug_gtests': [ - 'gpu_angle_unit_gtests', - 'gpu_common_gtests_passthrough', - 'gpu_fyi_and_optional_non_linux_gtests', - 'gpu_fyi_mac_specific_gtests', - ], - - 'gpu_fyi_mac_nvidia_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webcodecs_gl_passthrough_ganesh_telemetry_test', - 'gpu_webgl2_conformance_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests', - ], - - 'gpu_fyi_mac_pro_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_metal_passthrough_graphite_telemetry_tests', - 'gpu_webgl2_conformance_metal_passthrough_graphite_telemetry_tests', - 'gpu_webgl_conformance_metal_passthrough_graphite_telemetry_tests', - ], - - 'gpu_fyi_mac_release_gtests': [ - 'gpu_angle_unit_gtests', - 'gpu_common_gtests_passthrough', - 'gpu_desktop_specific_gtests', - 'gpu_fyi_and_optional_non_linux_gtests', - 'gpu_fyi_mac_specific_gtests', - ], - - 'gpu_fyi_mac_release_telemetry_tests': [ - 'gpu_gl_passthrough_ganesh_telemetry_tests', - 'gpu_metal_passthrough_ganesh_telemetry_tests', - 'gpu_webcodecs_gl_passthrough_ganesh_telemetry_test', - 'gpu_webcodecs_metal_passthrough_ganesh_telemetry_test', - 'gpu_webcodecs_metal_passthrough_graphite_telemetry_test', - 'gpu_webgl2_conformance_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webgl2_conformance_metal_passthrough_graphite_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webgl_conformance_metal_passthrough_ganesh_telemetry_tests', - 'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests', - ], - - 'gpu_fyi_only_mac_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_gl_passthrough_ganesh_telemetry_tests', - 'gpu_metal_passthrough_ganesh_telemetry_tests', - 'gpu_metal_passthrough_graphite_telemetry_tests', - 'gpu_webcodecs_gl_passthrough_ganesh_telemetry_test', - 'gpu_webcodecs_metal_passthrough_ganesh_telemetry_test', - 'gpu_webcodecs_metal_passthrough_graphite_telemetry_test', - 'gpu_webgl2_conformance_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webgl2_conformance_metal_passthrough_graphite_telemetry_tests', - 'gpu_webgl_conformance_gl_passthrough_ganesh_telemetry_tests', - 'gpu_webgl_conformance_metal_passthrough_ganesh_telemetry_tests', - 'gpu_webgl_conformance_metal_passthrough_graphite_telemetry_tests', - 'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests', - ], - - 'gpu_fyi_win_amd_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webcodecs_telemetry_test', - 'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests', - ], - - 'gpu_fyi_win_debug_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests', - 'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests', - ], - - 'gpu_fyi_win_gtests': [ - 'gpu_angle_unit_gtests', - 'gpu_common_gtests_passthrough', - 'gpu_default_and_optional_win_media_foundation_specific_gtests', - 'gpu_default_and_optional_win_specific_gtests', - 'gpu_desktop_specific_gtests', - 'gpu_fyi_and_optional_non_linux_gtests', - 'gpu_fyi_and_optional_win_specific_gtests', - ], - - 'gpu_fyi_win_intel_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webcodecs_telemetry_test', - 'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests', - 'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests', - ], - - 'gpu_fyi_win_optional_isolated_scripts': [ - 'gpu_command_buffer_perf_passthrough_isolated_scripts', - ], - - 'gpu_fyi_win_release_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_graphite_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_webcodecs_telemetry_test', - 'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests', - 'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests', - 'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests', - ], - - 'gpu_nexus5x_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_validating_telemetry_tests', - 'gpu_webcodecs_validating_telemetry_test', - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests', - 'gpu_webgl_conformance_validating_telemetry_tests', - ], - - 'gpu_nexus5x_telemetry_tests_v8': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_validating_telemetry_tests', - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests', - 'gpu_webgl_conformance_validating_telemetry_tests', - ], - - 'gpu_pixel_4_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_validating_telemetry_tests', - 'gpu_webcodecs_validating_telemetry_test', - 'gpu_webgl2_conformance_gles_passthrough_telemetry_tests', - 'gpu_webgl2_conformance_validating_telemetry_tests', - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests', - 'gpu_webgl_conformance_validating_telemetry_tests', - ], - - 'gpu_pixel_6_telemetry_tests': [ - 'gpu_common_and_optional_telemetry_tests', - 'gpu_passthrough_graphite_telemetry_tests', - 'gpu_passthrough_telemetry_tests', - 'gpu_validating_telemetry_tests', - 'gpu_webcodecs_validating_telemetry_test', - 'gpu_webgl2_conformance_gles_passthrough_telemetry_tests', - 'gpu_webgl2_conformance_validating_telemetry_tests', - 'gpu_webgl_conformance_gles_passthrough_graphite_telemetry_tests', - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests', - 'gpu_webgl_conformance_validating_telemetry_tests', - ], - - 'gpu_swangle_telemetry_tests': [ - 'gpu_webgl_conformance_swangle_passthrough_telemetry_tests', - ], - - 'gpu_win_gtests': [ - 'gpu_angle_unit_gtests', - 'gpu_common_gtests_passthrough', - 'gpu_default_and_optional_win_specific_gtests', - 'gpu_desktop_specific_gtests', - ], - - 'linux_chromeos_gtests': [ - 'aura_gtests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_linux_and_chromeos_only', - 'chromium_gtests_for_win_and_linux_only', - 'linux_chromeos_lacros_gtests', - 'linux_chromeos_specific_gtests', - 'linux_flavor_specific_chromium_gtests', - 'non_android_chromium_gtests', - ], - - 'linux_chromeos_gtests_oobe': [ - 'aura_gtests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_linux_and_chromeos_only', - 'chromium_gtests_for_win_and_linux_only', - 'linux_chromeos_lacros_gtests', - 'linux_chromeos_oobe_specific_tests', - 'linux_chromeos_specific_gtests', - 'linux_flavor_specific_chromium_gtests', - 'non_android_chromium_gtests', - ], - - 'linux_chromeos_isolated_scripts': [ - 'blink_web_tests_ppapi_isolated_scripts', - 'chrome_sizes_suite', - ], - - 'linux_chromeos_rel_cq': [ - 'ash_pixel_gtests', - 'aura_gtests', - 'chromium_gtests', - 'chromium_gtests_for_devices_with_graphical_output', - 'chromium_gtests_for_linux_and_chromeos_only', - 'chromium_gtests_for_win_and_linux_only', - 'linux_chromeos_lacros_gtests', - 'linux_chromeos_specific_gtests', - 'linux_flavor_specific_chromium_gtests', - 'non_android_chromium_gtests', - 'pixel_experimental_browser_tests_gtests', - ], - - 'linux_viz_gtests': [ - 'gpu_fyi_vulkan_swiftshader_gtests', - ], - - 'network_service_extra_gtests': [ - 'network_service_fyi_gtests', - ], - - 'oreo_isolated_scripts': [ - 'android_isolated_scripts', - 'chromium_junit_tests_scripts', - 'components_perftests_isolated_scripts', - 'monochrome_public_apk_checker_isolated_script', - 'telemetry_android_minidump_unittests_isolated_scripts', - 'telemetry_perf_unittests_isolated_scripts_android', - ], - - 'rust_host_gtests': [ - 'rust_common_gtests', - ], - - 'webview_fyi_bot_all_gtests': [ - 'system_webview_shell_instrumentation_tests', - 'webview_bot_instrumentation_test_apk_mutations_gtest', - 'webview_bot_instrumentation_test_apk_no_field_trial_gtest', - 'webview_bot_unittests_gtest', - 'webview_cts_tests_gtest', - 'webview_cts_tests_gtest_no_field_trial', - 'webview_ui_instrumentation_tests', - 'webview_ui_instrumentation_tests_no_field_trial', - ], - - 'webview_native_coverage_bot_gtests': [ - 'webview_bot_instrumentation_test_apk_mutations_gtest', - 'webview_bot_instrumentation_test_apk_no_field_trial_gtest', - 'webview_bot_unittests_gtest', - ], - - 'webview_trichrome_64_cts_gtests': [ - 'webview_trichrome_64_cts_tests_no_field_trial_suite', - 'webview_trichrome_64_cts_tests_suite', - ], - - 'win_specific_isolated_scripts_and_sizes': [ - 'chrome_sizes_suite', - 'win_specific_isolated_scripts', - ], - }, - - 'matrix_compound_suites': { - - 'android_11_emulator_gtests': { - 'android_emulator_specific_chrome_public_tests': {}, - 'android_smoke_tests': {}, - 'android_specific_chromium_gtests': {}, - 'android_trichrome_smoke_tests': {}, - 'chromium_gtests': {}, - 'chromium_gtests_for_devices_with_graphical_output': {}, - 'linux_flavor_specific_chromium_gtests': {}, - 'system_webview_shell_instrumentation_tests': {}, - 'webview_trichrome_cts_tests_suite': { - 'variants': [ - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS', - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS', - ], - }, - 'webview_ui_instrumentation_tests': {}, - }, - - 'android_12_emulator_gtests': { - 'android_ci_only_fieldtrial_webview_tests': {}, - 'android_emulator_specific_chrome_public_tests': {}, - 'android_smoke_tests': {}, - 'android_specific_chromium_gtests': {}, - 'android_trichrome_smoke_tests': {}, - 'chrome_profile_generator_tests': {}, - 'chromium_gtests': {}, - 'chromium_gtests_for_devices_with_graphical_output': {}, - 'fieldtrial_android_tests': {}, - 'jni_zero_sample_apk_test_suite': {}, - 'linux_flavor_specific_chromium_gtests': {}, - 'minidump_uploader_tests': {}, - 'system_webview_shell_instrumentation_tests': {}, - 'webview_trichrome_64_cts_tests_suite': { - 'variants': [ - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS', - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS', - ], - }, - 'webview_ui_instrumentation_tests': {}, - }, - - 'android_12l_emulator_gtests': { - 'android_emulator_specific_chrome_public_tests': {}, - 'android_smoke_tests': {}, - 'android_specific_chromium_gtests': {}, - 'android_trichrome_smoke_tests': {}, - 'chromium_gtests': {}, - 'chromium_gtests_for_devices_with_graphical_output': {}, - 'linux_flavor_specific_chromium_gtests': {}, - 'system_webview_shell_instrumentation_tests': {}, - 'webview_ui_instrumentation_tests': {}, - }, - - 'android_12l_landscape_emulator_gtests': { - 'android_emulator_specific_chrome_public_tests': {}, - }, - - 'android_13_emulator_gtests': { - 'android_ci_only_fieldtrial_webview_tests': {}, - 'android_emulator_specific_chrome_public_tests': {}, - 'android_smoke_tests': {}, - 'android_specific_chromium_gtests': {}, - 'android_trichrome_smoke_tests': {}, - 'chrome_profile_generator_tests': {}, - 'chromium_gtests': {}, - 'chromium_gtests_for_devices_with_graphical_output': {}, - 'fieldtrial_android_tests': {}, - 'jni_zero_sample_apk_test_suite': {}, - 'linux_flavor_specific_chromium_gtests': {}, - 'minidump_uploader_tests': {}, - 'system_webview_shell_instrumentation_tests': {}, - 'webview_trichrome_64_cts_tests_suite': { - 'variants': [ - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS', - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS', - ], - }, - 'webview_ui_instrumentation_tests': {}, - }, - - 'android_14_device_fyi_gtests': { - 'system_webview_shell_instrumentation_tests': {}, - 'webview_trichrome_64_cts_tests_suite': { - 'variants': [ - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS', - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS', - ], - }, - 'webview_ui_instrumentation_tests': {}, - }, - - 'android_14_device_gtests': { - 'android_hardware_specific_gtests': {}, - 'android_limited_capacity_gtests': {}, - 'android_smoke_tests': {}, - 'android_trichrome_smoke_tests': {}, - 'chrome_public_tests': {}, - }, - - 'android_14_emulator_gtests': { - 'android_emulator_specific_chrome_public_tests': {}, - 'android_smoke_tests': {}, - 'android_specific_chromium_gtests': {}, - 'android_trichrome_smoke_tests': {}, - 'chromium_gtests': {}, - 'chromium_gtests_for_devices_with_graphical_output': {}, - 'linux_flavor_specific_chromium_gtests': {}, - 'system_webview_shell_instrumentation_tests': {}, - 'webview_trichrome_64_cts_tests_no_field_trial_suite': {}, - 'webview_trichrome_64_cts_tests_suite': { - 'variants': [ - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS', - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS', - ], - }, - 'webview_ui_instrumentation_tests': {}, - }, - - 'android_14_tablet_gtests': { - 'android_smoke_tests': {}, - 'android_specific_chromium_gtests': {}, - 'android_trichrome_smoke_tests': {}, - 'chrome_public_tests': {}, - 'chromium_gtests': {}, - 'chromium_gtests_for_devices_with_graphical_output': {}, - 'linux_flavor_specific_chromium_gtests': {}, - 'system_webview_shell_instrumentation_tests': {}, - 'webview_trichrome_64_cts_tests_no_field_trial_suite': {}, - 'webview_trichrome_64_cts_tests_suite': { - 'variants': [ - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS', - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS', - ], - }, - 'webview_ui_instrumentation_tests': {}, - }, - - 'android_15_emulator_gtests': { - 'android_emulator_specific_chrome_public_tests': {}, - 'android_smoke_tests': {}, - 'android_specific_chromium_gtests': {}, - 'android_trichrome_smoke_tests': {}, - 'chromium_gtests': {}, - 'chromium_gtests_for_devices_with_graphical_output': {}, - 'linux_flavor_specific_chromium_gtests': {}, - 'system_webview_shell_instrumentation_tests': {}, - 'webview_trichrome_64_cts_tests_no_field_trial_suite': {}, - 'webview_trichrome_64_cts_tests_suite': { - 'variants': [ - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS', - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS', - ], - }, - 'webview_ui_instrumentation_tests': {}, - }, - - 'android_fieldtrial_rel_webview_tests': { - 'fieldtrial_android_tests': {}, - 'system_webview_shell_instrumentation_tests': { - 'variants': [ - 'DISABLE_FIELD_TRIAL_CONFIG_WEBVIEW_COMMANDLINE', - 'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR_WEBVIEW_COMMANDLINE', - 'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR_WEBVIEW_COMMANDLINE', - ], - }, - 'webview_bot_instrumentation_test_apk_gtest': { - 'variants': [ - 'DISABLE_FIELD_TRIAL_CONFIG', - 'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR', - 'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR', - ], - }, - 'webview_trichrome_64_cts_field_trial_tests': { - 'variants': [ - 'DISABLE_FIELD_TRIAL_CONFIG', - 'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR', - 'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR', - ], - }, - 'webview_ui_instrumentation_tests': { - 'variants': [ - 'DISABLE_FIELD_TRIAL_CONFIG', - 'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR', - 'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR', - ], - }, - }, - - 'chromeos_brya_skylab_tests': { - 'chromeos_chrome_all_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_criticalstaging_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_disabled_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_integration_tests_suite': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_system_friendly_gtests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_vaapi_gtests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'chromeos_ctp_preuprev_tests': { - 'chromeos_chrome_all_tast_tests': { - 'mixins': [ - 'shards-30', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_device_only_gtests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_integration_tests_suite': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'chromeos_jacuzzi_preuprev_tests': { - 'chromeos_chrome_cq_medium_tast_tests': { - 'mixins': [ - 'shards-10', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_device_only_gtests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_integration_tests_suite': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'chromeos_jacuzzi_rel_skylab_tests': { - 'chromeos_chrome_all_tast_tests': { - 'mixins': [ - 'chromeos-tast-public-builder', - 'shards-30', - ], - 'variants': [ - 'CROS_PUBLIC_LKGM', - ], - }, - 'chromeos_chrome_criticalstaging_tast_tests': { - 'mixins': [ - 'chromeos-tast-public-builder', - ], - 'variants': [ - 'CROS_PUBLIC_LKGM', - ], - }, - 'chromeos_chrome_disabled_tast_tests': { - 'mixins': [ - 'chromeos-tast-public-builder', - ], - 'variants': [ - 'CROS_PUBLIC_LKGM', - ], - }, - 'chromeos_device_only_gtests': { - 'variants': [ - 'CROS_PUBLIC_LKGM', - ], - }, - }, - - 'chromeos_jacuzzi_skylab_tests': { - 'chromeos_chrome_all_tast_tests': { - 'mixins': [ - 'shards-30', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_criticalstaging_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_disabled_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_device_only_gtests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_integration_tests_suite': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'chromeos_octopus_rel_skylab_tests': { - 'chromeos_chrome_all_tast_tests': { - 'mixins': [ - 'chromeos-tast-public-builder', - ], - 'variants': [ - 'CROS_PUBLIC_LKGM', - ], - }, - 'chromeos_chrome_criticalstaging_tast_tests': { - 'mixins': [ - 'chromeos-tast-public-builder', - ], - 'variants': [ - 'CROS_PUBLIC_LKGM', - ], - }, - 'chromeos_chrome_disabled_tast_tests': { - 'mixins': [ - 'chromeos-tast-public-builder', - ], - 'variants': [ - 'CROS_PUBLIC_LKGM', - ], - }, - 'chromeos_device_only_gtests': { - 'variants': [ - 'CROS_PUBLIC_LKGM', - ], - }, - }, - - 'chromeos_octopus_skylab_tests': { - 'chromeos_chrome_all_tast_tests': { - 'mixins': [ - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_device_only_gtests': { - 'mixins': [ - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'chromeos_trogdor_skylab_tests': { - 'chromeos_chrome_all_tast_tests': { - 'mixins': [ - 'shards-20', - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_device_only_gtests': { - 'mixins': [ - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_integration_tests_suite': { - 'mixins': [ - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'chromeos_vmlab_tests': { - 'chromeos_chrome_all_tast_tests': { - 'mixins': [ - 'shards-20', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_criticalstaging_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_disabled_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_integration_tests_suite': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_system_friendly_gtests_fails_vmlab': { - 'mixins': [ - 'experiments', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_system_friendly_gtests_vmlab': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_vaapi_gtests': { - 'mixins': [ - 'experiments', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'chromeos_vmlab_tests_no_gtests': { - 'chromeos_chrome_all_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_criticalstaging_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_disabled_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_integration_tests_suite': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'chromeos_vmlab_tests_no_gtests_no_arc': { - 'chromeos_chrome_all_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_criticalstaging_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_disabled_tast_tests': { - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_integration_tests_suite': { - 'mixins': [ - 'crosier-no-arc', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'chromeos_volteer_skylab_tests': { - 'chromeos_chrome_all_tast_tests': { - 'mixins': [ - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_criticalstaging_tast_tests': { - 'mixins': [ - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_chrome_disabled_tast_tests': { - 'mixins': [ - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_device_only_gtests': { - 'mixins': [ - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - 'chromeos_integration_tests_suite': { - 'mixins': [ - 'skylab-cft', - ], - 'variants': [ - 'CROS_RELEASE_LKGM', - ], - }, - }, - - 'dawn_chromeos_release_telemetry_tests_volteer_skylab': { - 'gpu_dawn_webgpu_cts': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - }, - - 'dawn_chromeos_release_tests_volteer_skylab': { - 'gpu_common_gtests_passthrough': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - 'gpu_dawn_gtests': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - 'gpu_dawn_gtests_with_validation': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - }, - - 'fieldtrial_ios_simulator_tests': { - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'disable_field_trial_config_for_earl_grey', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'disable_field_trial_config_for_earl_grey', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - ], - }, - }, - - 'gpu_angle_ios_gtests': { - 'gpu_angle_ios_end2end_gtests': { - 'variants': [ - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_14_18_0', - ], - }, - 'gpu_angle_ios_white_box_gtests': { - 'variants': [ - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_14_18_0', - ], - }, - }, - - 'gpu_fyi_chromeos_release_gtests_volteer_skylab': { - 'gpu_common_gtests_passthrough': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - }, - - 'gpu_fyi_chromeos_release_telemetry_tests_jacuzzi_skylab': { - 'gpu_common_and_optional_telemetry_tests': { - 'variants': [ - 'CROS_JACUZZI_RELEASE_LKGM', - ], - }, - 'gpu_passthrough_telemetry_tests': { - 'variants': [ - 'CROS_JACUZZI_RELEASE_LKGM', - ], - }, - 'gpu_webcodecs_telemetry_test': { - 'variants': [ - 'CROS_JACUZZI_RELEASE_LKGM', - ], - }, - 'gpu_webgl2_conformance_gles_passthrough_telemetry_tests': { - 'variants': [ - 'CROS_JACUZZI_RELEASE_LKGM', - ], - }, - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests': { - 'variants': [ - 'CROS_JACUZZI_RELEASE_LKGM', - ], - }, - }, - - 'gpu_fyi_chromeos_release_telemetry_tests_volteer_skylab': { - 'gpu_common_and_optional_telemetry_tests': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - 'gpu_passthrough_telemetry_tests': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - 'gpu_webcodecs_telemetry_test': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - 'gpu_webgl2_conformance_gles_passthrough_telemetry_tests': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests': { - 'variants': [ - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM', - ], - }, - }, - - 'gpu_fyi_lacros_device_release_telemetry_tests': { - 'gpu_pixel_passthrough_telemetry_tests': { - 'variants': [ - 'LACROS_ASH_TOT', - ], - }, - 'gpu_webgl2_conformance_gles_passthrough_telemetry_tests': { - 'variants': [ - 'LACROS_ASH_TOT', - ], - }, - 'gpu_webgl_conformance_gles_passthrough_telemetry_tests': { - 'variants': [ - 'LACROS_ASH_TOT', - ], - }, - }, - - 'ios17_beta_simulator_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - ], - }, - 'ios_crash_xcuitests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_SE_3RD_GEN_17_5', - ], - }, - }, - - 'ios17_sdk_simulator_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_SE_3RD_GEN_17_5', - ], - }, - }, - - 'ios18_beta_simulator_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_crash_xcuitests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_10TH_GEN_18_0', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_10TH_GEN_18_0', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_15_18_0', - 'SIM_IPHONE_15_PRO_MAX_18_0', - ], - }, - }, - - 'ios18_sdk_simulator_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_crash_xcuitests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_15_18_0', - 'SIM_IPHONE_SE_3RD_GEN_18_0', - ], - }, - }, - - 'ios_asan_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_15_18_0', - ], - }, - }, - - 'ios_blink_dbg_tests': { - 'ios_blink_tests': { - 'variants': [ - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - }, - - 'ios_clang_tot_device_tests': { - 'clang_tot_gtests': { - 'variants': [ - 'IPHONE_7_15_4_1', - ], - }, - }, - - 'ios_clang_tot_sim_tests': { - 'clang_tot_gtests': { - 'variants': [ - 'SIM_IPHONE_X_16_4', - ], - }, - }, - - 'ios_code_coverage_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPHONE_14_16_4', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_16_4', - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPAD_PRO_6TH_GEN_16_4', - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_16_4', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPAD_PRO_6TH_GEN_16_4', - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_16_4', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_PRO_6TH_GEN_16_4', - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_16_4', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - }, - - 'ios_m1_simulator_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_14_PRO_MAX_17_5', - 'SIM_IPHONE_15_18_0', - 'SIM_IPHONE_15_PRO_MAX_18_0', - ], - }, - }, - - 'ios_simulator_full_configs_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPHONE_14_PLUS_17_5', - 'SIM_IPHONE_14_PLUS_18_0', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - }, - - 'ios_simulator_noncq_tests': { - 'ios_crash_xcuitests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPHONE_SE_3RD_GEN_16_4', - 'SIM_IPHONE_SE_3RD_GEN_17_5', - 'SIM_IPHONE_SE_3RD_GEN_18_0', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_16_4', - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - 'record_failed_tests', - ], - 'variants': [ - 'SIM_IPAD_PRO_6TH_GEN_16_4', - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_16_4', - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPAD_PRO_6TH_GEN_16_4', - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_PLUS_16_4', - 'SIM_IPHONE_14_PLUS_17_5', - 'SIM_IPHONE_14_PLUS_18_0', - 'SIM_IPHONE_SE_3RD_GEN_16_4', - 'SIM_IPHONE_SE_3RD_GEN_17_5', - 'SIM_IPHONE_SE_3RD_GEN_18_0', - ], - }, - }, - - 'ios_simulator_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_PRO_6TH_GEN_17_5', - 'SIM_IPAD_PRO_7TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - }, - - 'ios_webkit_tot_tests': { - 'ios_common_tests': { - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_cq_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_eg2_tests': { - 'mixins': [ - 'xcodebuild_sim_runner', - ], - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - 'ios_screen_size_dependent_tests': { - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - }, - - 'ios_webrtc_fyi_tests': { - 'ios_remoting_fyi_unittests': { - 'variants': [ - 'SIM_IPAD_AIR_5TH_GEN_17_5', - 'SIM_IPAD_AIR_6TH_GEN_18_0', - 'SIM_IPHONE_14_17_5', - 'SIM_IPHONE_15_18_0', - ], - }, - }, - - 'linux_optional_gpu_tests_rel_gpu_telemetry_tests': { - 'gpu_common_and_optional_telemetry_tests': { - 'variants': [ - 'LINUX_INTEL_UHD_630_STABLE', - 'LINUX_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_webcodecs_telemetry_test': { - 'variants': [ - 'LINUX_INTEL_UHD_630_STABLE', - 'LINUX_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_webgl2_conformance_gl_passthrough_telemetry_tests': { - 'variants': [ - 'LINUX_INTEL_UHD_630_STABLE', - 'LINUX_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_webgl_conformance_gl_passthrough_telemetry_tests': { - 'variants': [ - 'LINUX_INTEL_UHD_630_STABLE', - 'LINUX_NVIDIA_GTX_1660_STABLE', - ], - }, - }, - - 'mac_optional_gpu_tests_rel_gpu_telemetry_tests': { - 'gpu_common_and_optional_telemetry_tests': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - 'MAC_RETINA_NVIDIA_GPU_STABLE', - ], - }, - 'gpu_gl_passthrough_ganesh_telemetry_tests': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - ], - }, - 'gpu_metal_passthrough_ganesh_telemetry_tests': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - ], - }, - 'gpu_webcodecs_gl_passthrough_ganesh_telemetry_test': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - 'MAC_RETINA_NVIDIA_GPU_STABLE', - ], - }, - 'gpu_webcodecs_metal_passthrough_ganesh_telemetry_test': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - ], - }, - 'gpu_webcodecs_metal_passthrough_graphite_telemetry_test': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - ], - }, - 'gpu_webgl2_conformance_metal_passthrough_graphite_telemetry_tests': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - ], - }, - 'gpu_webgl_conformance_gl_passthrough_ganesh_telemetry_tests': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - ], - }, - 'gpu_webgl_conformance_metal_passthrough_ganesh_telemetry_tests': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - ], - }, - 'gpu_webgl_conformance_swangle_passthrough_representative_telemetry_tests': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - ], - }, - }, - - 'mac_optional_gpu_tests_rel_gtests': { - 'gpu_fyi_and_optional_non_linux_gtests': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - 'MAC_RETINA_NVIDIA_GPU_STABLE', - ], - }, - 'gpu_fyi_mac_specific_gtests': { - 'variants': [ - 'MAC_MINI_INTEL_GPU_STABLE', - 'MAC_RETINA_AMD_GPU_STABLE', - 'MAC_RETINA_NVIDIA_GPU_STABLE', - ], - }, - }, - - 'optimization_guide_desktop_gtests': { - 'optimization_guide_gpu_gtests': {}, - 'optimization_guide_nogpu_gtests': {}, - }, - - 'optimization_guide_desktop_script_tests': { - 'model_validation_tests_light_suite': {}, - 'model_validation_tests_suite': {}, - 'ondevice_quality_tests_suite': {}, - 'ondevice_stability_tests_suite': {}, - }, - - 'optimization_guide_linux_gtests': { - 'optimization_guide_gpu_gtests': { - 'variants': [ - 'INTEL_UHD_630_OR_770', - 'NVIDIA_GEFORCE_GTX_1660', - ], - }, - 'optimization_guide_nogpu_gtests': { - 'mixins': [ - 'gce', - ], - }, - }, - - 'optimization_guide_linux_script_tests': { - 'model_validation_tests_light_suite': { - 'mixins': [ - 'gce', - ], - }, - 'model_validation_tests_suite': { - 'mixins': [ - 'gce', - ], - }, - 'ondevice_quality_tests_suite': { - 'variants': [ - 'INTEL_UHD_630_OR_770', - 'NVIDIA_GEFORCE_GTX_1660', - ], - }, - 'ondevice_stability_tests_suite': { - 'variants': [ - 'INTEL_UHD_630_OR_770', - 'NVIDIA_GEFORCE_GTX_1660', - ], - }, - }, - - 'optimization_guide_win_gtests': { - 'optimization_guide_gpu_gtests': { - 'variants': [ - 'AMD_RADEON_RX_5500_XT', - 'INTEL_UHD_630_OR_770', - 'NVIDIA_GEFORCE_GTX_1660', - ], - }, - 'optimization_guide_nogpu_gtests': { - 'mixins': [ - 'gce', - ], - }, - }, - - 'optimization_guide_win_script_tests': { - 'model_validation_tests_light_suite': { - 'mixins': [ - 'gce', - ], - }, - 'model_validation_tests_suite': { - 'mixins': [ - 'gce', - ], - }, - 'ondevice_quality_tests_suite': { - 'variants': [ - 'AMD_RADEON_RX_5500_XT', - 'INTEL_UHD_630_OR_770', - 'NVIDIA_GEFORCE_GTX_1660', - ], - }, - 'ondevice_stability_tests_suite': { - 'variants': [ - 'AMD_RADEON_RX_5500_XT', - 'INTEL_UHD_630_OR_770', - 'NVIDIA_GEFORCE_GTX_1660', - ], - }, - }, - - 'webview_trichrome_10_cts_tests_gtest': { - 'webview_trichrome_cts_tests_suite': { - 'variants': [ - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS', - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS', - ], - }, - }, - - 'webview_trichrome_64_cts_hostside_gtests': { - 'webview_trichrome_64_cts_hostside_tests_suite': { - 'variants': [ - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS', - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS', - ], - }, - }, - - 'win_optional_gpu_tests_rel_gpu_telemetry_tests': { - 'gpu_common_and_optional_telemetry_tests': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_passthrough_graphite_telemetry_tests': { - 'variants': [ - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_webcodecs_telemetry_test': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_webgl2_conformance_d3d11_passthrough_telemetry_tests': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_webgl_conformance_d3d11_passthrough_telemetry_tests': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_webgl_conformance_d3d9_passthrough_telemetry_tests': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_webgl_conformance_vulkan_passthrough_telemetry_tests': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - }, - - 'win_optional_gpu_tests_rel_gtests': { - 'gpu_default_and_optional_win_media_foundation_specific_gtests': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - ], - }, - 'gpu_default_and_optional_win_specific_gtests': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_fyi_and_optional_non_linux_gtests': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - 'gpu_fyi_and_optional_win_specific_gtests': { - 'variants': [ - 'WIN10_INTEL_UHD_630_STABLE', - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - }, - - 'win_optional_gpu_tests_rel_isolated_scripts': { - 'gpu_command_buffer_perf_passthrough_isolated_scripts': { - 'variants': [ - 'WIN10_NVIDIA_GTX_1660_STABLE', - ], - }, - }, - }, -}
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl deleted file mode 100644 index d8c38a1..0000000 --- a/testing/buildbot/variants.pyl +++ /dev/null
@@ -1,426 +0,0 @@ -# THIS IS A GENERATED FILE DO NOT EDIT!!! -# Instead: -# 1. Modify //infra/config/targets/variants.star -# 2. Run //infra/config/main.star -# 3. Run //infra/config/scripts/sync-pyl-files.py - -{ - 'AMD_RADEON_RX_5500_XT': { - 'identifier': 'AMD Radeon RX 5500 XT', - 'mixins': [ - 'amd_radeon_rx_5500_xt', - ], - }, - 'CROS_JACUZZI_RELEASE_LKGM': { - 'identifier': 'JACUZZI_RELEASE_LKGM', - 'skylab': { - 'cros_board': 'jacuzzi', - 'use_lkgm': True, - }, - }, - 'CROS_PUBLIC_LKGM': { - 'identifier': 'PUBLIC_LKGM', - 'skylab': { - 'use_lkgm': True, - 'bucket': 'chromiumos-image-archive', - 'public_builder': 'cros_test_platform_public', - 'public_builder_bucket': 'testplatform-public', - }, - }, - 'CROS_RELEASE_LKGM': { - 'identifier': 'RELEASE_LKGM', - 'skylab': { - 'use_lkgm': True, - }, - }, - 'CROS_VOLTEER_PUBLIC_RELEASE_ASH_LKGM': { - 'identifier': 'VOLTEER_PUBLIC_RELEASE_LKGM', - 'skylab': { - 'cros_board': 'volteer', - 'cros_model': 'voxel', - 'use_lkgm': True, - 'bucket': 'chromiumos-image-archive', - 'dut_pool': 'chromium', - 'public_builder': 'cros_test_platform_public', - 'public_builder_bucket': 'testplatform-public', - }, - }, - 'DISABLE_FIELD_TRIAL_CONFIG': { - 'identifier': 'Disable Field Trial Config', - 'args': [ - '--disable-field-trial-config', - '--webview-verbose-logging', - ], - }, - 'DISABLE_FIELD_TRIAL_CONFIG_WEBVIEW_COMMANDLINE': { - 'identifier': 'Disable Field Trial Config', - 'args': [ - '--webview-command-line-arg=--disable-field-trial-config', - '--webview-command-line-arg=--webview-verbose-logging', - ], - }, - 'INTEL_UHD_630_OR_770': { - 'identifier': 'Intel UHD 630 or 770', - 'mixins': [ - 'intel_uhd_630_or_770', - ], - }, - 'IPHONE_7_15_4_1': { - 'identifier': 'iPhone 7 15.4.1', - 'swarming': { - 'dimensions': { - 'os': 'iOS-15.4.1', - 'device': 'iPhone9,1', - }, - }, - }, - 'LACROS_ASH_TOT': { - 'identifier': 'Ash ToT', - 'args': [ - '--deploy-lacros', - ], - }, - 'LINUX_INTEL_UHD_630_STABLE': { - 'identifier': 'UHD 630', - 'mixins': [ - 'linux_intel_uhd_630_stable', - ], - }, - 'LINUX_NVIDIA_GTX_1660_STABLE': { - 'identifier': 'GTX 1660', - 'mixins': [ - 'linux_nvidia_gtx_1660_stable', - ], - }, - 'MAC_MINI_INTEL_GPU_STABLE': { - 'identifier': '8086:3e9b', - 'mixins': [ - 'mac_mini_intel_gpu_stable', - ], - }, - 'MAC_RETINA_AMD_GPU_STABLE': { - 'identifier': '1002:67ef', - 'mixins': [ - 'mac_retina_amd_gpu_stable', - ], - }, - 'MAC_RETINA_NVIDIA_GPU_STABLE': { - 'identifier': '10de:0fe9', - 'mixins': [ - 'mac_retina_nvidia_gpu_stable', - ], - }, - 'NVIDIA_GEFORCE_GTX_1660': { - 'identifier': 'NVIDIA GeForce GTX 1660', - 'mixins': [ - 'nvidia_geforce_gtx_1660', - ], - }, - 'SIM_IPAD_10TH_GEN_18_0': { - 'identifier': 'iPad (10th generation) 18.0', - 'args': [ - '--platform', - 'iPad (10th generation)', - '--version', - '18.0', - ], - 'mixins': [ - 'ios_runtime_cache_18_0', - ], - }, - 'SIM_IPAD_AIR_5TH_GEN_16_4': { - 'identifier': 'iPad Air (5th generation) 16.4', - 'args': [ - '--platform', - 'iPad Air (5th generation)', - '--version', - '16.4', - ], - 'mixins': [ - 'ios_runtime_cache_16_4', - ], - }, - 'SIM_IPAD_AIR_5TH_GEN_17_5': { - 'identifier': 'iPad Air (5th generation) 17.5', - 'args': [ - '--platform', - 'iPad Air (5th generation)', - '--version', - '17.5', - ], - 'mixins': [ - 'ios_runtime_cache_17_5', - ], - }, - 'SIM_IPAD_AIR_6TH_GEN_18_0': { - 'identifier': 'iPad Air (6th generation) 18.0', - 'args': [ - '--platform', - 'iPad Air 11-inch (M2)', - '--version', - '18.0', - ], - 'mixins': [ - 'ios_runtime_cache_18_0', - ], - }, - 'SIM_IPAD_PRO_6TH_GEN_16_4': { - 'identifier': 'iPad Pro (12.9-inch) (6th generation) 16.4', - 'args': [ - '--platform', - 'iPad Pro (12.9-inch) (6th generation)', - '--version', - '16.4', - ], - 'mixins': [ - 'ios_runtime_cache_16_4', - ], - }, - 'SIM_IPAD_PRO_6TH_GEN_17_5': { - 'identifier': 'iPad Pro (12.9-inch) (6th generation) 17.5', - 'args': [ - '--platform', - 'iPad Pro (12.9-inch) (6th generation)', - '--version', - '17.5', - ], - 'mixins': [ - 'ios_runtime_cache_17_5', - ], - }, - 'SIM_IPAD_PRO_7TH_GEN_18_0': { - 'identifier': 'iPad Pro 13-inch (M4) 18.0', - 'args': [ - '--platform', - 'iPad Pro 13-inch (M4)', - '--version', - '18.0', - ], - 'mixins': [ - 'ios_runtime_cache_18_0', - ], - }, - 'SIM_IPHONE_14_16_4': { - 'identifier': 'iPhone 14 16.4', - 'args': [ - '--platform', - 'iPhone 14', - '--version', - '16.4', - ], - 'mixins': [ - 'ios_runtime_cache_16_4', - ], - }, - 'SIM_IPHONE_14_17_5': { - 'identifier': 'iPhone 14 17.5', - 'args': [ - '--platform', - 'iPhone 14', - '--version', - '17.5', - ], - 'mixins': [ - 'ios_runtime_cache_17_5', - ], - }, - 'SIM_IPHONE_14_18_0': { - 'identifier': 'iPhone 14 18.0', - 'args': [ - '--platform', - 'iPhone 14', - '--version', - '18.0', - ], - 'mixins': [ - 'ios_runtime_cache_18_0', - ], - }, - 'SIM_IPHONE_14_PLUS_16_4': { - 'identifier': 'iPhone 14 Plus 16.4', - 'args': [ - '--platform', - 'iPhone 14 Plus', - '--version', - '16.4', - ], - 'mixins': [ - 'ios_runtime_cache_16_4', - ], - }, - 'SIM_IPHONE_14_PLUS_17_5': { - 'identifier': 'iPhone 14 Plus 17.5', - 'args': [ - '--platform', - 'iPhone 14 Plus', - '--version', - '17.5', - ], - 'mixins': [ - 'ios_runtime_cache_17_5', - ], - }, - 'SIM_IPHONE_14_PLUS_18_0': { - 'identifier': 'iPhone 14 Plus 18.0', - 'args': [ - '--platform', - 'iPhone 14 Plus', - '--version', - '18.0', - ], - 'mixins': [ - 'ios_runtime_cache_18_0', - ], - }, - 'SIM_IPHONE_14_PRO_MAX_17_5': { - 'identifier': 'iPhone 14 Pro Max 17.5', - 'args': [ - '--platform', - 'iPhone 14 Pro Max', - '--version', - '17.5', - ], - 'mixins': [ - 'ios_runtime_cache_17_5', - ], - }, - 'SIM_IPHONE_15_18_0': { - 'identifier': 'iPhone 15 18.0', - 'args': [ - '--platform', - 'iPhone 15', - '--version', - '18.0', - ], - 'mixins': [ - 'ios_runtime_cache_18_0', - ], - }, - 'SIM_IPHONE_15_PRO_MAX_18_0': { - 'identifier': 'iPhone 15 Pro Max 18.0', - 'args': [ - '--platform', - 'iPhone 15 Pro Max', - '--version', - '18.0', - ], - 'mixins': [ - 'ios_runtime_cache_18_0', - ], - }, - 'SIM_IPHONE_SE_3RD_GEN_16_4': { - 'identifier': 'iPhone SE (3rd generation) 16.4', - 'args': [ - '--platform', - 'iPhone SE (3rd generation)', - '--version', - '16.4', - ], - 'mixins': [ - 'ios_runtime_cache_16_4', - ], - }, - 'SIM_IPHONE_SE_3RD_GEN_17_5': { - 'identifier': 'iPhone SE (3rd generation) 17.5', - 'args': [ - '--platform', - 'iPhone SE (3rd generation)', - '--version', - '17.5', - ], - 'mixins': [ - 'ios_runtime_cache_17_5', - ], - }, - 'SIM_IPHONE_SE_3RD_GEN_18_0': { - 'identifier': 'iPhone SE (3rd generation) 18.0', - 'args': [ - '--platform', - 'iPhone SE (3rd generation)', - '--version', - '18.0', - ], - 'mixins': [ - 'ios_runtime_cache_18_0', - ], - }, - 'SIM_IPHONE_X_16_4': { - 'identifier': 'iPhone X 16.4', - 'args': [ - '--platform', - 'iPhone X', - '--version', - '16.4', - ], - 'mixins': [ - 'ios_runtime_cache_16_4', - ], - }, - 'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR': { - 'identifier': 'Single Group Per Study Prefer Existing Behavior Field Trial Config', - 'args': [ - '--variations-test-seed-path=../../third_party/chromium-variations/single_group_per_study_prefer_existing_behavior/seed.json', - '--accept-empty-variations-seed-signature', - '--webview-verbose-logging', - '--disable-field-trial-config', - '--fake-variations-channel=stable', - ], - }, - 'SINGLE_GROUP_PER_STUDY_PREFER_EXISTING_BEHAVIOR_WEBVIEW_COMMANDLINE': { - 'identifier': 'Single Group Per Study Prefer Existing Behavior Field Trial Config', - 'args': [ - '--webview-variations-test-seed-path=../../third_party/chromium-variations/single_group_per_study_prefer_existing_behavior/seed.json', - '--webview-command-line-arg=--accept-empty-variations-seed-signature', - '--webview-command-line-arg=--webview-verbose-logging', - '--webview-command-line-arg=--disable-field-trial-config', - '--webview-command-line-arg=--fake-variations-channel=stable', - ], - }, - 'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR': { - 'identifier': 'Single Group Per Study Prefer New Behavior Field Trial Config', - 'args': [ - '--variations-test-seed-path=../../third_party/chromium-variations/single_group_per_study_prefer_new_behavior/seed.json', - '--accept-empty-variations-seed-signature', - '--webview-verbose-logging', - '--disable-field-trial-config', - '--fake-variations-channel=stable', - ], - }, - 'SINGLE_GROUP_PER_STUDY_PREFER_NEW_BEHAVIOR_WEBVIEW_COMMANDLINE': { - 'identifier': 'Single Group Per Study Prefer New Behavior Field Trial Config', - 'args': [ - '--webview-variations-test-seed-path=../../third_party/chromium-variations/single_group_per_study_prefer_new_behavior/seed.json', - '--webview-command-line-arg=--accept-empty-variations-seed-signature', - '--webview-command-line-arg=--webview-verbose-logging', - '--webview-command-line-arg=--disable-field-trial-config', - '--webview-command-line-arg=--fake-variations-channel=stable', - ], - }, - 'WEBVIEW_TRICHROME_FULL_CTS_TESTS': { - 'identifier': 'full_mode', - 'swarming': { - 'shards': 2, - }, - }, - 'WEBVIEW_TRICHROME_INSTANT_CTS_TESTS': { - 'identifier': 'instant_mode', - 'args': [ - '--exclude-annotation', - 'AppModeFull', - '--test-apk-as-instant', - ], - }, - 'WIN10_INTEL_UHD_630_STABLE': { - 'identifier': '8086:9bc5', - 'mixins': [ - 'swarming_containment_auto', - 'win10_intel_uhd_630_stable', - ], - }, - 'WIN10_NVIDIA_GTX_1660_STABLE': { - 'identifier': '10de:2184', - 'mixins': [ - 'win10_nvidia_gtx_1660_stable', - ], - }, -}
diff --git a/testing/scripts/run_performance_tests.py b/testing/scripts/run_performance_tests.py index c6889e1f..bf30ebe 100755 --- a/testing/scripts/run_performance_tests.py +++ b/testing/scripts/run_performance_tests.py
@@ -662,6 +662,12 @@ os.path.join(isolated_out_dir, 'benchmarks_shard_map.json')) +def fetch_binary_path(dependency_name, os_name='linux', arch='x86_64'): + if binary_manager.NeedsInit(): + binary_manager.InitDependencyManager(None) + return binary_manager.FetchPath(dependency_name, os_name=os_name, arch=arch) + + class CrossbenchTest(object): """This class is for running Crossbench tests. @@ -690,7 +696,6 @@ BENCHMARK_FILESERVERS = {'speedometer_3.0': 'third_party/speedometer/v3.0'} def __init__(self, options, isolated_out_dir): - binary_manager.InitDependencyManager(None) self.options = options self.isolated_out_dir = isolated_out_dir browser_arg = self._get_browser_arg(options.passthrough_args) @@ -741,8 +746,7 @@ # TODO: Use update_wpr library when it supports Crossbench archive files. wpr_name = 'crossbench_android_speedometer_3.0_000.wprgo' archive = str(PAGE_SETS_DATA / wpr_name) - if not (wpr_go := binary_manager.FetchPath( - 'wpr_go', os_name='linux', arch='x86_64')): + if (wpr_go := fetch_binary_path('wpr_go')) is None: raise ValueError(f'wpr_go not found: {wpr_go}') if wpr_arg: # Replacing --wpr with --network. @@ -1156,6 +1160,7 @@ benchmarks = shard_configuration['crossbench'] # Overwriting the "run_benchmark" with the Crossbench tool. options.executable = str(CROSSBENCH_TOOL) + original_passthrough_args = options.passthrough_args for benchmark, benchmark_config in benchmarks.items(): display_name = benchmark_config.get('display_name', benchmark) print(f'\n### {display_name} ###') @@ -1168,6 +1173,7 @@ overall_return_code = return_code or overall_return_code test_results_files.append( OutputFilePaths(isolated_out_dir, display_name).test_results) + options.passthrough_args = original_passthrough_args return overall_return_code
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 90d4c2ae..6ce46ba 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1989,6 +1989,26 @@ ] } ], + "AutofillEnableVcnGrayOutForMerchantOptOut": [ + { + "platforms": [ + "android", + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "AutofillEnableVcnGrayOutForMerchantOptOut" + ] + } + ] + } + ], "AutofillEnableVerveCardSupport": [ { "platforms": [ @@ -4247,6 +4267,24 @@ ] } ], + "ChromeHomeFrequency": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled_4H", + "params": { + "start_surface_return_time_on_tablet_seconds": "14400" + }, + "enable_features": [ + "StartSurfaceReturnTime" + ] + } + ] + } + ], "ChromeLabs": [ { "platforms": [ @@ -7758,7 +7796,7 @@ "link_capturing_state": "on_by_default" }, "enable_features": [ - "DesktopPWAsLinkCapturing" + "PwaNavigationCapturing" ] }, { @@ -7768,7 +7806,7 @@ "link_capturing_state": "off_by_default" }, "enable_features": [ - "DesktopPWAsLinkCapturing" + "PwaNavigationCapturing" ] } ] @@ -10141,7 +10179,6 @@ "EnableFingerprintingProtectionFilter" ], "disable_features": [ - "FingerprintingProtectionSetting", "FingerprintingProtectionUx" ] } @@ -12923,6 +12960,8 @@ "name": "AllFeatures", "enable_features": [ "ForceSafeSearchForUnauthenticatedSupervisedUsers", + "ForceSupervisedUserReauthenticationForBlockedSites", + "ForceSupervisedUserReauthenticationForYouTube", "HideGuestModeForSupervisedUsers", "UncredentialedFilteringFallbackForSupervisedUsers" ] @@ -15118,11 +15157,11 @@ ] }, { - "name": "Enabled_PromotedBy100", + "name": "Enabled_DemotedBy100", "params": { "MlUrlPiecewiseMappedSearchBlending": "true", - "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,590;0.034,695;0.043,890;0.067,895;0.076,1000;0.117,1030;0.147,1300;0.184,1305;0.2,1400;0.647,1450;0.668,1510;0.988,1530;1,1530", - "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1514", + "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,590;0.034,495;0.043,690;0.067,695;0.076,800;0.117,830;0.147,1100;0.184,1105;0.2,1200;0.647,1250;0.668,1310;0.988,1330;1,1530", + "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1314", "MlUrlPiecewiseMappedSearchBlending_RelevanceBias": "0", "MlUrlScoringShortcutDocumentSignals": "true", "MlUrlSearchBlending_MappedSearchBlending": "false", @@ -15135,11 +15174,11 @@ ] }, { - "name": "Enabled_PromotedBy50", + "name": "Enabled_DemotedBy150", "params": { "MlUrlPiecewiseMappedSearchBlending": "true", - "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,590;0.034,645;0.043,840;0.067,845;0.076,950;0.117,980;0.147,1250;0.184,1255;0.2,1350;0.647,1400;0.668,1460;0.988,1480;1,1530", - "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1464", + "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,590;0.034,445;0.043,640;0.067,645;0.076,750;0.117,780;0.147,1050;0.184,1055;0.2,1150;0.647,1200;0.668,1260;0.988,1280;1,1530", + "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1264", "MlUrlPiecewiseMappedSearchBlending_RelevanceBias": "0", "MlUrlScoringShortcutDocumentSignals": "true", "MlUrlSearchBlending_MappedSearchBlending": "false", @@ -15169,7 +15208,7 @@ "params": { "MlUrlPiecewiseMappedSearchBlending": "true", "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,550;0.018,1300;0.14,1398;1,1422", - "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1400", + "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1414", "MlUrlPiecewiseMappedSearchBlending_RelevanceBias": "0", "MlUrlScoringShortcutDocumentSignals": "true", "enable_scoring_signals_annotators_for_ml_scoring": "true" @@ -15185,7 +15224,7 @@ "params": { "MlUrlPiecewiseMappedSearchBlending": "true", "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,550;0.018,1250;0.14,1348;1,1422", - "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1350", + "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1364", "MlUrlPiecewiseMappedSearchBlending_RelevanceBias": "0", "MlUrlScoringShortcutDocumentSignals": "true", "enable_scoring_signals_annotators_for_ml_scoring": "true" @@ -15197,11 +15236,11 @@ ] }, { - "name": "Enabled_PromotedBy100", + "name": "Enabled_DemotedBy100", "params": { "MlUrlPiecewiseMappedSearchBlending": "true", - "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,550;0.018,1400;0.14,1498;1,1522", - "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1500", + "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,550;0.018,1200;0.14,1298;1,1422", + "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1314", "MlUrlPiecewiseMappedSearchBlending_RelevanceBias": "0", "MlUrlScoringShortcutDocumentSignals": "true", "enable_scoring_signals_annotators_for_ml_scoring": "true" @@ -15213,11 +15252,11 @@ ] }, { - "name": "Enabled_PromotedBy50", + "name": "Enabled_DemotedBy150", "params": { "MlUrlPiecewiseMappedSearchBlending": "true", - "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,550;0.018,1350;0.14,1448;1,1472", - "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1450", + "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,550;0.018,1150;0.14,1248;1,1422", + "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1264", "MlUrlPiecewiseMappedSearchBlending_RelevanceBias": "0", "MlUrlScoringShortcutDocumentSignals": "true", "enable_scoring_signals_annotators_for_ml_scoring": "true" @@ -15272,11 +15311,11 @@ ] }, { - "name": "Enabled_PromotedBy100", + "name": "Enabled_DemotedBy100", "params": { "MlUrlPiecewiseMappedSearchBlending": "true", - "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,590;0.006,890;0.082,1390;0.443,1460;0.464,1500;0.987,1525;1,1530", - "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1514", + "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,590;0.006,690;0.082,1190;0.443,1260;0.464,1300;0.987,1325;1,1530", + "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1314", "MlUrlPiecewiseMappedSearchBlending_RelevanceBias": "0", "MlUrlScoringShortcutDocumentSignals": "true", "MlUrlSearchBlending_MappedSearchBlending": "false", @@ -15289,11 +15328,11 @@ ] }, { - "name": "Enabled_PromotedBy50", + "name": "Enabled_DemotedBy150", "params": { "MlUrlPiecewiseMappedSearchBlending": "true", - "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,590;0.006,840;0.082,1340;0.443,1410;0.464,1450;0.987,1475;1,1530", - "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1464", + "MlUrlPiecewiseMappedSearchBlending_BreakPoints": "0,590;0.006,640;0.082,1140;0.443,1210;0.464,1250;0.987,1275;1,1530", + "MlUrlPiecewiseMappedSearchBlending_GroupingThreshold": "1264", "MlUrlPiecewiseMappedSearchBlending_RelevanceBias": "0", "MlUrlScoringShortcutDocumentSignals": "true", "MlUrlSearchBlending_MappedSearchBlending": "false", @@ -20138,6 +20177,29 @@ ] } ], + "SafeBrowsingHashDatabaseOffsetMap": [ + { + "platforms": [ + "chromeos", + "chromeos_lacros", + "linux", + "mac", + "windows", + "ios" + ], + "experiments": [ + { + "name": "Enabled1024", + "params": { + "HashDatabaseOffsetMapBytesPerOffset": "1024" + }, + "enable_features": [ + "SafeBrowsingHashDatabaseOffsetMap" + ] + } + ] + } + ], "SafeBrowsingHashPrefixRealTimeLookups": [ { "platforms": [ @@ -22602,6 +22664,21 @@ ] } ], + "StructuredMetricsStorageManager": [ + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "EnableStorageManager", + "enable_features": [ + "EventStorageManager" + ] + } + ] + } + ], "SuppressToolbarCaptures": [ { "platforms": [
diff --git a/third_party/android_build_tools/dagger_compiler/.gitignore b/third_party/android_build_tools/dagger_compiler/.gitignore new file mode 100644 index 0000000..a85c0d22 --- /dev/null +++ b/third_party/android_build_tools/dagger_compiler/.gitignore
@@ -0,0 +1 @@ +/cipd/
diff --git a/third_party/android_build_tools/dagger_compiler/3pp/3pp.pb b/third_party/android_build_tools/dagger_compiler/3pp/3pp.pb new file mode 100644 index 0000000..9b805d6 --- /dev/null +++ b/third_party/android_build_tools/dagger_compiler/3pp/3pp.pb
@@ -0,0 +1,22 @@ +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +create { + source { + script { + name: "3pp.py" + use_fetch_checkout_workflow: true + } + } + + build { + install: ["3pp.py", "install"] + tool: "chromium/third_party/maven" + } +} + +upload { + pkg_prefix: "chromium/third_party/android_build_tools" + universal: true +}
diff --git a/third_party/android_build_tools/dagger_compiler/3pp/3pp.py b/third_party/android_build_tools/dagger_compiler/3pp/3pp.py new file mode 100755 index 0000000..a7908c7 --- /dev/null +++ b/third_party/android_build_tools/dagger_compiler/3pp/3pp.py
@@ -0,0 +1,18 @@ +#!/usr/bin/env python3 +# Copyright 2024 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import pathlib +import sys + +# Outside docker: //path/to/project/3pp/fetch.py +# Inside docker: //path/to/project/install.py +_THIS_DIR = pathlib.Path(__file__).resolve().parent +_SRC_ROOT = _THIS_DIR.parents[3 if _THIS_DIR.name == '3pp' else 2] + +sys.path.insert(1, str(_SRC_ROOT / 'build' / '3pp_common')) +import maven + + +maven.main(package='com.google.dagger:dagger-compiler', maven_url=maven.APACHE_MAVEN_URL)
diff --git a/third_party/android_build_tools/dagger_compiler/LICENSE b/third_party/android_build_tools/dagger_compiler/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/third_party/android_build_tools/dagger_compiler/LICENSE
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
diff --git a/third_party/android_build_tools/dagger_compiler/OWNERS b/third_party/android_build_tools/dagger_compiler/OWNERS new file mode 100644 index 0000000..a74cfbe --- /dev/null +++ b/third_party/android_build_tools/dagger_compiler/OWNERS
@@ -0,0 +1 @@ +file://build/android/OWNERS
diff --git a/third_party/android_build_tools/dagger_compiler/README.chromium b/third_party/android_build_tools/dagger_compiler/README.chromium new file mode 100644 index 0000000..34ea4ca --- /dev/null +++ b/third_party/android_build_tools/dagger_compiler/README.chromium
@@ -0,0 +1,16 @@ +Name: Dagger +Short Name: Dagger +Version: 2.52 +License: Apache Version 2.0 +License File: LICENSE +Security Critical: No +Shipped: no +URL: https://github.com/google/dagger + +Description: +Dagger is a fast dependency injector for Android and Java. This module contains +the Java annotation processor, and the Dagger runtime is managed via +//third_party/android_deps. + +Local Modifications: +None
diff --git a/third_party/android_deps/build.gradle b/third_party/android_deps/build.gradle index 96cf692..c3ae9f3 100644 --- a/third_party/android_deps/build.gradle +++ b/third_party/android_deps/build.gradle
@@ -135,7 +135,7 @@ buildCompile "com.google.guava:guava:32.1.3-jre" String daggerVersion = '2.30' - compile "com.google.dagger:dagger:${daggerVersion}" + compile "com.google.dagger:dagger:2.52" buildCompile "com.google.dagger:dagger-compiler:${daggerVersion}" // Matches version depended on by Dagger.
diff --git a/third_party/android_deps/libs/com_google_dagger_dagger/README.chromium b/third_party/android_deps/libs/com_google_dagger_dagger/README.chromium index 52be280..36f4530b 100644 --- a/third_party/android_deps/libs/com_google_dagger_dagger/README.chromium +++ b/third_party/android_deps/libs/com_google_dagger_dagger/README.chromium
@@ -1,7 +1,7 @@ Name: Dagger Short Name: dagger URL: https://github.com/google/dagger -Version: 2.30 +Version: 2.52 License: Apache 2.0 License File: LICENSE CPEPrefix: unknown
diff --git a/third_party/android_deps/libs/com_google_dagger_dagger/cipd.yaml b/third_party/android_deps/libs/com_google_dagger_dagger/cipd.yaml index 7264a78..8426901 100644 --- a/third_party/android_deps/libs/com_google_dagger_dagger/cipd.yaml +++ b/third_party/android_deps/libs/com_google_dagger_dagger/cipd.yaml
@@ -3,8 +3,8 @@ # found in the LICENSE file. # To create CIPD package run the following command. -# cipd create --pkg-def cipd.yaml -tag version:2@2.30.cr1 +# cipd create --pkg-def cipd.yaml -tag version:2@2.52.cr1 package: chromium/third_party/android_deps/libs/com_google_dagger_dagger description: "Dagger" data: -- file: dagger-2.30.jar +- file: dagger-2.52.jar
diff --git a/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/README.chromium b/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/README.chromium index df0655db..636fe81f 100644 --- a/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/README.chromium +++ b/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/README.chromium
@@ -1,7 +1,7 @@ Name: error-prone annotations Short Name: error_prone_annotations URL: https://github.com/google/error-prone/tree/master/annotations -Version: 2.23.0 +Version: 2.30.0 License: Apache 2.0 License File: LICENSE CPEPrefix: unknown
diff --git a/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/cipd.yaml b/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/cipd.yaml index a75d354..1af33df 100644 --- a/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/cipd.yaml +++ b/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations/cipd.yaml
@@ -3,8 +3,8 @@ # found in the LICENSE file. # To create CIPD package run the following command. -# cipd create --pkg-def cipd.yaml -tag version:2@2.23.0.cr1 +# cipd create --pkg-def cipd.yaml -tag version:2@2.30.0.cr1 package: chromium/third_party/android_deps/libs/com_google_errorprone_error_prone_annotations description: "error-prone annotations" data: -- file: error_prone_annotations-2.23.0.jar +- file: error_prone_annotations-2.30.0.jar
diff --git a/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/3pp/3pp.pb b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/3pp/3pp.pb new file mode 100644 index 0000000..d743b51b --- /dev/null +++ b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/3pp/3pp.pb
@@ -0,0 +1,16 @@ +# Copyright 2021 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This is generated, do not edit. Update BuildConfigGenerator.groovy instead. + +create { + source { + script { name: "fetch.py" } + } +} + +upload { + pkg_prefix: "chromium/third_party/android_deps/libs" + universal: true +}
diff --git a/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/3pp/fetch.py b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/3pp/fetch.py new file mode 100755 index 0000000..204dd8d9 --- /dev/null +++ b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/3pp/fetch.py
@@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +# Copyright 2021 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# This is generated, do not edit. Update BuildConfigGenerator.groovy and +# 3ppFetch.template instead. + +import pathlib +import sys + +_3PP_DIR = pathlib.Path(__file__).resolve().parent +sys.path.insert(0, str(_3PP_DIR.parents[2])) +import fetch_common + +_REPO_URL = 'https://repo.maven.apache.org/maven2' +SPEC = fetch_common.Spec(repo_url=_REPO_URL, + group_name='jakarta/inject', + module_name='jakarta.inject-api', + file_ext='jar', + patch_version='cr1', + version_override=None, + version_filter=None) + + +if __name__ == '__main__': + fetch_common.main(SPEC)
diff --git a/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/LICENSE b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/LICENSE new file mode 100644 index 0000000..d645695 --- /dev/null +++ b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/LICENSE
@@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License.
diff --git a/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/OWNERS b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/OWNERS new file mode 100644 index 0000000..aea47a05 --- /dev/null +++ b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/OWNERS
@@ -0,0 +1 @@ +file://third_party/android_deps/OWNERS
diff --git a/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/README.chromium b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/README.chromium new file mode 100644 index 0000000..6447e96 --- /dev/null +++ b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/README.chromium
@@ -0,0 +1,15 @@ +Name: Jakarta Dependency Injection +Short Name: jakarta.inject-api +URL: https://github.com/eclipse-ee4j/injection-api +Version: 2.0.1 +License: Apache Version 2.0 +License File: LICENSE +CPEPrefix: unknown +Security Critical: yes +Shipped: yes + +Description: +Jakarta Dependency Injection + +Local Modifications: +No modifications.
diff --git a/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/cipd.yaml b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/cipd.yaml new file mode 100644 index 0000000..8590de28 --- /dev/null +++ b/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api/cipd.yaml
@@ -0,0 +1,10 @@ +# Copyright 2018 The Chromium Authors +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +# To create CIPD package run the following command. +# cipd create --pkg-def cipd.yaml -tag version:2@2.0.1.cr1 +package: chromium/third_party/android_deps/libs/jakarta_inject_jakarta_inject_api +description: "Jakarta Dependency Injection" +data: +- file: jakarta.inject-api-2.0.1.jar
diff --git a/third_party/angle b/third_party/angle index f259487..24a3d30d 160000 --- a/third_party/angle +++ b/third_party/angle
@@ -1 +1 @@ -Subproject commit f25948774f7c24ef4d28c42cb0fee0e69aac0489 +Subproject commit 24a3d30d02ff37aa148f9ff41e3200bc66865b50
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl index d22f6fe0..15de6246 100644 --- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl +++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
@@ -9220,6 +9220,13 @@ # A new frame target will be created (see Target.attachedToTarget). swap + # Fired before frame subtree is detached. Emitted before any frame of the + # subtree is actually detached. + experimental event frameSubtreeWillBeDetached + parameters + # Id of the frame that is the root of the subtree that will be detached. + FrameId frameId + # The type of a frameNavigated event. experimental type NavigationType extends string enum
diff --git a/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom b/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom index ce915b4..1e49f81 100644 --- a/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom +++ b/third_party/blink/public/mojom/bluetooth/web_bluetooth.mojom
@@ -77,6 +77,8 @@ CONNECT_JNI_ENVIRONMENT, CONNECT_JNI_THREAD_ATTACH, CONNECT_WAKELOCK, + CONNECT_UNEXPECTED_STATE, + CONNECT_SOCKET_ERROR, // NotFoundError: NO_BLUETOOTH_ADAPTER, CHOSEN_DEVICE_VANISHED,
diff --git a/third_party/blink/public/web/web_performance_metrics_for_reporting.h b/third_party/blink/public/web/web_performance_metrics_for_reporting.h index 923f9e53..ef6af4cb 100644 --- a/third_party/blink/public/web/web_performance_metrics_for_reporting.h +++ b/third_party/blink/public/web/web_performance_metrics_for_reporting.h
@@ -36,8 +36,6 @@ uint64_t text_paint_size = 0; base::TimeTicks paint_time = base::TimeTicks(); std::optional<WebURLRequest::Priority> image_request_priority = std::nullopt; - bool is_loaded_from_memory_cache = false; - bool is_preloaded_with_early_hints = false; // The unclamped paint time of the largest content (image/text). std::optional<base::TimeTicks> merged_unclamped_paint_time = std::nullopt; };
diff --git a/third_party/blink/renderer/bindings/generated_in_core.gni b/third_party/blink/renderer/bindings/generated_in_core.gni index c1ebf9a9..d03560f 100644 --- a/third_party/blink/renderer/bindings/generated_in_core.gni +++ b/third_party/blink/renderer/bindings/generated_in_core.gni
@@ -68,6 +68,8 @@ "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_performance_observer_callback.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_predicate.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_predicate.h", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_reducer.cc", + "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_reducer.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_reporting_observer_callback.cc", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_reporting_observer_callback.h", "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_resize_observer_callback.cc",
diff --git a/third_party/blink/renderer/core/dom/child_frame_disconnector.cc b/third_party/blink/renderer/core/dom/child_frame_disconnector.cc index bf3441a6..2a9812f 100644 --- a/third_party/blink/renderer/core/dom/child_frame_disconnector.cc +++ b/third_party/blink/renderer/core/dom/child_frame_disconnector.cc
@@ -6,6 +6,7 @@ #include "third_party/blink/renderer/core/dom/shadow_root.h" #include "third_party/blink/renderer/core/html/html_frame_owner_element.h" +#include "third_party/blink/renderer/core/probe/core_probes.h" namespace blink { @@ -54,8 +55,15 @@ HTMLFrameOwnerElement* owner = frame_owners_[i].Get(); // Don't need to traverse up the tree for the first owner since no // script could have moved it. - if (!i || Root().IsShadowIncludingInclusiveAncestorOf(*owner)) + if (!i || Root().IsShadowIncludingInclusiveAncestorOf(*owner)) { + if (disconnect_reason_ == kDisconnectSelf) { + // Emit `FrameSubtreeWillBeDetached` only for the top of subtree before + // disconnecting the subtree. + probe::FrameSubtreeWillBeDetached(owner->GetDocument().GetFrame(), + owner->ContentFrame()); + } owner->DisconnectContentFrame(); + } } }
diff --git a/third_party/blink/renderer/core/dom/child_frame_disconnector.h b/third_party/blink/renderer/core/dom/child_frame_disconnector.h index 02c1364..23c4b00 100644 --- a/third_party/blink/renderer/core/dom/child_frame_disconnector.h +++ b/third_party/blink/renderer/core/dom/child_frame_disconnector.h
@@ -19,8 +19,11 @@ public: enum DisconnectPolicy { kRootAndDescendants, kDescendantsOnly }; + enum DisconnectReason { kDisconnectParent, kDisconnectSelf }; - explicit ChildFrameDisconnector(Node& root) : root_(&root) {} + explicit ChildFrameDisconnector(Node& root, + DisconnectReason disconnect_reason) + : root_(&root), disconnect_reason_(disconnect_reason) {} void Disconnect(DisconnectPolicy = kRootAndDescendants); @@ -31,6 +34,7 @@ HeapVector<Member<HTMLFrameOwnerElement>, 10> frame_owners_; Node* root_; + DisconnectReason disconnect_reason_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/dom/container_node.cc b/third_party/blink/renderer/core/dom/container_node.cc index e660707f..498470b 100644 --- a/third_party/blink/renderer/core/dom/container_node.cc +++ b/third_party/blink/renderer/core/dom/container_node.cc
@@ -658,7 +658,9 @@ // above. // // CHECK_EQ(GetDocument(), child.GetDocument()); - ChildFrameDisconnector(child).Disconnect(); + ChildFrameDisconnector( + child, ChildFrameDisconnector::DisconnectReason::kDisconnectSelf) + .Disconnect(); } if (GetDocument() != child.GetDocument()) { @@ -694,8 +696,9 @@ } CHECK(!GetDocument().StatePreservingAtomicMoveInProgress()); - ChildFrameDisconnector(*this).Disconnect( - ChildFrameDisconnector::kDescendantsOnly); + ChildFrameDisconnector( + *this, ChildFrameDisconnector::DisconnectReason::kDisconnectSelf) + .Disconnect(ChildFrameDisconnector::kDescendantsOnly); } LayoutBox* ContainerNode::GetLayoutBoxForScrolling() const { @@ -855,9 +858,11 @@ // This may cause arbitrary Javascript execution via onunload handlers. CHECK(!GetDocument().StatePreservingAtomicMoveInProgress()); - if (old_child.ConnectedSubframeCount()) - ChildFrameDisconnector(old_child).Disconnect(); - + if (old_child.ConnectedSubframeCount()) { + ChildFrameDisconnector( + old_child, ChildFrameDisconnector::DisconnectReason::kDisconnectSelf) + .Disconnect(); + } if (old_child.parentNode() != this) return;
diff --git a/third_party/blink/renderer/core/dom/observable.cc b/third_party/blink/renderer/core/dom/observable.cc index d3b8a752..9d186e1 100644 --- a/third_party/blink/renderer/core/dom/observable.cc +++ b/third_party/blink/renderer/core/dom/observable.cc
@@ -15,6 +15,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_observer_callback.h" #include "third_party/blink/renderer/bindings/core/v8/v8_observer_complete_callback.h" #include "third_party/blink/renderer/bindings/core/v8/v8_predicate.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_reducer.h" #include "third_party/blink/renderer/bindings/core/v8/v8_subscribe_callback.h" #include "third_party/blink/renderer/bindings/core/v8/v8_subscribe_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_observableinspector_observercallback.h" @@ -156,6 +157,106 @@ Member<AbortSignal::AlgorithmHandle> abort_algorithm_handle_; }; +// This is the internal observer associated with the `reduce()` operator. See +// https://wicg.github.io/observable/#dom-observable-reduce for its definition +// and spec prose. +class OperatorReduceInternalObserver final : public ObservableInternalObserver { + public: + OperatorReduceInternalObserver(ScriptPromiseResolver<IDLAny>* resolver, + AbortController* controller, + V8Reducer* reducer, + std::optional<ScriptValue> initial_value, + AbortSignal::AlgorithmHandle* handle) + : resolver_(resolver), + controller_(controller), + reducer_(reducer), + abort_algorithm_handle_(handle) { + CHECK(resolver_); + CHECK(controller_); + CHECK(reducer_); + CHECK(abort_algorithm_handle_); + if (initial_value) { + accumulator_ = MakeGarbageCollected<ScriptValueHolder>(*initial_value); + } + } + + void Next(ScriptValue value) override { + if (!accumulator_) [[unlikely]] { + // For all subsequent values, we will take the path where `accumulator_` + // is *not* null, and we invoke `reducer_` with it. + accumulator_ = MakeGarbageCollected<ScriptValueHolder>(value); + // Adjust the index, so that when we first call `reducer_` on the *second* + // value, the index is adjusted accordingly. + idx_++; + return; + } + + // `ScriptState::Scope` can only be created in a valid context, so + // early-return if we're in a detached one. + ScriptState* script_state = resolver_->GetScriptState(); + if (!script_state->ContextIsValid()) { + return; + } + + ScriptState::Scope scope(script_state); + v8::TryCatch try_catch(script_state->GetIsolate()); + const v8::Maybe<ScriptValue> result = reducer_->Invoke( + /*thisArg=*/nullptr, /*accumulator=*/accumulator_->Value(), + /*currentValue=*/value, /*index=*/idx_++); + if (try_catch.HasCaught()) { + abort_algorithm_handle_.Clear(); + ScriptValue exception(script_state->GetIsolate(), try_catch.Exception()); + resolver_->Reject(exception); + controller_->abort(script_state, exception); + return; + } + + // Since we handled the exception case above, `result` must not be + // `v8::Nothing`. + accumulator_ = MakeGarbageCollected<ScriptValueHolder>(result.ToChecked()); + } + + void Error(ScriptState* script_state, ScriptValue error_value) override { + abort_algorithm_handle_.Clear(); + + resolver_->Reject(error_value); + } + void Complete() override { + abort_algorithm_handle_.Clear(); + + if (accumulator_) { + resolver_->Resolve(accumulator_->Value()); + } else { + v8::Isolate* isolate = resolver_->GetScriptState()->GetIsolate(); + resolver_->Reject(V8ThrowException::CreateTypeError( + isolate, "Reduce of empty array with no initial value")); + } + } + + void Trace(Visitor* visitor) const override { + ObservableInternalObserver::Trace(visitor); + + visitor->Trace(resolver_); + visitor->Trace(controller_); + visitor->Trace(reducer_); + visitor->Trace(accumulator_); + visitor->Trace(abort_algorithm_handle_); + } + + private: + uint64_t idx_ = 0; + Member<ScriptPromiseResolver<IDLAny>> resolver_; + Member<AbortController> controller_; + Member<V8Reducer> reducer_; + // `accumulator_` is initually null unless `initialValue` is passed into the + // constructor of `this`. When `accumulator_` is initially null, we eventually + // set it to the first value that `this` encounters in `Next()`. Then, for all + // subsequent values, we use `accumulator_` as the "accumulator" argument for + // `reducer_` callback above. + Member<ScriptValueHolder> accumulator_; + Member<AbortSignal::AlgorithmHandle> abort_algorithm_handle_; +}; + // This is the internal observer associated with the `find()` operator. See // https://wicg.github.io/observable/#dom-observable-find for its definition // and spec prose quoted below. @@ -2454,6 +2555,62 @@ return promise; } +ScriptPromise<IDLAny> Observable::reduce(ScriptState* script_state, + V8Reducer* reducer) { + return ReduceInternal(script_state, reducer, std::nullopt, + MakeGarbageCollected<SubscribeOptions>()); +} + +ScriptPromise<IDLAny> Observable::reduce(ScriptState* script_state, + V8Reducer* reducer, + v8::Local<v8::Value> initialValue, + SubscribeOptions* options) { + DCHECK(options); + return ReduceInternal( + script_state, reducer, + std::make_optional(ScriptValue(script_state->GetIsolate(), initialValue)), + options); +} + +ScriptPromise<IDLAny> Observable::ReduceInternal( + ScriptState* script_state, + V8Reducer* reducer, + std::optional<ScriptValue> initial_value, + SubscribeOptions* options) { + ScriptPromiseResolver<IDLAny>* resolver = + MakeGarbageCollected<ScriptPromiseResolver<IDLAny>>(script_state); + ScriptPromise<IDLAny> promise = resolver->Promise(); + + AbortController* controller = AbortController::Create(script_state); + HeapVector<Member<AbortSignal>> signals; + signals.push_back(controller->signal()); + if (options->hasSignal()) { + signals.push_back(options->signal()); + } + + SubscribeOptions* internal_options = MakeGarbageCollected<SubscribeOptions>(); + internal_options->setSignal( + MakeGarbageCollected<AbortSignal>(script_state, signals)); + + if (internal_options->signal()->aborted()) { + resolver->Reject(options->signal()->reason(script_state)); + return promise; + } + + AbortSignal::AlgorithmHandle* algorithm_handle = + internal_options->signal()->AddAlgorithm( + MakeGarbageCollected<RejectPromiseAbortAlgorithm>( + resolver, internal_options->signal())); + + OperatorReduceInternalObserver* internal_observer = + MakeGarbageCollected<OperatorReduceInternalObserver>( + resolver, controller, reducer, initial_value, algorithm_handle); + SubscribeInternal(script_state, /*observer_union=*/nullptr, internal_observer, + internal_options); + + return promise; +} + void Observable::Trace(Visitor* visitor) const { visitor->Trace(subscribe_callback_); visitor->Trace(subscribe_delegate_);
diff --git a/third_party/blink/renderer/core/dom/observable.h b/third_party/blink/renderer/core/dom/observable.h index a64dfa5..e5e31c6 100644 --- a/third_party/blink/renderer/core/dom/observable.h +++ b/third_party/blink/renderer/core/dom/observable.h
@@ -5,6 +5,8 @@ #ifndef THIRD_PARTY_BLINK_RENDERER_CORE_DOM_OBSERVABLE_H_ #define THIRD_PARTY_BLINK_RENDERER_CORE_DOM_OBSERVABLE_H_ +#include <optional> + #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" @@ -19,6 +21,7 @@ class SubscribeOptions; class V8Mapper; class V8Predicate; +class V8Reducer; class V8SubscribeCallback; class V8UnionObservableInspectorOrObserverCallback; class V8UnionObserverOrObserverCallback; @@ -90,6 +93,11 @@ V8Predicate*, SubscribeOptions*); ScriptPromise<IDLAny> find(ScriptState*, V8Predicate*, SubscribeOptions*); + ScriptPromise<IDLAny> reduce(ScriptState*, V8Reducer*); + ScriptPromise<IDLAny> reduce(ScriptState*, + V8Reducer*, + v8::Local<v8::Value>, + SubscribeOptions*); void Trace(Visitor*) const override; @@ -103,6 +111,12 @@ SubscribeOptions*); private: + // Used by both overloads of `reduce()`. + ScriptPromise<IDLAny> ReduceInternal(ScriptState*, + V8Reducer*, + std::optional<ScriptValue>, + SubscribeOptions*); + // The `ScriptState` argument does not need to be associated with a valid // context (this method early-returns in that case). void SubscribeInternal(ScriptState*,
diff --git a/third_party/blink/renderer/core/dom/observable.idl b/third_party/blink/renderer/core/dom/observable.idl index 14bd2d42..a066e09 100644 --- a/third_party/blink/renderer/core/dom/observable.idl +++ b/third_party/blink/renderer/core/dom/observable.idl
@@ -8,6 +8,7 @@ callback ObserverCallback = void (any value); callback ObserverCompleteCallback = void (); +callback Reducer = any (any accumulator, any currentValue, unsigned long long index); callback Mapper = any (any element, unsigned long long index); // Differs from Mapper only in return type, since this callback is exclusively @@ -72,5 +73,6 @@ [CallWith=ScriptState] Promise<boolean> some(Predicate predicate, optional SubscribeOptions options = {}); [CallWith=ScriptState] Promise<boolean> every(Predicate predicate, optional SubscribeOptions options = {}); [CallWith=ScriptState] Promise<any> find(Predicate predicate, optional SubscribeOptions options = {}); + [CallWith=ScriptState] Promise<any> reduce(Reducer reducer, optional any initialValue, optional SubscribeOptions options = {}); };
diff --git a/third_party/blink/renderer/core/fetch/fetch_manager.cc b/third_party/blink/renderer/core/fetch/fetch_manager.cc index 7af782f..782f2da 100644 --- a/third_party/blink/renderer/core/fetch/fetch_manager.cc +++ b/third_party/blink/renderer/core/fetch/fetch_manager.cc
@@ -244,6 +244,22 @@ // TODO(crbug.com/1465781): Apply kLow when IsSubframeDeprioritizationEnabled. } +class FetchManagerResourceRequestContext final : public ResourceRequestContext { + STACK_ALLOCATED(); + + public: + ~FetchManagerResourceRequestContext() override = default; + + // Computes the ResourceLoadPriority. This is called if the priority was not + // set. + ResourceLoadPriority ComputeLoadPriority( + const FetchParameters& params) override { + return ComputeFetchLaterLoadPriority(params); + } + + void RecordTrace() override {} +}; + } // namespace // FetchLoaderBase provides common logic to prepare a blink::ResourceRequest @@ -1782,25 +1798,25 @@ const FetchClientSettingsObject& fetch_client_settings_object = fetcher->GetProperties().GetFetchClientSettingsObject(); + FetchManagerResourceRequestContext resource_request_context; if (!RuntimeEnabledFeatures:: MinimimalResourceRequestPrepBeforeCacheLookupEnabled()) { - if (PrepareResourceRequest(kFetchLaterResourceType, - fetch_client_settings_object, params, - fetcher->Context(), unused_virtual_time_pauser, - WTF::BindOnce(&ComputeFetchLaterLoadPriority), - base::NullCallback(), KURL()) != std::nullopt) { + if (PrepareResourceRequest( + kFetchLaterResourceType, fetch_client_settings_object, params, + fetcher->Context(), unused_virtual_time_pauser, + resource_request_context, KURL()) != std::nullopt) { return nullptr; } } else { if (PrepareResourceRequestForCacheAccess( kFetchLaterResourceType, fetch_client_settings_object, KURL(), - WTF::BindOnce(&ComputeFetchLaterLoadPriority), fetcher->Context(), + resource_request_context, fetcher->Context(), params) != std::nullopt) { return nullptr; } UpgradeResourceRequestForLoaderNew( kFetchLaterResourceType, params, fetcher->Context(), - unused_virtual_time_pauser, base::NullCallback()); + resource_request_context, unused_virtual_time_pauser); } // From `ResourceFetcher::StartLoad()`:
diff --git a/third_party/blink/renderer/core/fileapi/file_reader_loader.cc b/third_party/blink/renderer/core/fileapi/file_reader_loader.cc index 52ffd34..0d01fef 100644 --- a/third_party/blink/renderer/core/fileapi/file_reader_loader.cc +++ b/third_party/blink/renderer/core/fileapi/file_reader_loader.cc
@@ -197,7 +197,11 @@ void FileReaderLoader::OnDataPipeReadable(MojoResult result) { if (result != MOJO_RESULT_OK) { - if (!received_all_data_) { + if (!received_all_data_ && result != MOJO_RESULT_FAILED_PRECONDITION) { + // Whatever caused a `MOJO_RESULT_FAILED_PRECONDITION` will also prevent + // `BlobDataHandle` from writing to the pipe, so we expect a call to + // `OnComplete()` soon with a more specific error that we will then pass + // to the client. base::UmaHistogramExactLinear( "Storage.Blob.FileReaderLoader.DataPipeNotReadableMojoError", result, MOJO_RESULT_SHOULD_WAIT + 1);
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index 042a057..ad70aef6 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -928,7 +928,10 @@ bool LocalFrame::DetachChildren() { DCHECK(GetDocument()); - ChildFrameDisconnector(*GetDocument()).Disconnect(); + ChildFrameDisconnector( + *GetDocument(), + ChildFrameDisconnector::DisconnectReason::kDisconnectParent) + .Disconnect(); return !!Client(); }
diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc index 7bea44002..e3da0d0 100644 --- a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
@@ -1166,6 +1166,11 @@ FrameDetachTypeToProtocol(type)); } +void InspectorPageAgent::FrameSubtreeWillBeDetached(Frame* frame) { + GetFrontend()->frameSubtreeWillBeDetached(IdentifiersFactory::FrameId(frame)); + GetFrontend()->flush(); +} + bool InspectorPageAgent::ScreencastEnabled() { return enabled_.Get() && screencast_enabled_.Get(); }
diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.h b/third_party/blink/renderer/core/inspector/inspector_page_agent.h index 58fa858..4cc2438 100644 --- a/third_party/blink/renderer/core/inspector/inspector_page_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.h
@@ -230,6 +230,7 @@ LocalFrame*, const std::optional<AdScriptIdentifier>& ad_script_on_stack); void FrameDetachedFromParent(LocalFrame*, FrameDetachType); + void FrameSubtreeWillBeDetached(Frame* frame); void FrameStoppedLoading(LocalFrame*); void FrameRequestedNavigation(Frame* target_frame, const KURL&,
diff --git a/third_party/blink/renderer/core/layout/block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/block_layout_algorithm.cc index a794bce0..1022b24 100644 --- a/third_party/blink/renderer/core/layout/block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/block_layout_algorithm.cc
@@ -1385,10 +1385,9 @@ const InlineBreakToken** inline_break_token_out) { DCHECK(previous_result_); - // No lines are reusable if this block uses `NGParagraphLineBreaker`. - // TODO(kojii): This should include other non-stable values; i.e. - // `if (!Style().ShouldWrapLineGreedy()) {`. - if (Style().GetTextWrapStyle() == TextWrapStyle::kBalance) { + // No lines are reusable if this block uses paragraph-level line breakers such + // as `ParagraphLineBreaker` or `ScoreLineBreaker`. + if (!Style().ShouldWrapLineGreedy()) { return false; }
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc index a4652e19..9c83a79 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_content.cc +++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.cc
@@ -110,10 +110,7 @@ ImageResource* resource = ImageResource::Fetch(params, fetcher); if (!resource) return nullptr; - resource->GetContent()->SetIsLoadedFromMemoryCache( - resource->IsLoadedFromMemoryCache()); - resource->GetContent()->SetIsPreloadedWithEarlyHints( - resource->IsPreloadedByEarlyHints()); + return resource->GetContent(); }
diff --git a/third_party/blink/renderer/core/loader/resource/image_resource_content.h b/third_party/blink/renderer/core/loader/resource/image_resource_content.h index abcd2fa..0a42b0b 100644 --- a/third_party/blink/renderer/core/loader/resource/image_resource_content.h +++ b/third_party/blink/renderer/core/loader/resource/image_resource_content.h
@@ -230,22 +230,6 @@ // BitmapImage. |use_counter| may be a null pointer. void RecordDecodedImageType(UseCounter* use_counter); - void SetIsLoadedFromMemoryCache(bool is_loaded_from_memory_cache) { - is_loaded_from_memory_cache_ = is_loaded_from_memory_cache; - } - - void SetIsPreloadedWithEarlyHints(bool is_preloaded_with_early_hints) { - is_preloaded_with_early_hints_ = is_preloaded_with_early_hints; - } - - bool IsLoadedFromMemoryCache() const override { - return is_loaded_from_memory_cache_; - } - - bool IsPreloadedWithEarlyHints() const override { - return is_preloaded_with_early_hints_; - } - void SetAllocatedExternalMemory() { allocated_external_memory_ = true; } private: @@ -302,10 +286,6 @@ bool is_broken_ = false; - bool is_loaded_from_memory_cache_ = false; - - bool is_preloaded_with_early_hints_ = false; - #if DCHECK_IS_ON() bool is_update_image_being_called_ = false; #endif
diff --git a/third_party/blink/renderer/core/loader/resource/video_timing.h b/third_party/blink/renderer/core/loader/resource/video_timing.h index 29889d04..bb7d83d 100644 --- a/third_party/blink/renderer/core/loader/resource/video_timing.h +++ b/third_party/blink/renderer/core/loader/resource/video_timing.h
@@ -76,10 +76,6 @@ base::TimeTicks DiscoveryTime() const override { return base::TimeTicks(); } - bool IsLoadedFromMemoryCache() const override { return false; } - - bool IsPreloadedWithEarlyHints() const override { return false; } - private: KURL url_; bool is_loaded_ = false;
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc index fb4569df..0ddae9e 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area.cc
@@ -1319,8 +1319,7 @@ } bool PaintLayerScrollableArea::IsGlobalRootNonOverlayScroller() const { - return RuntimeEnabledFeatures::UsedColorSchemeRootScrollbarsEnabled() && - GetLayoutBox()->IsGlobalRootScroller() && + return GetLayoutBox()->IsGlobalRootScroller() && !GetPageScrollbarTheme().UsesOverlayScrollbars(); }
diff --git a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc index 2d221d6..113d42c 100644 --- a/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc +++ b/third_party/blink/renderer/core/paint/paint_layer_scrollable_area_test.cc
@@ -1650,13 +1650,8 @@ mojom::blink::PreferredColorScheme::kDark); UpdateAllLifecyclePhasesForTest(); - if (RuntimeEnabledFeatures::UsedColorSchemeRootScrollbarsEnabled()) { - EXPECT_EQ(root_scrollable_area->UsedColorSchemeScrollbars(), - mojom::blink::ColorScheme::kDark); - } else { - EXPECT_EQ(root_scrollable_area->UsedColorSchemeScrollbars(), - mojom::blink::ColorScheme::kLight); - } + EXPECT_EQ(root_scrollable_area->UsedColorSchemeScrollbars(), + mojom::blink::ColorScheme::kDark); EXPECT_EQ(non_root_scrollable_area_dark->UsedColorSchemeScrollbars(), mojom::blink::ColorScheme::kDark); EXPECT_EQ(non_root_scrollable_area_normal->UsedColorSchemeScrollbars(), @@ -1806,11 +1801,7 @@ // Root scrollbars should be set for invalidation after the color scheme // change. - if (RuntimeEnabledFeatures::UsedColorSchemeRootScrollbarsEnabled()) { - ExpectEqAllScrollControlsNeedPaintInvalidation(root_scrollable_area, true); - } else { - ExpectEqAllScrollControlsNeedPaintInvalidation(root_scrollable_area, false); - } + ExpectEqAllScrollControlsNeedPaintInvalidation(root_scrollable_area, true); // Non root scrollbars should not change. ExpectEqAllScrollControlsNeedPaintInvalidation(non_root_scrollable_area, @@ -1858,23 +1849,14 @@ // Root scrollbars should be set for invalidation after the color scheme // change. - if (RuntimeEnabledFeatures::UsedColorSchemeRootScrollbarsEnabled()) { - ExpectEqAllScrollControlsNeedPaintInvalidation(root_scrollable_area, true); - } else { - ExpectEqAllScrollControlsNeedPaintInvalidation(root_scrollable_area, false); - } + ExpectEqAllScrollControlsNeedPaintInvalidation(root_scrollable_area, true); // Non root scrollbars should not change. ExpectEqAllScrollControlsNeedPaintInvalidation(non_root_scrollable_area, false); - if (RuntimeEnabledFeatures::UsedColorSchemeRootScrollbarsEnabled()) { - EXPECT_EQ(root_scrollable_area->UsedColorSchemeScrollbars(), - mojom::blink::ColorScheme::kDark); - } else { - EXPECT_EQ(root_scrollable_area->UsedColorSchemeScrollbars(), - mojom::blink::ColorScheme::kLight); - } + EXPECT_EQ(root_scrollable_area->UsedColorSchemeScrollbars(), + mojom::blink::ColorScheme::kDark); } TEST_P(PaintLayerScrollableAreaTest, @@ -1897,9 +1879,8 @@ UpdateAllLifecyclePhasesForTest(); root_scrollable_area->UsedColorSchemeScrollbars(); - EXPECT_EQ(GetDocument().IsUseCounted( - WebFeature::kUsedColorSchemeRootScrollbarsDark), - RuntimeEnabledFeatures::UsedColorSchemeRootScrollbarsEnabled()); + EXPECT_TRUE(GetDocument().IsUseCounted( + WebFeature::kUsedColorSchemeRootScrollbarsDark)); } // TODO(crbug.com/1020913): Actually this tests a situation that should not
diff --git a/third_party/blink/renderer/core/paint/theme_painter.cc b/third_party/blink/renderer/core/paint/theme_painter.cc index efa439e..3b2ef2b 100644 --- a/third_party/blink/renderer/core/paint/theme_painter.cc +++ b/third_party/blink/renderer/core/paint/theme_painter.cc
@@ -240,7 +240,20 @@ return false; case kBaseSelectPart: return true; - default: + case kNoControlPart: + case kAutoPart: + // kNoControlPart isn't possible because callers should only call this + // function when HasEffectiveAppearance is true. + // kAutoPart isn't possible because it can't be an effective appearance. + NOTREACHED(); + // TODO(dbaron): The following values were previously covered by a + // default: case and should be classified correctly: + case kMediaControlPart: + case kMeterPart: + case kMediaSliderPart: + case kMediaSliderThumbPart: + case kMediaVolumeSliderPart: + case kMediaVolumeSliderThumbPart: UseCounter::Count( element.GetDocument(), WebFeature::kCSSValueAppearanceNoImplementationSkipBorder);
diff --git a/third_party/blink/renderer/core/paint/timing/largest_contentful_paint_calculator.cc b/third_party/blink/renderer/core/paint/timing/largest_contentful_paint_calculator.cc index 73986fa..e967d59 100644 --- a/third_party/blink/renderer/core/paint/timing/largest_contentful_paint_calculator.cc +++ b/third_party/blink/renderer/core/paint/timing/largest_contentful_paint_calculator.cc
@@ -284,10 +284,6 @@ image_record->media_timing->LoadStart(); latest_lcp_details_.resource_load_timings.load_end = image_record->media_timing->LoadEnd(); - latest_lcp_details_.is_loaded_from_memory_cache = - image_record->media_timing->IsLoadedFromMemoryCache(); - latest_lcp_details_.is_preloaded_with_early_hints = - image_record->media_timing->IsPreloadedWithEarlyHints(); } } latest_lcp_details_.largest_image_paint_time = image_paint_time;
diff --git a/third_party/blink/renderer/core/paint/timing/lcp_objects.h b/third_party/blink/renderer/core/paint/timing/lcp_objects.h index 7c61acd2..c764102 100644 --- a/third_party/blink/renderer/core/paint/timing/lcp_objects.h +++ b/third_party/blink/renderer/core/paint/timing/lcp_objects.h
@@ -32,8 +32,6 @@ base::TimeTicks largest_contentful_paint_time; std::optional<WebURLRequest::Priority> largest_contentful_paint_image_request_priority = std::nullopt; - bool is_loaded_from_memory_cache = false; - bool is_preloaded_with_early_hints = false; }; // This class is used for tracing only.
diff --git a/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.cc b/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.cc index 353dc85..6f918f1d 100644 --- a/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.cc +++ b/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector.cc
@@ -139,10 +139,6 @@ return false; } - if (RuntimeEnabledFeatures::LCPMultipleUpdatesPerElementEnabled()) { - return true; - } - if (rewalkable_set_.Contains(&object)) return true;
diff --git a/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector_test.cc b/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector_test.cc index c42b094..b03baea 100644 --- a/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector_test.cc +++ b/third_party/blink/renderer/core/paint/timing/text_paint_timing_detector_test.cc
@@ -284,13 +284,12 @@ TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_FontSizeChange_MultipleUpdates) { - ScopedLCPMultipleUpdatesPerElementForTest scoped_lcp_multiple_updates(true); SetBodyInnerHTML(R"HTML()HTML"); Element* text = AppendDivElementToBody("text"); SetElementStyle(text, "font-size: 200px"); UpdateAllLifecyclePhasesAndSimulatePresentationTime(); SetElementStyle(text, "font-size: 300px"); - CheckSizeOfTextQueuedForPaintTimeAfterUpdateLifecyclePhases(1u); + CheckSizeOfTextQueuedForPaintTimeAfterUpdateLifecyclePhases(0u); } TEST_F(TextPaintTimingDetectorTest, LargestTextPaint_TraceEvent_Candidate) {
diff --git a/third_party/blink/renderer/core/probe/core_probes.json5 b/third_party/blink/renderer/core/probe/core_probes.json5 index 8286c47a..a7a60e57 100644 --- a/third_party/blink/renderer/core/probe/core_probes.json5 +++ b/third_party/blink/renderer/core/probe/core_probes.json5
@@ -236,6 +236,7 @@ "FrameAttachedToParent", "FrameClearedScheduledNavigation", "FrameDetachedFromParent", + "FrameSubtreeWillBeDetached", "FrameRequestedNavigation", "FrameScheduledNavigation", "FrameStoppedLoading",
diff --git a/third_party/blink/renderer/core/probe/core_probes.pidl b/third_party/blink/renderer/core/probe/core_probes.pidl index 89adc51..759ab55 100644 --- a/third_party/blink/renderer/core/probe/core_probes.pidl +++ b/third_party/blink/renderer/core/probe/core_probes.pidl
@@ -121,6 +121,7 @@ void LoadEventFired([Keep] LocalFrame*); void FrameAttachedToParent([Keep] LocalFrame*, const std::optional<AdScriptIdentifier>& ad_script_on_stack); void FrameDetachedFromParent([Keep] LocalFrame*, FrameDetachType); + void FrameSubtreeWillBeDetached(LocalFrame*, Frame*); void DidStartProvisionalLoad([Keep] LocalFrame*); void DidFailProvisionalLoad([Keep] LocalFrame*); void WillCommitLoad([Keep] LocalFrame*, DocumentLoader*);
diff --git a/third_party/blink/renderer/core/timing/performance_timing_for_reporting.cc b/third_party/blink/renderer/core/timing/performance_timing_for_reporting.cc index 801c629a5..052d7eb 100644 --- a/third_party/blink/renderer/core/timing/performance_timing_for_reporting.cc +++ b/third_party/blink/renderer/core/timing/performance_timing_for_reporting.cc
@@ -89,8 +89,6 @@ timing.largest_contentful_paint_time, timing.largest_contentful_paint_image_request_priority, - timing.is_loaded_from_memory_cache, - timing.is_preloaded_with_early_hints, merged_unclamped_paint_time}; }
diff --git a/third_party/blink/renderer/core/view_transition/dom_view_transition.cc b/third_party/blink/renderer/core/view_transition/dom_view_transition.cc index a3eaf302..a828965d 100644 --- a/third_party/blink/renderer/core/view_transition/dom_view_transition.cc +++ b/third_party/blink/renderer/core/view_transition/dom_view_transition.cc
@@ -181,6 +181,7 @@ // If the callback couldn't be run for some reason, treat it as an empty // promise rejected with an abort exception. if (result.IsNothing()) { + ScriptState::Scope scope(script_state); auto value = ScriptValue::From( script_state, MakeGarbageCollected<DOMException>( DOMExceptionCode::kAbortError, kAbortedMessage));
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index e674b78..01ab473 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -7732,8 +7732,10 @@ if (ancestor->RoleValue() != ax::mojom::blink::Role::kGenericContainer && ancestor->RoleValue() != ax::mojom::blink::Role::kNone && + ancestor->RoleValue() != ax::mojom::blink::Role::kGroup && ancestor->RoleValue() != ax::mojom::blink::Role::kRowGroup) { - // Not inside a grid or a treegrid, or reached the top of one. + // Any other role other than those that are neutral in a [tree]grid, + // indicate that we are not in a [tree]grid. return false; } ancestor = ancestor->ParentObjectUnignored();
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc index a510ab8..f9d62c3 100644 --- a/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc +++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_error.cc
@@ -238,6 +238,10 @@ "Connection Error: An internal error has occurred."); MAP_ERROR(CONNECT_WAKELOCK, DOMExceptionCode::kUnknownError, "Connection Error: An internal error has occurred."); + MAP_ERROR(CONNECT_UNEXPECTED_STATE, DOMExceptionCode::kUnknownError, + "Connection Error: An internal error has occurred."); + MAP_ERROR(CONNECT_SOCKET_ERROR, DOMExceptionCode::kUnknownError, + "Connection Error: An internal error has occurred."); #undef MAP_ERROR }
diff --git a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_utils.cc b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_utils.cc index e00032d..0d379ee 100644 --- a/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_utils.cc +++ b/third_party/blink/renderer/modules/bluetooth/bluetooth_remote_gatt_utils.cc
@@ -11,8 +11,7 @@ const WTF::Vector<uint8_t>& wtf_vector) { static_assert(sizeof(*wtf_vector.data()) == 1, "uint8_t should be a single byte"); - DOMArrayBuffer* dom_buffer = - DOMArrayBuffer::Create(wtf_vector.data(), wtf_vector.size()); + DOMArrayBuffer* dom_buffer = DOMArrayBuffer::Create(wtf_vector); return DOMDataView::Create(dom_buffer, 0, wtf_vector.size()); }
diff --git a/third_party/blink/renderer/modules/credentialmanagement/authentication_credentials_container.cc b/third_party/blink/renderer/modules/credentialmanagement/authentication_credentials_container.cc index bbca0323..f2fe8dd 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/authentication_credentials_container.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/authentication_credentials_container.cc
@@ -554,8 +554,7 @@ } DOMArrayBuffer* VectorToDOMArrayBuffer(const Vector<uint8_t> buffer) { - return DOMArrayBuffer::Create(static_cast<const void*>(buffer.data()), - buffer.size()); + return DOMArrayBuffer::Create(buffer); } AuthenticationExtensionsPRFValues* GetPRFExtensionResults(
diff --git a/third_party/blink/renderer/modules/credentialmanagement/authenticator_assertion_response.cc b/third_party/blink/renderer/modules/credentialmanagement/authenticator_assertion_response.cc index 5a4cd1b..aac9a64 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/authenticator_assertion_response.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/authenticator_assertion_response.cc
@@ -10,14 +10,6 @@ #include "third_party/blink/renderer/modules/credentialmanagement/json.h" namespace blink { -namespace { - -DOMArrayBuffer* VectorToDOMArrayBuffer(const Vector<uint8_t> buffer) { - return DOMArrayBuffer::Create(static_cast<const void*>(buffer.data()), - buffer.size()); -} - -} // namespace AuthenticatorAssertionResponse::AuthenticatorAssertionResponse( const Vector<uint8_t> client_data_json, @@ -25,11 +17,11 @@ const Vector<uint8_t> signature, const std::optional<Vector<uint8_t>> optional_user_handle) : AuthenticatorAssertionResponse( - VectorToDOMArrayBuffer(client_data_json), - VectorToDOMArrayBuffer(authenticator_data), - VectorToDOMArrayBuffer(signature), + DOMArrayBuffer::Create(client_data_json), + DOMArrayBuffer::Create(authenticator_data), + DOMArrayBuffer::Create(signature), optional_user_handle && optional_user_handle->size() > 0 - ? VectorToDOMArrayBuffer(std::move(*optional_user_handle)) + ? DOMArrayBuffer::Create(std::move(*optional_user_handle)) : nullptr) {} AuthenticatorAssertionResponse::AuthenticatorAssertionResponse(
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc index 8fba45b..e23dc23 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.cc
@@ -190,12 +190,6 @@ return nullptr; } -static blink::DOMArrayBuffer* VectorToDOMArrayBuffer( - const Vector<uint8_t> buffer) { - return blink::DOMArrayBuffer::Create(static_cast<const void*>(buffer.data()), - buffer.size()); -} - #if BUILDFLAG(IS_ANDROID) static Vector<Vector<uint32_t>> UvmEntryToArray( const Vector<blink::mojom::blink::UvmEntryPtr>& user_verification_methods) { @@ -234,7 +228,7 @@ blink::AuthenticationExtensionsLargeBlobOutputs::Create(); if (extensions->large_blob) { large_blob_outputs->setBlob( - VectorToDOMArrayBuffer(std::move(*extensions->large_blob))); + blink::DOMArrayBuffer::Create(std::move(*extensions->large_blob))); } if (extensions->echo_large_blob_written) { large_blob_outputs->setWritten(extensions->large_blob_written); @@ -243,7 +237,7 @@ } if (extensions->get_cred_blob) { extension_outputs->setGetCredBlob( - VectorToDOMArrayBuffer(std::move(*extensions->get_cred_blob))); + blink::DOMArrayBuffer::Create(std::move(*extensions->get_cred_blob))); } if (extensions->supplemental_pub_keys) { extension_outputs->setSupplementalPubKeys( @@ -256,12 +250,12 @@ auto* values = blink::AuthenticationExtensionsPRFValues::Create(); values->setFirst( MakeGarbageCollected<blink::V8UnionArrayBufferOrArrayBufferView>( - VectorToDOMArrayBuffer( + blink::DOMArrayBuffer::Create( std::move(extensions->prf_results->first)))); if (extensions->prf_results->second) { values->setSecond( MakeGarbageCollected<blink::V8UnionArrayBufferOrArrayBufferView>( - VectorToDOMArrayBuffer( + blink::DOMArrayBuffer::Create( std::move(extensions->prf_results->second.value())))); } prf_outputs->setResults(values); @@ -279,7 +273,7 @@ supplemental_pub_keys) { blink::HeapVector<blink::Member<blink::DOMArrayBuffer>> signatures; for (const auto& sig : supplemental_pub_keys->signatures) { - signatures.push_back(VectorToDOMArrayBuffer(std::move(sig))); + signatures.push_back(blink::DOMArrayBuffer::Create(std::move(sig))); } auto* spk_outputs =
diff --git a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters_unittest.cc b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters_unittest.cc index dd197754..c271a07 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters_unittest.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters_unittest.cc
@@ -9,6 +9,8 @@ #include "third_party/blink/renderer/modules/credentialmanagement/credential_manager_type_converters.h" +#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "mojo/public/cpp/bindings/type_converter.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -436,9 +438,9 @@ static blink::V8UnionArrayBufferOrArrayBufferView* arrayBufferOrView( const uint8_t* data, size_t size) { - blink::DOMArrayBuffer* dom_array = blink::DOMArrayBuffer::Create(data, size); return blink::MakeGarbageCollected< - blink::V8UnionArrayBufferOrArrayBufferView>(std::move(dom_array)); + blink::V8UnionArrayBufferOrArrayBufferView>( + blink::DOMArrayBuffer::Create(UNSAFE_TODO(base::span(data, size)))); } static Vector<uint8_t> vectorOf(const uint8_t* data, size_t size) {
diff --git a/third_party/blink/renderer/modules/credentialmanagement/json.cc b/third_party/blink/renderer/modules/credentialmanagement/json.cc index 70f7188..8acd962 100644 --- a/third_party/blink/renderer/modules/credentialmanagement/json.cc +++ b/third_party/blink/renderer/modules/credentialmanagement/json.cc
@@ -1,5 +1,6 @@ #include "third_party/blink/renderer/modules/credentialmanagement/json.h" +#include "base/containers/span.h" #include "base/numerics/safe_conversions.h" #include "base/strings/strcat.h" #include "third_party/blink/renderer/bindings/core/v8/v8_object_builder.h" @@ -44,7 +45,7 @@ if (!Base64UnpaddedURLDecode(in, out)) { return std::nullopt; } - return DOMArrayBuffer::Create(out.data(), out.size()); + return DOMArrayBuffer::Create(base::as_byte_span(out)); } PublicKeyCredentialUserEntity* PublicKeyCredentialUserEntityFromJSON(
diff --git a/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc b/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc index 92e915db..32795501 100644 --- a/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc +++ b/third_party/blink/renderer/modules/crypto/crypto_result_impl.cc
@@ -30,6 +30,8 @@ #include "third_party/blink/renderer/modules/crypto/crypto_result_impl.h" +#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/platform/web_crypto_algorithm.h" #include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
diff --git a/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper_unittest.cc b/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper_unittest.cc index 1b46657..c94bd564 100644 --- a/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper_unittest.cc +++ b/third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper_unittest.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/direct_sockets/tcp_writable_stream_wrapper.h" +#include "base/containers/span.h" #include "base/functional/callback_helpers.h" #include "base/ranges/algorithm.h" #include "base/test/mock_callback.h" @@ -121,7 +122,7 @@ auto* script_state = scope.GetScriptState(); auto* writer = tcp_writable_stream_wrapper->Writable()->getWriter( script_state, ASSERT_NO_EXCEPTION); - auto* chunk = DOMArrayBuffer::Create("A", 1); + auto* chunk = DOMArrayBuffer::Create(base::byte_span_from_cstring("A")); ScriptPromiseUntyped result = writer->write(script_state, ScriptValue::From(script_state, chunk), ASSERT_NO_EXCEPTION); @@ -140,7 +141,7 @@ auto* script_state = scope.GetScriptState(); auto* writer = tcp_writable_stream_wrapper->Writable()->getWriter( script_state, ASSERT_NO_EXCEPTION); - auto* buffer = DOMArrayBuffer::Create("*B", 2); + auto* buffer = DOMArrayBuffer::Create(base::byte_span_from_cstring("*B")); // Create a view into the buffer with offset 1, ie. "B". auto* chunk = DOMUint8Array::Create(buffer, 1, 1); ScriptPromiseUntyped result = @@ -224,7 +225,7 @@ auto* script_state = scope.GetScriptState(); auto* writer = tcp_writable_stream_wrapper->Writable()->getWriter( script_state, ASSERT_NO_EXCEPTION); - auto* chunk = DOMArrayBuffer::Create("D", 1); + auto* chunk = DOMArrayBuffer::Create(base::byte_span_from_cstring("D")); ScriptPromiseUntyped write_promise = writer->write(script_state, ScriptValue::From(script_state, chunk), ASSERT_NO_EXCEPTION); @@ -255,7 +256,7 @@ auto* script_state = scope.GetScriptState(); auto* writer = tcp_writable_stream_wrapper->Writable()->getWriter( script_state, ASSERT_NO_EXCEPTION); - auto* chunk = DOMArrayBuffer::Create("D", 1); + auto* chunk = DOMArrayBuffer::Create(base::byte_span_from_cstring("D")); ScriptPromiseUntyped write_promise = writer->write(script_state, ScriptValue::From(script_state, chunk), ASSERT_NO_EXCEPTION); @@ -287,7 +288,8 @@ std::optional<ScriptPromiseTester> tester; if (pending_write) { auto* script_state = scope.GetScriptState(); - auto* chunk = DOMArrayBuffer::Create("D", 2); + auto* chunk = + DOMArrayBuffer::Create(base::byte_span_with_nul_from_cstring("D")); ScriptPromiseUntyped write_promise = tcp_writable_stream_wrapper->Writable() ->getWriter(script_state, ASSERT_NO_EXCEPTION) @@ -324,7 +326,8 @@ std::optional<ScriptPromiseTester> tester; if (pending_write) { auto* script_state = scope.GetScriptState(); - auto* chunk = DOMArrayBuffer::Create("D", 2); + auto* chunk = + DOMArrayBuffer::Create(base::byte_span_with_nul_from_cstring("D")); ScriptPromiseUntyped write_promise = tcp_writable_stream_wrapper->Writable() ->getWriter(script_state, ASSERT_NO_EXCEPTION)
diff --git a/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper_unittest.cc b/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper_unittest.cc index 9f46676..e723a167 100644 --- a/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper_unittest.cc +++ b/third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper_unittest.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/direct_sockets/udp_writable_stream_wrapper.h" +#include "base/containers/span.h" #include "base/functional/bind.h" #include "base/notreached.h" #include "mojo/public/cpp/bindings/receiver.h" @@ -153,7 +154,7 @@ auto* writer = udp_writable_stream_wrapper->Writable()->getWriter( script_state, ASSERT_NO_EXCEPTION); - auto* chunk = DOMArrayBuffer::Create("A", 1); + auto* chunk = DOMArrayBuffer::Create(base::byte_span_from_cstring("A")); auto* message = UDPMessage::Create(); message->setData( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(chunk)); @@ -184,7 +185,7 @@ auto* writer = udp_writable_stream_wrapper->Writable()->getWriter( script_state, ASSERT_NO_EXCEPTION); - auto* buffer = DOMArrayBuffer::Create("ABC", 3); + auto* buffer = DOMArrayBuffer::Create(base::byte_span_from_cstring("ABC")); auto* chunk = DOMUint8Array::Create(buffer, 0, 3); auto* message = UDPMessage::Create(); @@ -252,8 +253,8 @@ auto* writer = udp_writable_stream_wrapper->Writable()->getWriter( script_state, ASSERT_NO_EXCEPTION); - for (const auto* value : {"A", "B"}) { - auto* chunk = DOMArrayBuffer::Create(value, 1); + for (const std::string_view value : {"A", "B"}) { + auto* chunk = DOMArrayBuffer::Create(base::as_byte_span(value)); auto* message = UDPMessage::Create(); message->setData( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(chunk)); @@ -286,7 +287,7 @@ auto* writer = udp_writable_stream_wrapper->Writable()->getWriter( script_state, ASSERT_NO_EXCEPTION); - auto* chunk = DOMArrayBuffer::Create("A", 1); + auto* chunk = DOMArrayBuffer::Create(base::byte_span_from_cstring("A")); auto* message = UDPMessage::Create(); message->setData( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(chunk)); @@ -338,7 +339,7 @@ auto* writer = udp_writable_stream_wrapper->Writable()->getWriter( script_state, ASSERT_NO_EXCEPTION); - auto* chunk = DOMArrayBuffer::Create("A", 1); + auto* chunk = DOMArrayBuffer::Create(base::byte_span_from_cstring("A")); auto* message = UDPMessage::Create(); message->setData( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(chunk));
diff --git a/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc b/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc index 3910ec2..09bee1b 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/modules/encryptedmedia/html_media_element_encrypted_media.h" +#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "media/base/eme_constants.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" @@ -418,7 +420,8 @@ MediaEncryptedEventInit* initializer = MediaEncryptedEventInit::Create(); initializer->setInitDataType( EncryptedMediaUtils::ConvertFromInitDataType(init_data_type)); - initializer->setInitData(DOMArrayBuffer::Create(init_data, init_data_length)); + initializer->setInitData(DOMArrayBuffer::Create( + UNSAFE_TODO(base::span(init_data, init_data_length)))); initializer->setBubbles(false); initializer->setCancelable(false);
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc index e911030..5189e94 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_session.cc
@@ -28,6 +28,8 @@ #include <cmath> #include <limits> +#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/numerics/safe_conversions.h" #include "encrypted_media_utils.h" #include "media/base/content_decryption_module.h" @@ -545,7 +547,7 @@ // 7. Let init data be a copy of the contents of the initData parameter. DOMArrayBuffer* init_data_buffer = - DOMArrayBuffer::Create(init_data.Data(), init_data.ByteLength()); + DOMArrayBuffer::Create(init_data.ByteSpan()); // 8. Let session type be this object's session type. // (Done in constructor.) @@ -777,8 +779,7 @@ } // 4. Let response copy be a copy of the contents of the response parameter. - DOMArrayBuffer* response_copy = - DOMArrayBuffer::Create(response.Data(), response.ByteLength()); + DOMArrayBuffer* response_copy = DOMArrayBuffer::Create(response.ByteSpan()); // Log the usage of update(). EncryptedMediaUtils::ReportUsage(EmeApiType::kUpdate, GetExecutionContext(), @@ -991,8 +992,7 @@ break; } init->setMessage( - DOMArrayBuffer::Create(static_cast<const void*>(message), - base::checked_cast<uint32_t>(message_length))); + DOMArrayBuffer::Create(UNSAFE_TODO(base::span(message, message_length)))); MediaKeyMessageEvent* event = MediaKeyMessageEvent::Create(event_type_names::kMessage, init);
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc b/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc index e0fd743..308e532 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/media_keys.cc
@@ -334,8 +334,8 @@ // 3. Let certificate be a copy of the contents of the serverCertificate // parameter. - DOMArrayBuffer* server_certificate_buffer = DOMArrayBuffer::Create( - server_certificate.Data(), server_certificate.ByteLength()); + DOMArrayBuffer* server_certificate_buffer = + DOMArrayBuffer::Create(server_certificate.ByteSpan()); // 4. Let promise be a new promise. auto* resolver = MakeGarbageCollected<ScriptPromiseResolver<IDLBoolean>>(
diff --git a/third_party/blink/renderer/modules/hid/hid_device.cc b/third_party/blink/renderer/modules/hid/hid_device.cc index 4991d6b..f25a708 100644 --- a/third_party/blink/renderer/modules/hid/hid_device.cc +++ b/third_party/blink/renderer/modules/hid/hid_device.cc
@@ -547,8 +547,7 @@ const std::optional<Vector<uint8_t>>& data) { MarkRequestComplete(resolver); if (success && data) { - DOMArrayBuffer* dom_buffer = - DOMArrayBuffer::Create(data->data(), data->size()); + DOMArrayBuffer* dom_buffer = DOMArrayBuffer::Create(data.value()); DOMDataView* data_view = DOMDataView::Create(dom_buffer, 0, data->size()); resolver->Resolve(NotShared(data_view)); } else {
diff --git a/third_party/blink/renderer/modules/hid/hid_input_report_event.cc b/third_party/blink/renderer/modules/hid/hid_input_report_event.cc index 5ea059b..d4597b8c 100644 --- a/third_party/blink/renderer/modules/hid/hid_input_report_event.cc +++ b/third_party/blink/renderer/modules/hid/hid_input_report_event.cc
@@ -17,7 +17,7 @@ : Event(type, Bubbles::kNo, Cancelable::kNo), device_(device), report_id_(report_id) { - DOMArrayBuffer* dom_buffer = DOMArrayBuffer::Create(data.data(), data.size()); + DOMArrayBuffer* dom_buffer = DOMArrayBuffer::Create(data); data_ = DOMDataView::Create(dom_buffer, 0, data.size()); }
diff --git a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc index f9f54107..108367d 100644 --- a/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc +++ b/third_party/blink/renderer/modules/ml/webnn/ml_graph_test.cc
@@ -1361,8 +1361,7 @@ const std::array<const uint8_t, kBufferSize> input_data = {0xAA, 0xAA, 0xAA, 0xAA}; - DOMArrayBuffer* array_buffer = - DOMArrayBuffer::Create(input_data.data(), input_data.size()); + DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(input_data); ASSERT_THAT(array_buffer, testing::NotNull()); // Writing the full buffer.
diff --git a/third_party/blink/renderer/modules/nfc/ndef_record.cc b/third_party/blink/renderer/modules/nfc/ndef_record.cc index d324ced..ed632286 100644 --- a/third_party/blink/renderer/modules/nfc/ndef_record.cc +++ b/third_party/blink/renderer/modules/nfc/ndef_record.cc
@@ -593,8 +593,7 @@ DCHECK(payload_data_.empty()); return nullptr; } - DOMArrayBuffer* dom_buffer = - DOMArrayBuffer::Create(payload_data_.data(), payload_data_.size()); + DOMArrayBuffer* dom_buffer = DOMArrayBuffer::Create(payload_data_); return DOMDataView::Create(dom_buffer, 0, payload_data_.size()); }
diff --git a/third_party/blink/renderer/modules/payments/payment_response.cc b/third_party/blink/renderer/modules/payments/payment_response.cc index d8cb443..1abeb946 100644 --- a/third_party/blink/renderer/modules/payments/payment_response.cc +++ b/third_party/blink/renderer/modules/payments/payment_response.cc
@@ -39,9 +39,7 @@ auto* result = MakeGarbageCollected<PublicKeyCredential>( get_assertion_authentication_response->info->id, - DOMArrayBuffer::Create(static_cast<const void*>(info->raw_id.data()), - info->raw_id.size()), - authenticator_response, + DOMArrayBuffer::Create(info->raw_id), authenticator_response, get_assertion_authentication_response->authenticator_attachment, ConvertTo<AuthenticationExtensionsClientOutputs*>( get_assertion_authentication_response->extensions));
diff --git a/third_party/blink/renderer/modules/payments/payment_test_helper.cc b/third_party/blink/renderer/modules/payments/payment_test_helper.cc index ee3bcb2..efc0454d 100644 --- a/third_party/blink/renderer/modules/payments/payment_test_helper.cc +++ b/third_party/blink/renderer/modules/payments/payment_test_helper.cc
@@ -227,16 +227,12 @@ HeapVector<Member<V8UnionArrayBufferOrArrayBufferView>> credentialIds; credentialIds.push_back( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>( - DOMArrayBuffer::Create( - kSecurePaymentConfirmationCredentialId, - std::size(kSecurePaymentConfirmationCredentialId)))); + DOMArrayBuffer::Create(kSecurePaymentConfirmationCredentialId))); request->setCredentialIds(credentialIds); request->setChallenge( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>( - DOMArrayBuffer::Create( - kSecurePaymentConfirmationChallenge, - std::size(kSecurePaymentConfirmationChallenge)))); + DOMArrayBuffer::Create(kSecurePaymentConfirmationChallenge))); PaymentCredentialInstrument* instrument = PaymentCredentialInstrument::Create(scope.GetIsolate());
diff --git a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper_test.cc b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper_test.cc index 790a7bc8..d59aa97f 100644 --- a/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper_test.cc +++ b/third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper_test.cc
@@ -4,6 +4,8 @@ #include "third_party/blink/renderer/modules/payments/secure_payment_confirmation_helper.h" +#include "base/compiler_specific.h" +#include "base/containers/span.h" #include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/mojom/payments/payment_request.mojom-blink.h" @@ -14,9 +16,9 @@ #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_client_inputs.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_inputs.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_authentication_extensions_prf_values.h" +#include "third_party/blink/renderer/bindings/modules/v8/v8_network_or_issuer_information.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_payment_credential_instrument.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_secure_payment_confirmation_request.h" -#include "third_party/blink/renderer/bindings/modules/v8/v8_network_or_issuer_information.h" #include "third_party/blink/renderer/modules/payments/payment_test_helper.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/testing/task_environment.h" @@ -37,9 +39,9 @@ static V8UnionArrayBufferOrArrayBufferView* ArrayBufferOrView( const uint8_t* data, size_t size) { - DOMArrayBuffer* dom_array = DOMArrayBuffer::Create(data, size); - return MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>( - std::move(dom_array)); + DOMArrayBuffer* dom_array = + DOMArrayBuffer::Create(UNSAFE_TODO(base::span(data, size))); + return MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(dom_array); } static AuthenticationExtensionsPRFInputs* CreatePrfInputs( @@ -164,9 +166,7 @@ HeapVector<Member<V8UnionArrayBufferOrArrayBufferView>> credentialIds; credentialIds.push_back( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>( - DOMArrayBuffer::Create( - kSecurePaymentConfirmationCredentialId, - std::size(kSecurePaymentConfirmationCredentialId)))); + DOMArrayBuffer::Create(kSecurePaymentConfirmationCredentialId))); const size_t num_elements = 0; const size_t byte_length = 0; credentialIds.push_back(
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc index 71c8cbe2..2da3c2f4 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
@@ -740,9 +740,7 @@ return; } if (binary_type_ == kBinaryTypeArrayBuffer) { - DOMArrayBuffer* dom_buffer = DOMArrayBuffer::Create( - buffer.data.cdata(), - base::checked_cast<unsigned>(buffer.data.size())); + DOMArrayBuffer* dom_buffer = DOMArrayBuffer::Create(buffer.data); DispatchEvent(*MessageEvent::Create(dom_buffer)); return; }
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc index 1d2de77..9a936ab 100644 --- a/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc +++ b/third_party/blink/renderer/modules/peerconnection/rtc_dtls_transport.cc
@@ -140,8 +140,7 @@ auto& cert = certs->Get(i); rtc::Buffer der_cert; cert.ToDER(&der_cert); - DOMArrayBuffer* dab_cert = DOMArrayBuffer::Create( - der_cert.data(), static_cast<unsigned int>(der_cert.size())); + DOMArrayBuffer* dab_cert = DOMArrayBuffer::Create(der_cert); remote_certificates_.push_back(dab_cert); } } else { @@ -150,8 +149,7 @@ auto& cert = certs->Get(i); rtc::Buffer der_cert; cert.ToDER(&der_cert); - DOMArrayBuffer* dab_cert = DOMArrayBuffer::Create( - der_cert.data(), static_cast<unsigned int>(der_cert.size())); + DOMArrayBuffer* dab_cert = DOMArrayBuffer::Create(der_cert); // Don't replace the certificate if it's unchanged. // Should have been "if (*dab_cert != *remote_certificates_[i])" if (dab_cert->ByteLength() != remote_certificates_[i]->ByteLength() ||
diff --git a/third_party/blink/renderer/modules/push_messaging/push_manager_test.cc b/third_party/blink/renderer/modules/push_messaging/push_manager_test.cc index 36aac250..51933c9 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_manager_test.cc +++ b/third_party/blink/renderer/modules/push_messaging/push_manager_test.cc
@@ -59,8 +59,7 @@ PushSubscriptionOptionsInit* options = PushSubscriptionOptionsInit::Create(); options->setApplicationServerKey( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>( - DOMArrayBuffer::Create(kApplicationServerKey, - kApplicationServerKeyLength))); + DOMArrayBuffer::Create(kApplicationServerKey))); DummyExceptionStateForTesting exception_state; PushSubscriptionOptions* output = @@ -98,12 +97,11 @@ TEST(PushManagerTest, InvalidSenderKeyLength) { test::TaskEnvironment task_environment; - uint8_t sender_key[kMaxKeyLength + 1]; - memset(sender_key, 0, sizeof(sender_key)); + uint8_t sender_key[kMaxKeyLength + 1] = {}; PushSubscriptionOptionsInit* options = PushSubscriptionOptionsInit::Create(); options->setApplicationServerKey( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferViewOrString>( - DOMArrayBuffer::Create(sender_key, kMaxKeyLength + 1))); + DOMArrayBuffer::Create(sender_key))); DummyExceptionStateForTesting exception_state; PushSubscriptionOptions* output =
diff --git a/third_party/blink/renderer/modules/push_messaging/push_message_data.cc b/third_party/blink/renderer/modules/push_messaging/push_message_data.cc index fa11a5d..b9c2527 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_message_data.cc +++ b/third_party/blink/renderer/modules/push_messaging/push_message_data.cc
@@ -6,6 +6,7 @@ #include <memory> +#include "base/containers/span.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybuffer_arraybufferview_usvstring.h" #include "third_party/blink/renderer/core/fileapi/blob.h" @@ -71,7 +72,7 @@ PushMessageData::~PushMessageData() = default; DOMArrayBuffer* PushMessageData::arrayBuffer() const { - return DOMArrayBuffer::Create(data_.data(), data_.size()); + return DOMArrayBuffer::Create(base::as_byte_span(data_)); } Blob* PushMessageData::blob() const {
diff --git a/third_party/blink/renderer/modules/push_messaging/push_subscription.cc b/third_party/blink/renderer/modules/push_messaging/push_subscription.cc index 5846afb0..5dbe318 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_subscription.cc +++ b/third_party/blink/renderer/modules/push_messaging/push_subscription.cc
@@ -87,11 +87,8 @@ options_(MakeGarbageCollected<PushSubscriptionOptions>( user_visible_only, application_server_key)), - p256dh_( - DOMArrayBuffer::Create(p256dh.data(), - base::checked_cast<unsigned>(p256dh.size()))), - auth_(DOMArrayBuffer::Create(auth.data(), - base::checked_cast<unsigned>(auth.size()))), + p256dh_(DOMArrayBuffer::Create(p256dh)), + auth_(DOMArrayBuffer::Create(auth)), expiration_time_(expiration_time), service_worker_registration_(service_worker_registration) {}
diff --git a/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc b/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc index a8e7cf9..77bc5940 100644 --- a/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc +++ b/third_party/blink/renderer/modules/push_messaging/push_subscription_options.cc
@@ -103,9 +103,7 @@ bool user_visible_only, const Vector<uint8_t>& application_server_key) : user_visible_only_(user_visible_only), - application_server_key_(DOMArrayBuffer::Create( - application_server_key.data(), - base::checked_cast<unsigned>(application_server_key.size()))) {} + application_server_key_(DOMArrayBuffer::Create(application_server_key)) {} void PushSubscriptionOptions::Trace(Visitor* visitor) const { visitor->Trace(application_server_key_);
diff --git a/third_party/blink/renderer/modules/smart_card/smart_card_connection.cc b/third_party/blink/renderer/modules/smart_card/smart_card_connection.cc index f7e2816..82a41b7 100644 --- a/third_party/blink/renderer/modules/smart_card/smart_card_connection.cc +++ b/third_party/blink/renderer/modules/smart_card/smart_card_connection.cc
@@ -613,9 +613,7 @@ return; } - const Vector<uint8_t>& data = result->get_data(); - - resolver->Resolve(DOMArrayBuffer::Create(data.data(), data.size())); + resolver->Resolve(DOMArrayBuffer::Create(result->get_data())); } void SmartCardConnection::OnStatusDone( @@ -644,8 +642,7 @@ status->setState(connection_state.value()); if (!mojo_status->answer_to_reset.empty()) { status->setAnswerToReset( - DOMArrayBuffer::Create(mojo_status->answer_to_reset.data(), - mojo_status->answer_to_reset.size())); + DOMArrayBuffer::Create(mojo_status->answer_to_reset)); } resolver->Resolve(status); }
diff --git a/third_party/blink/renderer/modules/smart_card/smart_card_context.cc b/third_party/blink/renderer/modules/smart_card/smart_card_context.cc index 40debaa..6641ddb 100644 --- a/third_party/blink/renderer/modules/smart_card/smart_card_context.cc +++ b/third_party/blink/renderer/modules/smart_card/smart_card_context.cc
@@ -83,8 +83,7 @@ ToV8ReaderStateFlagsOut(*mojom_state_out->event_state)); state_out->setEventCount(mojom_state_out->event_count); state_out->setAnswerToReset( - DOMArrayBuffer::Create(mojom_state_out->answer_to_reset.data(), - mojom_state_out->answer_to_reset.size())); + DOMArrayBuffer::Create(mojom_state_out->answer_to_reset)); reader_states.push_back(state_out); }
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc index 3cdb65cb..bc01958 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_data_copy_to_fuzzer.cc
@@ -25,10 +25,6 @@ auto page_holder = std::make_unique<DummyPageHolder>(); page_holder->GetFrame().GetSettings()->SetScriptEnabled(true); - // Request a full GC upon returning. - auto scoped_gc = - MakeScopedGarbageCollectionRequest(task_environment.isolate()); - ScriptState* script_state = ToScriptStateForMainWorld(&page_holder->GetFrame()); ScriptState::Scope scope(script_state);
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_data_test.cc b/third_party/blink/renderer/modules/webcodecs/audio_data_test.cc index 0dd866d..6085140 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_data_test.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_data_test.cc
@@ -11,6 +11,7 @@ #include <optional> +#include "base/containers/span.h" #include "media/base/audio_sample_types.h" #include "media/base/test_helpers.h" #include "testing/gtest/include/gtest/gtest.h" @@ -290,7 +291,7 @@ TEST_F(AudioDataTest, TransferBuffer) { V8TestingScope scope; std::string data = "audio data"; - auto* buffer = DOMArrayBuffer::Create(data.data(), data.size()); + auto* buffer = DOMArrayBuffer::Create(base::as_byte_span(data)); auto* buffer_source = MakeGarbageCollected<AllowSharedBufferSource>(buffer); const void* buffer_data_ptr = buffer->Data(); @@ -326,8 +327,7 @@ V8TestingScope scope; const uint32_t frames = 3; std::vector<float> data{0.0, 1.0, 2.0, 3.0, 4.0}; - auto* buffer = - DOMArrayBuffer::Create(data.data(), data.size() * sizeof(float)); + auto* buffer = DOMArrayBuffer::Create(base::as_byte_span(data)); auto* view = DOMDataView::Create( buffer, 1 /* offset one byte from the float ptr, that how we are sure that the view is not aligned to sizeof(float) */
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc b/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc index 1d76a48..87a2663 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_decoder.cc
@@ -48,8 +48,7 @@ if (config.hasDescription()) { auto desc_wrapper = AsSpan<const uint8_t>(config.description()); if (!desc_wrapper.empty()) { - DOMArrayBuffer* buffer_copy = - DOMArrayBuffer::Create(desc_wrapper.data(), desc_wrapper.size()); + DOMArrayBuffer* buffer_copy = DOMArrayBuffer::Create(desc_wrapper); copy->setDescription( MakeGarbageCollected<AllowSharedBufferSource>(buffer_copy)); }
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_decoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/audio_decoder_fuzzer.cc index 6557dfe..2da7cb0 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_decoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_decoder_fuzzer.cc
@@ -36,10 +36,6 @@ auto page_holder = std::make_unique<DummyPageHolder>(); page_holder->GetFrame().GetSettings()->SetScriptEnabled(true); - // Request a full GC upon returning. - auto scoped_gc = - MakeScopedGarbageCollectionRequest(task_environment.isolate()); - // // NOTE: GC objects that need to survive iterations of the loop below // must be Persistent<>! @@ -51,69 +47,66 @@ // // Scoping Persistent<> refs so GC can collect these at the end. - { - Persistent<ScriptState> script_state = - ToScriptStateForMainWorld(&page_holder->GetFrame()); - ScriptState::Scope scope(script_state); + Persistent<ScriptState> script_state = + ToScriptStateForMainWorld(&page_holder->GetFrame()); + ScriptState::Scope scope(script_state); - Persistent<ScriptFunction> error_function = - MakeGarbageCollected<ScriptFunction>( - script_state, MakeGarbageCollected<FakeFunction>("error")); - Persistent<V8WebCodecsErrorCallback> error_callback = - V8WebCodecsErrorCallback::Create(error_function->V8Function()); - Persistent<ScriptFunction> output_function = - MakeGarbageCollected<ScriptFunction>( - script_state, MakeGarbageCollected<FakeFunction>("output")); - Persistent<V8AudioDataOutputCallback> output_callback = - V8AudioDataOutputCallback::Create(output_function->V8Function()); + Persistent<ScriptFunction> error_function = + MakeGarbageCollected<ScriptFunction>( + script_state, MakeGarbageCollected<FakeFunction>("error")); + Persistent<V8WebCodecsErrorCallback> error_callback = + V8WebCodecsErrorCallback::Create(error_function->V8Function()); + Persistent<ScriptFunction> output_function = + MakeGarbageCollected<ScriptFunction>( + script_state, MakeGarbageCollected<FakeFunction>("output")); + Persistent<V8AudioDataOutputCallback> output_callback = + V8AudioDataOutputCallback::Create(output_function->V8Function()); - Persistent<AudioDecoderInit> audio_decoder_init = - MakeGarbageCollected<AudioDecoderInit>(); - audio_decoder_init->setError(error_callback); - audio_decoder_init->setOutput(output_callback); + Persistent<AudioDecoderInit> audio_decoder_init = + MakeGarbageCollected<AudioDecoderInit>(); + audio_decoder_init->setError(error_callback); + audio_decoder_init->setOutput(output_callback); - Persistent<AudioDecoder> audio_decoder = AudioDecoder::Create( - script_state, audio_decoder_init, IGNORE_EXCEPTION_FOR_TESTING); + Persistent<AudioDecoder> audio_decoder = AudioDecoder::Create( + script_state, audio_decoder_init, IGNORE_EXCEPTION_FOR_TESTING); - if (audio_decoder) { - for (auto& invocation : proto.invocations()) { - switch (invocation.Api_case()) { - case wc_fuzzer::AudioDecoderApiInvocation::kConfigure: { - AudioDecoderConfig* config = - MakeAudioDecoderConfig(invocation.configure()); + if (audio_decoder) { + for (auto& invocation : proto.invocations()) { + switch (invocation.Api_case()) { + case wc_fuzzer::AudioDecoderApiInvocation::kConfigure: { + AudioDecoderConfig* config = + MakeAudioDecoderConfig(invocation.configure()); - // Use the same config to fuzz isConfigSupported(). - AudioDecoder::isConfigSupported(script_state, config, - IGNORE_EXCEPTION_FOR_TESTING); + // Use the same config to fuzz isConfigSupported(). + AudioDecoder::isConfigSupported(script_state, config, + IGNORE_EXCEPTION_FOR_TESTING); - audio_decoder->configure(config, IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::AudioDecoderApiInvocation::kDecode: - audio_decoder->decode( - MakeEncodedAudioChunk(script_state, - invocation.decode().chunk()), - IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::AudioDecoderApiInvocation::kFlush: { - // TODO(https://crbug.com/1119253): Fuzz whether to await resolution - // of the flush promise. - audio_decoder->flush(IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::AudioDecoderApiInvocation::kReset: - audio_decoder->reset(IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::AudioDecoderApiInvocation::kClose: - audio_decoder->close(IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::AudioDecoderApiInvocation::API_NOT_SET: - break; + audio_decoder->configure(config, IGNORE_EXCEPTION_FOR_TESTING); + break; } - - // Give other tasks a chance to run (e.g. calling our output callback). - base::RunLoop().RunUntilIdle(); + case wc_fuzzer::AudioDecoderApiInvocation::kDecode: + audio_decoder->decode( + MakeEncodedAudioChunk(script_state, invocation.decode().chunk()), + IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::AudioDecoderApiInvocation::kFlush: { + // TODO(https://crbug.com/1119253): Fuzz whether to await resolution + // of the flush promise. + audio_decoder->flush(IGNORE_EXCEPTION_FOR_TESTING); + break; + } + case wc_fuzzer::AudioDecoderApiInvocation::kReset: + audio_decoder->reset(IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::AudioDecoderApiInvocation::kClose: + audio_decoder->close(IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::AudioDecoderApiInvocation::API_NOT_SET: + break; } + + // Give other tasks a chance to run (e.g. calling our output callback). + base::RunLoop().RunUntilIdle(); } } }
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc b/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc index bf34284..b67b13c 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_encoder.cc
@@ -626,8 +626,7 @@ decoder_config->setSampleRate(encoded_buffer.params.sample_rate()); decoder_config->setNumberOfChannels(active_config->options.channels); if (codec_desc.has_value()) { - auto* desc_array_buf = DOMArrayBuffer::Create(codec_desc.value().data(), - codec_desc.value().size()); + auto* desc_array_buf = DOMArrayBuffer::Create(codec_desc.value()); decoder_config->setDescription( MakeGarbageCollected<AllowSharedBufferSource>(desc_array_buf)); }
diff --git a/third_party/blink/renderer/modules/webcodecs/audio_encoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/audio_encoder_fuzzer.cc index 91687624..7b79a7f 100644 --- a/third_party/blink/renderer/modules/webcodecs/audio_encoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/audio_encoder_fuzzer.cc
@@ -156,10 +156,6 @@ auto page_holder = std::make_unique<DummyPageHolder>(); page_holder->GetFrame().GetSettings()->SetScriptEnabled(true); - // Request a full GC upon returning. - auto scoped_gc = - MakeScopedGarbageCollectionRequest(task_environment.isolate()); - #if HAS_AAC_ENCODER base::test::ScopedFeatureList platform_aac(media::kPlatformAudioEncoder); static const bool kSetTestBinder = []() { @@ -185,73 +181,71 @@ // // Scoping Persistent<> refs so GC can collect these at the end. - { - Persistent<ScriptState> script_state = - ToScriptStateForMainWorld(&page_holder->GetFrame()); - ScriptState::Scope scope(script_state); + Persistent<ScriptState> script_state = + ToScriptStateForMainWorld(&page_holder->GetFrame()); + ScriptState::Scope scope(script_state); - Persistent<ScriptFunction> error_function = - MakeGarbageCollected<ScriptFunction>( - script_state, MakeGarbageCollected<FakeFunction>("error")); - Persistent<V8WebCodecsErrorCallback> error_callback = - V8WebCodecsErrorCallback::Create(error_function->V8Function()); - Persistent<ScriptFunction> output_function = - MakeGarbageCollected<ScriptFunction>( - script_state, MakeGarbageCollected<FakeFunction>("output")); - Persistent<V8EncodedAudioChunkOutputCallback> output_callback = - V8EncodedAudioChunkOutputCallback::Create( - output_function->V8Function()); + Persistent<ScriptFunction> error_function = + MakeGarbageCollected<ScriptFunction>( + script_state, MakeGarbageCollected<FakeFunction>("error")); + Persistent<V8WebCodecsErrorCallback> error_callback = + V8WebCodecsErrorCallback::Create(error_function->V8Function()); + Persistent<ScriptFunction> output_function = + MakeGarbageCollected<ScriptFunction>( + script_state, MakeGarbageCollected<FakeFunction>("output")); + Persistent<V8EncodedAudioChunkOutputCallback> output_callback = + V8EncodedAudioChunkOutputCallback::Create(output_function->V8Function()); - Persistent<AudioEncoderInit> audio_encoder_init = - MakeGarbageCollected<AudioEncoderInit>(); - audio_encoder_init->setError(error_callback); - audio_encoder_init->setOutput(output_callback); + Persistent<AudioEncoderInit> audio_encoder_init = + MakeGarbageCollected<AudioEncoderInit>(); + audio_encoder_init->setError(error_callback); + audio_encoder_init->setOutput(output_callback); - Persistent<AudioEncoder> audio_encoder = AudioEncoder::Create( - script_state, audio_encoder_init, IGNORE_EXCEPTION_FOR_TESTING); + Persistent<AudioEncoder> audio_encoder = AudioEncoder::Create( + script_state, audio_encoder_init, IGNORE_EXCEPTION_FOR_TESTING); - if (audio_encoder) { - for (auto& invocation : proto.invocations()) { - switch (invocation.Api_case()) { - case wc_fuzzer::AudioEncoderApiInvocation::kConfigure: { - AudioEncoderConfig* config = - MakeAudioEncoderConfig(invocation.configure()); + if (audio_encoder) { + for (auto& invocation : proto.invocations()) { + switch (invocation.Api_case()) { + case wc_fuzzer::AudioEncoderApiInvocation::kConfigure: { + AudioEncoderConfig* config = + MakeAudioEncoderConfig(invocation.configure()); - // Use the same config to fuzz isConfigSupported(). - AudioEncoder::isConfigSupported(script_state, config, - IGNORE_EXCEPTION_FOR_TESTING); + // Use the same config to fuzz isConfigSupported(). + AudioEncoder::isConfigSupported(script_state, config, + IGNORE_EXCEPTION_FOR_TESTING); - audio_encoder->configure(config, IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::AudioEncoderApiInvocation::kEncode: { - AudioData* data = - MakeAudioData(script_state, invocation.encode().data()); - if (!data) - return; - - audio_encoder->encode(data, IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::AudioEncoderApiInvocation::kFlush: { - // TODO(https://crbug.com/1119253): Fuzz whether to await resolution - // of the flush promise. - audio_encoder->flush(IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::AudioEncoderApiInvocation::kReset: - audio_encoder->reset(IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::AudioEncoderApiInvocation::kClose: - audio_encoder->close(IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::AudioEncoderApiInvocation::API_NOT_SET: - break; + audio_encoder->configure(config, IGNORE_EXCEPTION_FOR_TESTING); + break; } + case wc_fuzzer::AudioEncoderApiInvocation::kEncode: { + AudioData* data = + MakeAudioData(script_state, invocation.encode().data()); + if (!data) { + return; + } - // Give other tasks a chance to run (e.g. calling our output callback). - base::RunLoop().RunUntilIdle(); + audio_encoder->encode(data, IGNORE_EXCEPTION_FOR_TESTING); + break; + } + case wc_fuzzer::AudioEncoderApiInvocation::kFlush: { + // TODO(https://crbug.com/1119253): Fuzz whether to await resolution + // of the flush promise. + audio_encoder->flush(IGNORE_EXCEPTION_FOR_TESTING); + break; + } + case wc_fuzzer::AudioEncoderApiInvocation::kReset: + audio_encoder->reset(IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::AudioEncoderApiInvocation::kClose: + audio_encoder->close(IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::AudioEncoderApiInvocation::API_NOT_SET: + break; } + + // Give other tasks a chance to run (e.g. calling our output callback). + base::RunLoop().RunUntilIdle(); } } }
diff --git a/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_test.cc b/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_test.cc index b9c7ed840..966e398b 100644 --- a/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_test.cc +++ b/third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk_test.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/webcodecs/encoded_audio_chunk.h" +#include "base/containers/span.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_decrypt_config.h" @@ -67,7 +68,7 @@ auto* init = EncodedAudioChunkInit::Create(); init->setTimestamp(timestamp); init->setType(type); - auto* buffer = DOMArrayBuffer::Create(data.data(), data.size()); + auto* buffer = DOMArrayBuffer::Create(base::as_byte_span(data)); init->setData(MakeGarbageCollected<AllowSharedBufferSource>(buffer)); HeapVector<Member<DOMArrayBuffer>> transfer; transfer.push_back(Member<DOMArrayBuffer>(buffer));
diff --git a/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_test.cc b/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_test.cc index d15b2d7..a4ebb01 100644 --- a/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_test.cc +++ b/third_party/blink/renderer/modules/webcodecs/encoded_video_chunk_test.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/webcodecs/encoded_video_chunk.h" +#include "base/containers/span.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_decrypt_config.h" @@ -68,7 +69,7 @@ auto* init = EncodedVideoChunkInit::Create(); init->setTimestamp(timestamp); init->setType(type); - auto* buffer = DOMArrayBuffer::Create(data.data(), data.size()); + auto* buffer = DOMArrayBuffer::Create(base::as_byte_span(data)); init->setData(MakeGarbageCollected<AllowSharedBufferSource>(buffer)); HeapVector<Member<DOMArrayBuffer>> transfer; transfer.push_back(Member<DOMArrayBuffer>(buffer));
diff --git a/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc index 4d66519..140bad1 100644 --- a/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/image_decoder_fuzzer.cc
@@ -12,6 +12,7 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_union_arraybufferallowshared_arraybufferviewallowshared_readablestream.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_image_decode_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_image_decoder_init.h" +#include "third_party/blink/renderer/core/css/css_default_style_sheets.h" #include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/streams/readable_stream.h" @@ -25,6 +26,7 @@ #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/heap/persistent.h" +#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h" #include "third_party/blink/renderer/platform/testing/blink_fuzzer_test_support.h" #include "third_party/blink/renderer/platform/testing/task_environment.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" @@ -81,13 +83,10 @@ const wc_fuzzer::ImageDecoderApiInvocationSequence& proto) { static BlinkFuzzerTestSupport test_support = BlinkFuzzerTestSupport(); test::TaskEnvironment task_environment; + auto page_holder = std::make_unique<DummyPageHolder>(); page_holder->GetFrame().GetSettings()->SetScriptEnabled(true); - // Request a full GC upon returning. - auto scoped_gc = - MakeScopedGarbageCollectionRequest(task_environment.isolate()); - // // NOTE: GC objects that need to survive iterations of the loop below // must be Persistent<>! @@ -99,95 +98,89 @@ // // Scoping Persistent<> refs so GC can collect these at the end. - { - Persistent<ScriptState> script_state = - ToScriptStateForMainWorld(&page_holder->GetFrame()); - ScriptState::Scope scope(script_state); + Persistent<ScriptState> script_state = + ToScriptStateForMainWorld(&page_holder->GetFrame()); + ScriptState::Scope scope(script_state); - // Fuzz the isTypeSupported() API explicitly. - ImageDecoderExternal::isTypeSupported(script_state, - proto.config().type().c_str()); + // Fuzz the isTypeSupported() API explicitly. + ImageDecoderExternal::isTypeSupported(script_state, + proto.config().type().c_str()); - Persistent<ImageDecoderInit> image_decoder_init = - MakeGarbageCollected<ImageDecoderInit>(); - image_decoder_init->setType(proto.config().type().c_str()); - Persistent<DOMArrayBuffer> data_copy = DOMArrayBuffer::Create( - proto.config().data().data(), proto.config().data().size()); - image_decoder_init->setData( - MakeGarbageCollected<V8ImageBufferSource>(data_copy)); - image_decoder_init->setColorSpaceConversion(ToColorSpaceConversion( - proto.config().options().color_space_conversion())); + Persistent<ImageDecoderInit> image_decoder_init = + MakeGarbageCollected<ImageDecoderInit>(); + image_decoder_init->setType(proto.config().type().c_str()); + Persistent<DOMArrayBuffer> data_copy = DOMArrayBuffer::Create( + proto.config().data().data(), proto.config().data().size()); + image_decoder_init->setData( + MakeGarbageCollected<V8ImageBufferSource>(data_copy)); + image_decoder_init->setColorSpaceConversion(ToColorSpaceConversion( + proto.config().options().color_space_conversion())); - // Limit resize support to a reasonable value to prevent fuzzer oom. - constexpr uint32_t kMaxDimension = 4096u; - image_decoder_init->setDesiredWidth( - std::min(proto.config().options().resize_width(), kMaxDimension)); - image_decoder_init->setDesiredHeight( - std::min(proto.config().options().resize_height(), kMaxDimension)); - image_decoder_init->setPreferAnimation(proto.config().prefer_animation()); + // Limit resize support to a reasonable value to prevent fuzzer oom. + constexpr uint32_t kMaxDimension = 4096u; + image_decoder_init->setDesiredWidth( + std::min(proto.config().options().resize_width(), kMaxDimension)); + image_decoder_init->setDesiredHeight( + std::min(proto.config().options().resize_height(), kMaxDimension)); + image_decoder_init->setPreferAnimation(proto.config().prefer_animation()); - Persistent<ImageDecoderExternal> image_decoder = - ImageDecoderExternal::Create(script_state, image_decoder_init, - IGNORE_EXCEPTION_FOR_TESTING); + Persistent<ImageDecoderExternal> image_decoder = ImageDecoderExternal::Create( + script_state, image_decoder_init, IGNORE_EXCEPTION_FOR_TESTING); - if (image_decoder) { - // Promises will be fulfilled synchronously since we're using an array - // buffer based source. - RunFuzzingLoop(image_decoder, proto.invocations()); + if (image_decoder) { + // Promises will be fulfilled synchronously since we're using an array + // buffer based source. + RunFuzzingLoop(image_decoder, proto.invocations()); - // Close out underlying decoder to simplify reproduction analysis. - image_decoder->close(); - image_decoder = nullptr; - base::RunLoop().RunUntilIdle(); + // Close out underlying decoder to simplify reproduction analysis. + image_decoder->close(); + image_decoder = nullptr; + base::RunLoop().RunUntilIdle(); - // Collect what we can after the first fuzzing loop; this keeps memory - // pressure down during ReadableStream fuzzing. - script_state->GetIsolate()->RequestGarbageCollectionForTesting( - v8::Isolate::kFullGarbageCollection); - } - - Persistent<TestUnderlyingSource> underlying_source = - MakeGarbageCollected<TestUnderlyingSource>(script_state); - Persistent<ReadableStream> stream = - ReadableStream::CreateWithCountQueueingStrategy(script_state, - underlying_source, 0); - - image_decoder_init->setData( - MakeGarbageCollected<V8ImageBufferSource>(stream)); - image_decoder = ImageDecoderExternal::Create( - script_state, image_decoder_init, IGNORE_EXCEPTION_FOR_TESTING); - image_decoder_init = nullptr; - - if (image_decoder) { - // Split the image data into chunks. - constexpr size_t kNumChunks = 2; - const size_t chunk_size = (data_copy->ByteLength() + 1) / kNumChunks; - size_t offset = 0; - for (size_t i = 0; i < kNumChunks; ++i) { - RunFuzzingLoop(image_decoder, proto.invocations()); - - const size_t current_chunk_size = - std::min(data_copy->ByteLength() - offset, chunk_size); - - v8::Local<v8::Value> v8_data_array = ToV8Traits<DOMUint8Array>::ToV8( - script_state, - DOMUint8Array::Create(data_copy, offset, current_chunk_size)); - - underlying_source->Enqueue( - ScriptValue(script_state->GetIsolate(), v8_data_array)); - offset += chunk_size; - } - - underlying_source->Close(); - data_copy = nullptr; - - // Run one additional loop after all data has been appended. - RunFuzzingLoop(image_decoder, proto.invocations()); - } + // Collect what we can after the first fuzzing loop; this keeps memory + // pressure down during ReadableStream fuzzing. + script_state->GetIsolate()->RequestGarbageCollectionForTesting( + v8::Isolate::kFullGarbageCollection); } - // Give other tasks a chance to run before we GC. - base::RunLoop().RunUntilIdle(); + Persistent<TestUnderlyingSource> underlying_source = + MakeGarbageCollected<TestUnderlyingSource>(script_state); + Persistent<ReadableStream> stream = + ReadableStream::CreateWithCountQueueingStrategy(script_state, + underlying_source, 0); + + image_decoder_init->setData( + MakeGarbageCollected<V8ImageBufferSource>(stream)); + image_decoder = ImageDecoderExternal::Create(script_state, image_decoder_init, + IGNORE_EXCEPTION_FOR_TESTING); + image_decoder_init = nullptr; + + if (image_decoder) { + // Split the image data into chunks. + constexpr size_t kNumChunks = 2; + const size_t chunk_size = (data_copy->ByteLength() + 1) / kNumChunks; + size_t offset = 0; + for (size_t i = 0; i < kNumChunks; ++i) { + RunFuzzingLoop(image_decoder, proto.invocations()); + + const size_t current_chunk_size = + std::min(data_copy->ByteLength() - offset, chunk_size); + + v8::Local<v8::Value> v8_data_array = ToV8Traits<DOMUint8Array>::ToV8( + script_state, + DOMUint8Array::Create(data_copy, offset, current_chunk_size)); + + underlying_source->Enqueue( + ScriptValue(script_state->GetIsolate(), v8_data_array)); + offset += chunk_size; + } + + underlying_source->Close(); + data_copy = nullptr; + + // Run one additional loop after all data has been appended. + RunFuzzingLoop(image_decoder, proto.invocations()); + } } } // namespace blink
diff --git a/third_party/blink/renderer/modules/webcodecs/test_helpers.cc b/third_party/blink/renderer/modules/webcodecs/test_helpers.cc index 41f10f47..bab9cc9d 100644 --- a/third_party/blink/renderer/modules/webcodecs/test_helpers.cc +++ b/third_party/blink/renderer/modules/webcodecs/test_helpers.cc
@@ -4,11 +4,13 @@ #include "third_party/blink/renderer/modules/webcodecs/test_helpers.h" +#include "base/containers/span.h" + namespace blink { AllowSharedBufferSource* StringToBuffer(std::string_view data) { return MakeGarbageCollected<AllowSharedBufferSource>( - DOMArrayBuffer::Create(data.data(), data.size())); + DOMArrayBuffer::Create(base::as_byte_span(data))); } std::string BufferToString(const media::DecoderBuffer& buffer) {
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc index 3ef3db15..c7c8e3d 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder.cc
@@ -130,8 +130,7 @@ NOTREACHED_IN_MIGRATION(); return nullptr; } - DOMArrayBuffer* buffer_copy = - DOMArrayBuffer::Create(desc_wrapper.data(), desc_wrapper.size()); + DOMArrayBuffer* buffer_copy = DOMArrayBuffer::Create(desc_wrapper); copy->setDescription( MakeGarbageCollected<AllowSharedBufferSource>(buffer_copy)); }
diff --git a/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc index 8d33530f..b9f1b0d1 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_decoder_fuzzer.cc
@@ -36,10 +36,6 @@ auto page_holder = std::make_unique<DummyPageHolder>(); page_holder->GetFrame().GetSettings()->SetScriptEnabled(true); - // Request a full GC upon returning. - auto scoped_gc = - MakeScopedGarbageCollectionRequest(task_environment.isolate()); - // // NOTE: GC objects that need to survive iterations of the loop below // must be Persistent<>! @@ -51,69 +47,66 @@ // // Scoping Persistent<> refs so GC can collect these at the end. - { - Persistent<ScriptState> script_state = - ToScriptStateForMainWorld(&page_holder->GetFrame()); - ScriptState::Scope scope(script_state); + Persistent<ScriptState> script_state = + ToScriptStateForMainWorld(&page_holder->GetFrame()); + ScriptState::Scope scope(script_state); - Persistent<ScriptFunction> error_function = - MakeGarbageCollected<ScriptFunction>( - script_state, MakeGarbageCollected<FakeFunction>("error")); - Persistent<V8WebCodecsErrorCallback> error_callback = - V8WebCodecsErrorCallback::Create(error_function->V8Function()); - Persistent<ScriptFunction> output_function = - MakeGarbageCollected<ScriptFunction>( - script_state, MakeGarbageCollected<FakeFunction>("output")); - Persistent<V8VideoFrameOutputCallback> output_callback = - V8VideoFrameOutputCallback::Create(output_function->V8Function()); + Persistent<ScriptFunction> error_function = + MakeGarbageCollected<ScriptFunction>( + script_state, MakeGarbageCollected<FakeFunction>("error")); + Persistent<V8WebCodecsErrorCallback> error_callback = + V8WebCodecsErrorCallback::Create(error_function->V8Function()); + Persistent<ScriptFunction> output_function = + MakeGarbageCollected<ScriptFunction>( + script_state, MakeGarbageCollected<FakeFunction>("output")); + Persistent<V8VideoFrameOutputCallback> output_callback = + V8VideoFrameOutputCallback::Create(output_function->V8Function()); - Persistent<VideoDecoderInit> video_decoder_init = - MakeGarbageCollected<VideoDecoderInit>(); - video_decoder_init->setError(error_callback); - video_decoder_init->setOutput(output_callback); + Persistent<VideoDecoderInit> video_decoder_init = + MakeGarbageCollected<VideoDecoderInit>(); + video_decoder_init->setError(error_callback); + video_decoder_init->setOutput(output_callback); - Persistent<VideoDecoder> video_decoder = VideoDecoder::Create( - script_state, video_decoder_init, IGNORE_EXCEPTION_FOR_TESTING); + Persistent<VideoDecoder> video_decoder = VideoDecoder::Create( + script_state, video_decoder_init, IGNORE_EXCEPTION_FOR_TESTING); - if (video_decoder) { - for (auto& invocation : proto.invocations()) { - switch (invocation.Api_case()) { - case wc_fuzzer::VideoDecoderApiInvocation::kConfigure: { - VideoDecoderConfig* config = - MakeVideoDecoderConfig(invocation.configure()); + if (video_decoder) { + for (auto& invocation : proto.invocations()) { + switch (invocation.Api_case()) { + case wc_fuzzer::VideoDecoderApiInvocation::kConfigure: { + VideoDecoderConfig* config = + MakeVideoDecoderConfig(invocation.configure()); - // Use the same config to fuzz isConfigSupported(). - VideoDecoder::isConfigSupported(script_state, config, - IGNORE_EXCEPTION_FOR_TESTING); + // Use the same config to fuzz isConfigSupported(). + VideoDecoder::isConfigSupported(script_state, config, + IGNORE_EXCEPTION_FOR_TESTING); - video_decoder->configure(config, IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::VideoDecoderApiInvocation::kDecode: - video_decoder->decode( - MakeEncodedVideoChunk(script_state, - invocation.decode().chunk()), - IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::VideoDecoderApiInvocation::kFlush: { - // TODO(https://crbug.com/1119253): Fuzz whether to await resolution - // of the flush promise. - video_decoder->flush(IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::VideoDecoderApiInvocation::kReset: - video_decoder->reset(IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::VideoDecoderApiInvocation::kClose: - video_decoder->close(IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::VideoDecoderApiInvocation::API_NOT_SET: - break; + video_decoder->configure(config, IGNORE_EXCEPTION_FOR_TESTING); + break; } - - // Give other tasks a chance to run (e.g. calling our output callback). - base::RunLoop().RunUntilIdle(); + case wc_fuzzer::VideoDecoderApiInvocation::kDecode: + video_decoder->decode( + MakeEncodedVideoChunk(script_state, invocation.decode().chunk()), + IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::VideoDecoderApiInvocation::kFlush: { + // TODO(https://crbug.com/1119253): Fuzz whether to await resolution + // of the flush promise. + video_decoder->flush(IGNORE_EXCEPTION_FOR_TESTING); + break; + } + case wc_fuzzer::VideoDecoderApiInvocation::kReset: + video_decoder->reset(IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::VideoDecoderApiInvocation::kClose: + video_decoder->close(IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::VideoDecoderApiInvocation::API_NOT_SET: + break; } + + // Give other tasks a chance to run (e.g. calling our output callback). + base::RunLoop().RunUntilIdle(); } } }
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc index 90eb929..d365f126 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
@@ -1472,8 +1472,7 @@ decoder_config->setColorSpace(color_space->toJSON()); if (codec_desc.has_value()) { - auto* desc_array_buf = DOMArrayBuffer::Create(codec_desc.value().data(), - codec_desc.value().size()); + auto* desc_array_buf = DOMArrayBuffer::Create(codec_desc.value()); decoder_config->setDescription( MakeGarbageCollected<AllowSharedBufferSource>(desc_array_buf)); }
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc index fdf5263b..9e85f78 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_encoder_fuzzer.cc
@@ -37,10 +37,6 @@ auto page_holder = std::make_unique<DummyPageHolder>(); page_holder->GetFrame().GetSettings()->SetScriptEnabled(true); - // Request a full GC upon returning. - auto scoped_gc = - MakeScopedGarbageCollectionRequest(task_environment.isolate()); - // // NOTE: GC objects that need to survive iterations of the loop below // must be Persistent<>! @@ -52,92 +48,89 @@ // // Scoping Persistent<> refs so GC can collect these at the end. - { - Persistent<ScriptState> script_state = - ToScriptStateForMainWorld(&page_holder->GetFrame()); - ScriptState::Scope scope(script_state); + Persistent<ScriptState> script_state = + ToScriptStateForMainWorld(&page_holder->GetFrame()); + ScriptState::Scope scope(script_state); - Persistent<ScriptFunction> error_function = - MakeGarbageCollected<ScriptFunction>( - script_state, MakeGarbageCollected<FakeFunction>("error")); - Persistent<V8WebCodecsErrorCallback> error_callback = - V8WebCodecsErrorCallback::Create(error_function->V8Function()); - Persistent<ScriptFunction> output_function = - MakeGarbageCollected<ScriptFunction>( - script_state, MakeGarbageCollected<FakeFunction>("output")); - Persistent<V8EncodedVideoChunkOutputCallback> output_callback = - V8EncodedVideoChunkOutputCallback::Create( - output_function->V8Function()); + Persistent<ScriptFunction> error_function = + MakeGarbageCollected<ScriptFunction>( + script_state, MakeGarbageCollected<FakeFunction>("error")); + Persistent<V8WebCodecsErrorCallback> error_callback = + V8WebCodecsErrorCallback::Create(error_function->V8Function()); + Persistent<ScriptFunction> output_function = + MakeGarbageCollected<ScriptFunction>( + script_state, MakeGarbageCollected<FakeFunction>("output")); + Persistent<V8EncodedVideoChunkOutputCallback> output_callback = + V8EncodedVideoChunkOutputCallback::Create(output_function->V8Function()); - Persistent<VideoEncoderInit> video_encoder_init = - MakeGarbageCollected<VideoEncoderInit>(); - video_encoder_init->setError(error_callback); - video_encoder_init->setOutput(output_callback); + Persistent<VideoEncoderInit> video_encoder_init = + MakeGarbageCollected<VideoEncoderInit>(); + video_encoder_init->setError(error_callback); + video_encoder_init->setOutput(output_callback); - Persistent<VideoEncoder> video_encoder = VideoEncoder::Create( - script_state, video_encoder_init, IGNORE_EXCEPTION_FOR_TESTING); + Persistent<VideoEncoder> video_encoder = VideoEncoder::Create( + script_state, video_encoder_init, IGNORE_EXCEPTION_FOR_TESTING); - if (video_encoder) { - for (auto& invocation : proto.invocations()) { - switch (invocation.Api_case()) { - case wc_fuzzer::VideoEncoderApiInvocation::kConfigure: { - VideoEncoderConfig* config = - MakeVideoEncoderConfig(invocation.configure()); + if (video_encoder) { + for (auto& invocation : proto.invocations()) { + switch (invocation.Api_case()) { + case wc_fuzzer::VideoEncoderApiInvocation::kConfigure: { + VideoEncoderConfig* config = + MakeVideoEncoderConfig(invocation.configure()); - // Use the same config to fuzz isConfigSupported(). - VideoEncoder::isConfigSupported(script_state, config, - IGNORE_EXCEPTION_FOR_TESTING); + // Use the same config to fuzz isConfigSupported(). + VideoEncoder::isConfigSupported(script_state, config, + IGNORE_EXCEPTION_FOR_TESTING); - video_encoder->configure(config, IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::VideoEncoderApiInvocation::kEncode: { - VideoFrame* frame; - switch (invocation.encode().Frames_case()) { - case wc_fuzzer::EncodeVideo::kFrame: - frame = - MakeVideoFrame(script_state, invocation.encode().frame()); - break; - case wc_fuzzer::EncodeVideo::kFrameFromBuffer: - frame = MakeVideoFrame(script_state, - invocation.encode().frame_from_buffer()); - break; - default: - frame = nullptr; - break; - } - - // Often the fuzzer input will be too crazy to produce a valid frame - // (e.g. bitmap width > bitmap length). In these cases, return early - // to discourage this sort of fuzzer input. WebIDL doesn't allow - // callers to pass null, so this is not a real concern. - if (!frame) - return; - - video_encoder->encode( - frame, MakeEncodeOptions(invocation.encode().options()), - IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::VideoEncoderApiInvocation::kFlush: { - // TODO(https://crbug.com/1119253): Fuzz whether to await resolution - // of the flush promise. - video_encoder->flush(IGNORE_EXCEPTION_FOR_TESTING); - break; - } - case wc_fuzzer::VideoEncoderApiInvocation::kReset: - video_encoder->reset(IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::VideoEncoderApiInvocation::kClose: - video_encoder->close(IGNORE_EXCEPTION_FOR_TESTING); - break; - case wc_fuzzer::VideoEncoderApiInvocation::API_NOT_SET: - break; + video_encoder->configure(config, IGNORE_EXCEPTION_FOR_TESTING); + break; } + case wc_fuzzer::VideoEncoderApiInvocation::kEncode: { + VideoFrame* frame; + switch (invocation.encode().Frames_case()) { + case wc_fuzzer::EncodeVideo::kFrame: + frame = MakeVideoFrame(script_state, invocation.encode().frame()); + break; + case wc_fuzzer::EncodeVideo::kFrameFromBuffer: + frame = MakeVideoFrame(script_state, + invocation.encode().frame_from_buffer()); + break; + default: + frame = nullptr; + break; + } - // Give other tasks a chance to run (e.g. calling our output callback). - base::RunLoop().RunUntilIdle(); + // Often the fuzzer input will be too crazy to produce a valid frame + // (e.g. bitmap width > bitmap length). In these cases, return early + // to discourage this sort of fuzzer input. WebIDL doesn't allow + // callers to pass null, so this is not a real concern. + if (!frame) { + return; + } + + video_encoder->encode( + frame, MakeEncodeOptions(invocation.encode().options()), + IGNORE_EXCEPTION_FOR_TESTING); + break; + } + case wc_fuzzer::VideoEncoderApiInvocation::kFlush: { + // TODO(https://crbug.com/1119253): Fuzz whether to await resolution + // of the flush promise. + video_encoder->flush(IGNORE_EXCEPTION_FOR_TESTING); + break; + } + case wc_fuzzer::VideoEncoderApiInvocation::kReset: + video_encoder->reset(IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::VideoEncoderApiInvocation::kClose: + video_encoder->close(IGNORE_EXCEPTION_FOR_TESTING); + break; + case wc_fuzzer::VideoEncoderApiInvocation::API_NOT_SET: + break; } + + // Give other tasks a chance to run (e.g. calling our output callback). + base::RunLoop().RunUntilIdle(); } } }
diff --git a/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc b/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc index 18f03db0..3afcd9b 100644 --- a/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc +++ b/third_party/blink/renderer/modules/webcodecs/video_frame_copy_to_fuzzer.cc
@@ -28,10 +28,6 @@ auto page_holder = std::make_unique<DummyPageHolder>(); page_holder->GetFrame().GetSettings()->SetScriptEnabled(true); - // Request a full GC upon returning. - auto scoped_gc = - MakeScopedGarbageCollectionRequest(task_environment.isolate()); - ScriptState* script_state = ToScriptStateForMainWorld(&page_holder->GetFrame()); ScriptState::Scope scope(script_state);
diff --git a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc index b30cc37..b055600 100644 --- a/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc +++ b/third_party/blink/renderer/modules/websockets/web_pepper_socket_impl.cc
@@ -155,7 +155,7 @@ void WebPepperSocketImpl::DidReceiveBinaryMessage( std::unique_ptr<Vector<char>> payload) { client_->DidReceiveArrayBuffer( - WebArrayBuffer(DOMArrayBuffer::Create(payload->data(), payload->size()))); + WebArrayBuffer(DOMArrayBuffer::Create(base::as_byte_span(*payload)))); } void WebPepperSocketImpl::DidError() {
diff --git a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc index 17f56a7..0a30024 100644 --- a/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc +++ b/third_party/blink/renderer/modules/websockets/websocket_channel_impl_test.cc
@@ -540,7 +540,8 @@ auto websocket = Connect(4 * 1024, &writable, &readable, &client); ASSERT_TRUE(websocket); - DOMArrayBuffer* foo_buffer = DOMArrayBuffer::Create("foo", 3); + DOMArrayBuffer* foo_buffer = + DOMArrayBuffer::Create(base::byte_span_from_cstring("foo")); Channel()->Send(*foo_buffer, 0, 3, base::OnceClosure()); test::RunPendingTasks(); @@ -560,8 +561,10 @@ auto websocket = Connect(4 * 1024, &writable, &readable, &client); ASSERT_TRUE(websocket); - DOMArrayBuffer* foobar_buffer = DOMArrayBuffer::Create("foobar", 6); - DOMArrayBuffer* qbazux_buffer = DOMArrayBuffer::Create("qbazux", 6); + DOMArrayBuffer* foobar_buffer = + DOMArrayBuffer::Create(base::byte_span_from_cstring("foobar")); + DOMArrayBuffer* qbazux_buffer = + DOMArrayBuffer::Create(base::byte_span_from_cstring("qbazux")); Channel()->Send(*foobar_buffer, 0, 3, base::OnceClosure()); Channel()->Send(*foobar_buffer, 3, 3, base::OnceClosure()); Channel()->Send(*qbazux_buffer, 1, 3, base::OnceClosure()); @@ -593,21 +596,30 @@ auto websocket = Connect(4 * 1024, &writable, &readable, &client); ASSERT_TRUE(websocket); - constexpr int kLengthOfEachMessage = 3; + // Used to CHECK() string was not truncated at first NUL. + constexpr size_t kLengthOfEachMessage = 3; { - DOMArrayBuffer* b = DOMArrayBuffer::Create("\0ar", kLengthOfEachMessage); + auto byte_span = base::byte_span_from_cstring("\0ar"); + CHECK_EQ(kLengthOfEachMessage, byte_span.size()); + DOMArrayBuffer* b = DOMArrayBuffer::Create(byte_span); Channel()->Send(*b, 0, 3, base::OnceClosure()); } { - DOMArrayBuffer* b = DOMArrayBuffer::Create("b\0z", kLengthOfEachMessage); + auto byte_span = base::byte_span_from_cstring("b\0z"); + CHECK_EQ(kLengthOfEachMessage, byte_span.size()); + DOMArrayBuffer* b = DOMArrayBuffer::Create(byte_span); Channel()->Send(*b, 0, 3, base::OnceClosure()); } { - DOMArrayBuffer* b = DOMArrayBuffer::Create("qu\0", kLengthOfEachMessage); + auto byte_span = base::byte_span_from_cstring("qu\0"); + CHECK_EQ(kLengthOfEachMessage, byte_span.size()); + DOMArrayBuffer* b = DOMArrayBuffer::Create(byte_span); Channel()->Send(*b, 0, 3, base::OnceClosure()); } { - DOMArrayBuffer* b = DOMArrayBuffer::Create("\0\0\0", kLengthOfEachMessage); + auto byte_span = base::byte_span_from_cstring("\0\0\0"); + CHECK_EQ(kLengthOfEachMessage, byte_span.size()); + DOMArrayBuffer* b = DOMArrayBuffer::Create(byte_span); Channel()->Send(*b, 0, 3, base::OnceClosure()); } @@ -641,7 +653,8 @@ auto websocket = Connect(4 * 1024, &writable, &readable, &client); ASSERT_TRUE(websocket); - DOMArrayBuffer* b = DOMArrayBuffer::Create("\xe7\x8b\x90", 3); + DOMArrayBuffer* b = + DOMArrayBuffer::Create(base::byte_span_from_cstring("\xe7\x8b\x90")); Channel()->Send(*b, 0, 3, base::OnceClosure()); test::RunPendingTasks(); @@ -663,7 +676,8 @@ auto websocket = Connect(4 * 1024, &writable, &readable, &client); ASSERT_TRUE(websocket); - DOMArrayBuffer* b = DOMArrayBuffer::Create("\x80\xff\xe7", 3); + DOMArrayBuffer* b = + DOMArrayBuffer::Create(base::byte_span_from_cstring("\x80\xff\xe7")); Channel()->Send(*b, 0, 3, base::OnceClosure()); test::RunPendingTasks(); @@ -760,7 +774,7 @@ test::RunPendingTasks(); CallTrackingClosure closure; - const auto* b = DOMArrayBuffer::Create("hello", 5); + const auto* b = DOMArrayBuffer::Create(base::byte_span_from_cstring("hello")); EXPECT_EQ(WebSocketChannel::SendResult::kSentSynchronously, Channel()->Send(*b, 0, 5, closure.Closure())); @@ -784,7 +798,7 @@ std::string long_message(kMessageSize, 'a'); CallTrackingClosure closure; - const auto* b = DOMArrayBuffer::Create(long_message.data(), kMessageSize); + const auto* b = DOMArrayBuffer::Create(base::as_byte_span(long_message)); Channel()->Send(*b, 0, kMessageSize, base::OnceClosure()); EXPECT_EQ(WebSocketChannel::SendResult::kCallbackWillBeCalled, Channel()->Send(*b, 0, kMessageSize, closure.Closure())); @@ -812,7 +826,7 @@ std::string long_message(kMessageSize, 'a'); CallTrackingClosure closure; - const auto* b = DOMArrayBuffer::Create(long_message.data(), kMessageSize); + const auto* b = DOMArrayBuffer::Create(base::as_byte_span(long_message)); EXPECT_EQ(WebSocketChannel::SendResult::kCallbackWillBeCalled, Channel()->Send(*b, 0, kMessageSize, closure.Closure()));
diff --git a/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc b/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc index 8898859..41dca0c 100644 --- a/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc +++ b/third_party/blink/renderer/modules/webtransport/outgoing_stream_test.cc
@@ -6,6 +6,7 @@ #include <utility> +#include "base/containers/span.h" #include "base/ranges/algorithm.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" @@ -137,7 +138,7 @@ auto* script_state = scope.GetScriptState(); auto* writer = outgoing_stream->Writable()->getWriter(script_state, ASSERT_NO_EXCEPTION); - auto* chunk = DOMArrayBuffer::Create("A", 1); + auto* chunk = DOMArrayBuffer::Create(base::byte_span_from_cstring("A")); ScriptPromiseUntyped result = writer->write(script_state, ScriptValue::From(script_state, chunk), ASSERT_NO_EXCEPTION); @@ -157,7 +158,7 @@ auto* script_state = scope.GetScriptState(); auto* writer = outgoing_stream->Writable()->getWriter(script_state, ASSERT_NO_EXCEPTION); - auto* buffer = DOMArrayBuffer::Create("*B", 2); + auto* buffer = DOMArrayBuffer::Create(base::byte_span_from_cstring("*B")); // Create a view into the buffer with offset 1, ie. "B". auto* chunk = DOMUint8Array::Create(buffer, 1, 1); ScriptPromiseUntyped result = @@ -244,7 +245,7 @@ auto* script_state = scope.GetScriptState(); auto* writer = outgoing_stream->Writable()->getWriter(script_state, ASSERT_NO_EXCEPTION); - auto* chunk = DOMArrayBuffer::Create("D", 1); + auto* chunk = DOMArrayBuffer::Create(base::byte_span_from_cstring("D")); ScriptPromiseUntyped write_promise = writer->write(script_state, ScriptValue::From(script_state, chunk), ASSERT_NO_EXCEPTION);
diff --git a/third_party/blink/renderer/modules/webtransport/web_transport_test.cc b/third_party/blink/renderer/modules/webtransport/web_transport_test.cc index 05d19c3..58a6ed3b 100644 --- a/third_party/blink/renderer/modules/webtransport/web_transport_test.cc +++ b/third_party/blink/renderer/modules/webtransport/web_transport_test.cc
@@ -558,8 +558,7 @@ auto* hash = MakeGarbageCollected<WebTransportHash>(); hash->setAlgorithm("sha-256"); constexpr uint8_t kPattern[] = {0x28, 0x24, 0xa8, 0xa2}; - DOMArrayBuffer* hashValue = - DOMArrayBuffer::Create(kPattern, sizeof(kPattern)); + DOMArrayBuffer* hashValue = DOMArrayBuffer::Create(kPattern); hash->setValue( MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>(hashValue)); auto* options = MakeGarbageCollected<WebTransportOptions>(); @@ -582,7 +581,7 @@ auto* hash = MakeGarbageCollected<WebTransportHash>(); hash->setAlgorithm("sha-256"); constexpr uint8_t kPattern[6] = {0x28, 0x24, 0xa8, 0xa2, 0x44, 0xee}; - DOMArrayBuffer* buffer = DOMArrayBuffer::Create(kPattern, sizeof(kPattern)); + DOMArrayBuffer* buffer = DOMArrayBuffer::Create(kPattern); DOMUint8Array* view = DOMUint8Array::Create(buffer, 2, 3); hash->setValue(MakeGarbageCollected<V8UnionArrayBufferOrArrayBufferView>( NotShared<DOMUint8Array>(view)));
diff --git a/third_party/blink/renderer/modules/webusb/usb_device.cc b/third_party/blink/renderer/modules/webusb/usb_device.cc index cc11f00..c4bd13b3 100644 --- a/third_party/blink/renderer/modules/webusb/usb_device.cc +++ b/third_party/blink/renderer/modules/webusb/usb_device.cc
@@ -1150,7 +1150,7 @@ Vector<UsbIsochronousPacketPtr> mojo_packets) { MarkRequestComplete(resolver); - DOMArrayBuffer* buffer = DOMArrayBuffer::Create(data.data(), data.size()); + DOMArrayBuffer* buffer = DOMArrayBuffer::Create(data); HeapVector<Member<USBIsochronousInTransferPacket>> packets; packets.reserve(mojo_packets.size()); uint32_t byte_offset = 0;
diff --git a/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h b/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h index b399e42e..c0047f93 100644 --- a/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h +++ b/third_party/blink/renderer/modules/webusb/usb_in_transfer_result.h
@@ -21,8 +21,8 @@ public: static USBInTransferResult* Create(const String& status, base::span<const uint8_t> data) { - DOMDataView* data_view = DOMDataView::Create( - DOMArrayBuffer::Create(data.data(), data.size()), 0, data.size()); + DOMDataView* data_view = + DOMDataView::Create(DOMArrayBuffer::Create(data), 0, data.size()); return MakeGarbageCollected<USBInTransferResult>(status, data_view); }
diff --git a/third_party/blink/renderer/modules/xr/xr_depth_manager.cc b/third_party/blink/renderer/modules/xr/xr_depth_manager.cc index e43eb96..c671834 100644 --- a/third_party/blink/renderer/modules/xr/xr_depth_manager.cc +++ b/third_party/blink/renderer/modules/xr/xr_depth_manager.cc
@@ -106,8 +106,7 @@ } // Copy the pixel data into ArrayBuffer: - data_ = DOMArrayBuffer::Create(depth_data_->pixel_data.data(), - depth_data_->pixel_data.size()); + data_ = DOMArrayBuffer::Create(depth_data_->pixel_data); } void XRDepthManager::Trace(Visitor* visitor) const {
diff --git a/third_party/blink/renderer/platform/bindings/dom_data_store.h b/third_party/blink/renderer/platform/bindings/dom_data_store.h index bc0ce72..933c180 100644 --- a/third_party/blink/renderer/platform/bindings/dom_data_store.h +++ b/third_party/blink/renderer/platform/bindings/dom_data_store.h
@@ -33,6 +33,7 @@ #include "base/containers/contains.h" #include "third_party/blink/renderer/platform/bindings/dom_wrapper_world.h" +#include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/bindings/trace_wrapper_v8_reference.h" #include "third_party/blink/renderer/platform/bindings/wrapper_type_info.h" @@ -89,8 +90,22 @@ v8::Local<v8::Object> v8_receiver, const ScriptWrappable* blink_receiver); + // Returns the wrapper for `object` in the world corresponding to + // `script_state`. Can be used from any world. Cross-checks the world in + // `script_state` against the current world used by the Isolate (in the script + // state). + // + // Prefer this method over the version taking the Isolate parameter for + // performance reasons. + static inline v8::MaybeLocal<v8::Object> GetWrapper( + ScriptState* script_state, + const ScriptWrappable* object); + // Returns the wrapper for `object` in the world corresponding to `isolate`. // Can be used from any world. Will only consider the current world. + // + // Prefer the method taking the ScriptState if possible for performance + // reasons. static inline v8::MaybeLocal<v8::Object> GetWrapper( v8::Isolate* isolate, const ScriptWrappable* object); @@ -310,12 +325,24 @@ return Current(isolate).Get(isolate, object); } +// static +v8::MaybeLocal<v8::Object> DOMDataStore::GetWrapper( + ScriptState* script_state, + const ScriptWrappable* object) { + DOMDataStore& store = script_state->World().DomDataStore(); + auto* isolate = script_state->GetIsolate(); + return store.Get(isolate, object); +} + template <bool entered_context> v8::MaybeLocal<v8::Object> DOMDataStore::Get(v8::Isolate* isolate, const ScriptWrappable* object) { + DCHECK(!CanUseInlineStorageForWrapper() || can_use_inline_storage_); if (can_use_inline_storage_) { - return entered_context ? GetInlineStorage(isolate, object).Get(isolate) - : GetUncheckedInlineStorage(object).Get(isolate); + // The following will crash if no context is entered. This is by design. The + // validation can be skipped with `entered_context`. + DCHECK(!entered_context || Current(isolate).can_use_inline_storage_); + return GetUncheckedInlineStorage(object).Get(isolate); } if (const auto it = wrapper_map_.find(object); it != wrapper_map_.end()) { return it->value.Get(isolate);
diff --git a/third_party/blink/renderer/platform/bindings/frozen_array_base.cc b/third_party/blink/renderer/platform/bindings/frozen_array_base.cc index 35ded4e..53271c66 100644 --- a/third_party/blink/renderer/platform/bindings/frozen_array_base.cc +++ b/third_party/blink/renderer/platform/bindings/frozen_array_base.cc
@@ -42,8 +42,8 @@ v8::Local<v8::Value> FrozenArrayBase::ToV8(ScriptState* script_state) { v8::Local<v8::Object> wrapper; - if (DOMDataStore::GetWrapper(script_state->GetIsolate(), this) - .ToLocal(&wrapper)) [[likely]] { + if (DOMDataStore::GetWrapper(script_state, this).ToLocal(&wrapper)) + [[likely]] { return wrapper; }
diff --git a/third_party/blink/renderer/platform/bindings/script_wrappable.cc b/third_party/blink/renderer/platform/bindings/script_wrappable.cc index 946bee0..7420860e 100644 --- a/third_party/blink/renderer/platform/bindings/script_wrappable.cc +++ b/third_party/blink/renderer/platform/bindings/script_wrappable.cc
@@ -21,8 +21,8 @@ v8::Local<v8::Value> ScriptWrappable::ToV8(ScriptState* script_state) { v8::Local<v8::Object> wrapper; - if (DOMDataStore::GetWrapper(script_state->GetIsolate(), this) - .ToLocal(&wrapper)) [[likely]] { + if (DOMDataStore::GetWrapper(script_state, this).ToLocal(&wrapper)) + [[likely]] { return wrapper; } return Wrap(script_state);
diff --git a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc index cd03f5d..2e431d4 100644 --- a/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc +++ b/third_party/blink/renderer/platform/graphics/web_graphics_context_3d_video_frame_pool.cc
@@ -34,11 +34,14 @@ namespace { -#if BUILDFLAG(IS_WIN) BASE_FEATURE(kUseCopyToGpuMemoryBufferAsync, "UseCopyToGpuMemoryBufferAsync", - base::FEATURE_ENABLED_BY_DEFAULT); +#if BUILDFLAG(IS_WIN) + base::FEATURE_ENABLED_BY_DEFAULT +#else + base::FEATURE_DISABLED_BY_DEFAULT #endif +); class Context : public media::RenderableGpuMemoryBufferVideoFramePool::Context { public: @@ -206,13 +209,14 @@ query_id, std::move(callback))); } -#if BUILDFLAG(IS_WIN) void CopyToGpuMemoryBuffer( base::WeakPtr<blink::WebGraphicsContext3DProviderWrapper> ctx_wrapper, media::VideoFrame* dst_frame, base::OnceClosure callback) { CHECK(dst_frame->HasMappableGpuBuffer()); CHECK(!dst_frame->HasNativeGpuMemoryBuffer()); + CHECK_EQ(dst_frame->shared_image_format_type(), + media::SharedImageFormatType::kSharedImageFormat); DCHECK(ctx_wrapper); auto* context_provider = ctx_wrapper->ContextProvider(); @@ -229,10 +233,7 @@ DCHECK(sii); const bool use_async_copy = - base::FeatureList::IsEnabled(kUseCopyToGpuMemoryBufferAsync) && - dst_frame->shared_image_format_type() == - media::SharedImageFormatType::kSharedImageFormat; - + base::FeatureList::IsEnabled(kUseCopyToGpuMemoryBufferAsync); if (use_async_copy) { auto copy_to_gmb_done_lambda = [](base::OnceClosure callback, bool success) { @@ -283,7 +284,6 @@ std::move(callback)); } } -#endif } // namespace bool WebGraphicsContext3DVideoFramePool::CopyRGBATextureToVideoFrame( @@ -355,17 +355,18 @@ }, std::move(dst_frame), std::move(callback), flow_id)); -#if BUILDFLAG(IS_WIN) - // For shared memory GMBs on Windows we needed to explicitly request a copy - // from the shared image GPU texture to the GMB. - CopyToGpuMemoryBuffer(weak_context_provider_, dst_frame_ptr, + if (!dst_frame_ptr->HasNativeGpuMemoryBuffer()) { + // For shared memory GMBs we needed to explicitly request a copy + // from the shared image GPU texture to the GMB. + CopyToGpuMemoryBuffer(weak_context_provider_, dst_frame_ptr, + wrapped_callback->callback()); + } else { + // QueryEXT functions are used to make sure that + // CopyRGBATextureToVideoFrame() texture copy is complete before we access + // GMB data. + SignalGpuCompletion(weak_context_provider_, GL_COMMANDS_COMPLETED_CHROMIUM, wrapped_callback->callback()); -#else - // QueryEXT functions are used to make sure that CopyRGBATextureToVideoFrame() - // texture copy is complete before we access GMB data. - SignalGpuCompletion(weak_context_provider_, GL_COMMANDS_COMPLETED_CHROMIUM, - wrapped_callback->callback()); -#endif + } // Cleanup stale callbacks before adding a new one. It's ok to loop until the // first non-cancelled callback since they should execute in order anyway.
diff --git a/third_party/blink/renderer/platform/heap/heap_test_platform.h b/third_party/blink/renderer/platform/heap/heap_test_platform.h index 8488e70b..0bc5de1 100644 --- a/third_party/blink/renderer/platform/heap/heap_test_platform.h +++ b/third_party/blink/renderer/platform/heap/heap_test_platform.h
@@ -54,7 +54,8 @@ return platform_->NumberOfWorkerThreads(); } std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner( - v8::Isolate* isolate) final { + v8::Isolate* isolate, + v8::TaskPriority priority) final { // Provides task runner that allows for incremental tasks even in detached // mode. return task_runner_;
diff --git a/third_party/blink/renderer/platform/loader/fetch/media_timing.h b/third_party/blink/renderer/platform/loader/fetch/media_timing.h index 283e8055..15131e4 100644 --- a/third_party/blink/renderer/platform/loader/fetch/media_timing.h +++ b/third_party/blink/renderer/platform/loader/fetch/media_timing.h
@@ -68,10 +68,6 @@ virtual base::TimeTicks LoadStart() const = 0; virtual base::TimeTicks LoadEnd() const = 0; - - virtual bool IsLoadedFromMemoryCache() const = 0; - - virtual bool IsPreloadedWithEarlyHints() const = 0; }; } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource.h b/third_party/blink/renderer/platform/loader/fetch/resource.h index cddc991..11192744 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource.h
@@ -445,10 +445,6 @@ bool IsPreloadedByEarlyHints() const { return is_preloaded_by_early_hints_; } - void SetIsLoadedFromMemoryCache() { is_loaded_from_memory_cache_ = true; } - - bool IsLoadedFromMemoryCache() { return is_loaded_from_memory_cache_; } - virtual std::unique_ptr<BackgroundResponseProcessorFactory> MaybeCreateBackgroundResponseProcessorFactory(); @@ -564,7 +560,6 @@ bool is_unused_preload_ = false; bool stale_revalidation_started_ = false; bool is_preloaded_by_early_hints_ = false; - bool is_loaded_from_memory_cache_ = false; enum class RevalidationStatus { kNoRevalidatingOrFailed, // not in revalidate procedure or
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 d3a1a4c2..307570d 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
@@ -378,25 +378,32 @@ // PrepareRequestForCacheAccess() is called first. If the resource can not be // served from the cache, UpgradeForLoaderIfNecessary() is called to complete // the necessary steps before loading. -class ResourceFetcher::ResourcePrepareHelper { +class ResourceFetcher::ResourcePrepareHelper final + : public ResourceRequestContext { STACK_ALLOCATED(); public: - ResourcePrepareHelper(ResourceFetcher& fetcher, FetchParameters& params); + ResourcePrepareHelper(ResourceFetcher& fetcher, + FetchParameters& params, + const ResourceFactory& factory); std::optional<ResourceRequestBlockedReason> PrepareRequestForCacheAccess( - const ResourceFactory& factory, WebScopedVirtualTimePauser& pauser); - void UpgradeForLoaderIfNecessary(const ResourceFactory& factory, - WebScopedVirtualTimePauser& pauser); + void UpgradeForLoaderIfNecessary(WebScopedVirtualTimePauser& pauser); bool WasUpgradeForLoaderCalled() const { return was_upgrade_for_loader_called_; } + // ResourceRequestContext: + ResourceLoadPriority ComputeLoadPriority( + const FetchParameters& params) override; + void RecordTrace() override; + private: ResourceFetcher& fetcher_; FetchParameters& params_; KURL bundle_url_for_uuid_resources_; + const ResourceFactory& factory_; const bool has_transparent_placeholder_image_; bool was_upgrade_for_loader_called_ = true; #if DCHECK_IS_ON() @@ -691,18 +698,6 @@ return priority; } -ResourceLoadPriority ResourceFetcher::ComputeLoadPriorityHelper( - ResourceType resource_type, - ResourcePriority::VisibilityStatus visibility, - const FetchParameters& params) { - return ComputeLoadPriority( - resource_type, params.GetResourceRequest(), visibility, params.Defer(), - params.GetSpeculativePreloadType(), params.GetRenderBlockingBehavior(), - params.GetScriptType(), params.IsLinkPreload(), params.GetResourceWidth(), - params.GetResourceHeight(), params.IsPotentiallyLCPElement(), - params.IsPotentiallyLCPInfluencer()); -} - // Boost the priority for the first N not-small images from the preload scanner ResourceLoadPriority ResourceFetcher::AdjustImagePriority( const ResourceLoadPriority priority_so_far, @@ -999,7 +994,6 @@ } } } - resource->SetIsLoadedFromMemoryCache(); } Resource* ResourceFetcher::CreateResourceForStaticData( @@ -1256,57 +1250,6 @@ return std::nullopt; } -std::optional<ResourceRequestBlockedReason> ResourceFetcher::PrepareRequest( - FetchParameters& params, - const ResourceFactory& factory, - WebScopedVirtualTimePauser& virtual_time_pauser, - const KURL& bundle_url_for_uuid_resources) { - ResourceRequest& resource_request = params.MutableResourceRequest(); - // This case is handled in UpdateRequestForTransparentPlaceholderImage(). - DCHECK(!(IsSimplifyLoadingTransparentPlaceholderImageEnabled() && - (resource_request.GetKnownTransparentPlaceholderImageIndex() != - kNotFound))); - - ResourceType resource_type = factory.GetType(); - const ResourceLoaderOptions& options = params.Options(); - - DCHECK(options.synchronous_policy == kRequestAsynchronously || - resource_type == ResourceType::kRaw || - resource_type == ResourceType::kXSLStyleSheet); - - params.OverrideContentType(factory.ContentType()); - - if (RuntimeEnabledFeatures:: - MinimimalResourceRequestPrepBeforeCacheLookupEnabled()) { - UpgradeResourceRequestForLoaderNew( - resource_type, params, Context(), virtual_time_pauser, - WTF::BindOnce([](const ResourceRequest& r) { - TRACE_EVENT_NESTABLE_ASYNC_INSTANT1( - TRACE_DISABLED_BY_DEFAULT("network"), "ResourcePrioritySet", - TRACE_ID_WITH_SCOPE("BlinkResourceID", - TRACE_ID_LOCAL(r.InspectorId())), - "priority", r.Priority()); - })); - return std::nullopt; - } - - return PrepareResourceRequest( - resource_type, properties_->GetFetchClientSettingsObject(), params, - Context(), virtual_time_pauser, - WTF::BindOnce( - &ResourceFetcher::ComputeLoadPriorityHelper, - // This callback will be run synchronously, so no cyclic dependency. - WrapPersistent(this), resource_type, ResourcePriority::kNotVisible), - WTF::BindOnce([](const ResourceRequest& r) { - TRACE_EVENT_NESTABLE_ASYNC_INSTANT1( - TRACE_DISABLED_BY_DEFAULT("network"), "ResourcePrioritySet", - TRACE_ID_WITH_SCOPE("BlinkResourceID", - TRACE_ID_LOCAL(r.InspectorId())), - "priority", r.Priority()); - }), - bundle_url_for_uuid_resources); -} - KURL ResourceFetcher::PrepareRequestForWebBundle( ResourceRequest& resource_request) const { if (resource_request.GetWebBundleTokenParams()) { @@ -1416,9 +1359,9 @@ WebScopedVirtualTimePauser pauser; - ResourcePrepareHelper prepare_helper(*this, params); + ResourcePrepareHelper prepare_helper(*this, params, factory); std::optional<ResourceRequestBlockedReason> blocked_reason = - prepare_helper.PrepareRequestForCacheAccess(factory, pauser); + prepare_helper.PrepareRequestForCacheAccess(pauser); if (blocked_reason) { auto* resource = ResourceForBlockedRequest(params, factory, blocked_reason.value(), client); @@ -1444,7 +1387,7 @@ // deferred. if (!is_stale_revalidation && (archive_ || (is_data_url && defer_policy != DeferPolicy::kDefer))) { - prepare_helper.UpgradeForLoaderIfNecessary(factory, pauser); + prepare_helper.UpgradeForLoaderIfNecessary(pauser); resource = CreateResourceForStaticData(params, factory); if (resource) { policy = @@ -1467,12 +1410,12 @@ if (!prepare_helper.WasUpgradeForLoaderCalled() && preloads_.find(PreloadKey(params.Url(), resource_type)) != preloads_.end()) { - prepare_helper.UpgradeForLoaderIfNecessary(factory, pauser); + prepare_helper.UpgradeForLoaderIfNecessary(pauser); } resource = MatchPreload(params, resource_type); if (resource) { policy = RevalidationPolicy::kUse; - prepare_helper.UpgradeForLoaderIfNecessary(factory, pauser); + prepare_helper.UpgradeForLoaderIfNecessary(pauser); // If |params| is for a blocking resource and a preloaded resource is // found, we may need to make it block the onload event. MakePreloadedResourceBlockOnloadIfNeeded(resource, params); @@ -1498,7 +1441,7 @@ } if (!prepare_helper.WasUpgradeForLoaderCalled() && policy != RevalidationPolicy::kUse) { - prepare_helper.UpgradeForLoaderIfNecessary(factory, pauser); + prepare_helper.UpgradeForLoaderIfNecessary(pauser); } UpdateMemoryCacheStats( @@ -1594,7 +1537,7 @@ // If a load is necessary, force upgrade so that the resource width is // updated. This is a bit heavyweight, and could be optimized by adding // a new function specifically to add the width. - prepare_helper.UpgradeForLoaderIfNecessary(factory, pauser); + prepare_helper.UpgradeForLoaderIfNecessary(pauser); } // The resource width can change after the request was initially created. @@ -3458,9 +3401,11 @@ ResourceFetcher::ResourcePrepareHelper::ResourcePrepareHelper( ResourceFetcher& fetcher, - FetchParameters& params) + FetchParameters& params, + const ResourceFactory& factory) : fetcher_(fetcher), params_(params), + factory_(factory), has_transparent_placeholder_image_( fetcher.IsSimplifyLoadingTransparentPlaceholderImageEnabled() && (params.GetResourceRequest() @@ -3468,7 +3413,6 @@ std::optional<ResourceRequestBlockedReason> ResourceFetcher::ResourcePrepareHelper::PrepareRequestForCacheAccess( - const ResourceFactory& factory, WebScopedVirtualTimePauser& pauser) { #if DCHECK_IS_ON() DCHECK(!determined_initial_blocked_reason_); @@ -3480,37 +3424,38 @@ ResourceRequest& resource_request = params_.MutableResourceRequest(); bundle_url_for_uuid_resources_ = fetcher_.PrepareRequestForWebBundle(resource_request); - auto compute_load_priority_callback = WTF::BindOnce( - &ResourceFetcher::ComputeLoadPriorityHelper, - // This callback will be run synchronously, so no cyclic dependency. - WrapPersistent(&fetcher_), factory.GetType(), - ResourcePriority::kNotVisible); + + ResourceType resource_type = factory_.GetType(); + const ResourceLoaderOptions& options = params_.Options(); + + DCHECK(options.synchronous_policy == kRequestAsynchronously || + resource_type == ResourceType::kRaw || + resource_type == ResourceType::kXSLStyleSheet); if (!RuntimeEnabledFeatures:: MinimimalResourceRequestPrepBeforeCacheLookupEnabled()) { - return fetcher_.PrepareRequest(params_, factory, pauser, - bundle_url_for_uuid_resources_); + params_.OverrideContentType(factory_.ContentType()); + return PrepareResourceRequest( + resource_type, fetcher_.properties_->GetFetchClientSettingsObject(), + params_, fetcher_.Context(), pauser, *this, + bundle_url_for_uuid_resources_); } std::optional<ResourceRequestBlockedReason> blocked_reason = PrepareResourceRequestForCacheAccess( - factory.GetType(), - fetcher_.properties_->GetFetchClientSettingsObject(), - bundle_url_for_uuid_resources_, - std::move(compute_load_priority_callback), fetcher_.Context(), - params_); + resource_type, fetcher_.properties_->GetFetchClientSettingsObject(), + bundle_url_for_uuid_resources_, *this, fetcher_.Context(), params_); if (blocked_reason) { return blocked_reason; } was_upgrade_for_loader_called_ = false; if (params_.GetResourceRequest().RequiresUpgradeForLoader()) { - UpgradeForLoaderIfNecessary(factory, pauser); + UpgradeForLoaderIfNecessary(pauser); } return std::nullopt; } void ResourceFetcher::ResourcePrepareHelper::UpgradeForLoaderIfNecessary( - const ResourceFactory& factory, WebScopedVirtualTimePauser& pauser) { #if DCHECK_IS_ON() DCHECK(determined_initial_blocked_reason_); @@ -3519,8 +3464,30 @@ return; } was_upgrade_for_loader_called_ = true; - fetcher_.PrepareRequest(params_, factory, pauser, - bundle_url_for_uuid_resources_); + params_.OverrideContentType(factory_.ContentType()); + UpgradeResourceRequestForLoaderNew(factory_.GetType(), params_, + fetcher_.Context(), *this, pauser); +} + +ResourceLoadPriority +ResourceFetcher::ResourcePrepareHelper::ComputeLoadPriority( + const FetchParameters& params) { + return fetcher_.ComputeLoadPriority( + factory_.GetType(), params.GetResourceRequest(), + ResourcePriority::kNotVisible, params.Defer(), + params.GetSpeculativePreloadType(), params.GetRenderBlockingBehavior(), + params.GetScriptType(), params.IsLinkPreload(), params.GetResourceWidth(), + params.GetResourceHeight(), params.IsPotentiallyLCPElement(), + params.IsPotentiallyLCPInfluencer()); +} + +void ResourceFetcher::ResourcePrepareHelper::RecordTrace() { + const ResourceRequest& resource_request = params_.GetResourceRequest(); + TRACE_EVENT_NESTABLE_ASYNC_INSTANT1( + TRACE_DISABLED_BY_DEFAULT("network"), "ResourcePrioritySet", + TRACE_ID_WITH_SCOPE("BlinkResourceID", + TRACE_ID_LOCAL(resource_request.InspectorId())), + "priority", resource_request.Priority()); } } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h index 5ec7f86e..98e04b4 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.h
@@ -444,11 +444,6 @@ const std::optional<float> resource_height = std::nullopt, bool is_potentially_lcp_element = false, bool is_potentially_lcp_influencer = false); - // A helper that uses `params` to fill out other remaining parameters. - ResourceLoadPriority ComputeLoadPriorityHelper( - ResourceType, - ResourcePriority::VisibilityStatus, - const FetchParameters& params); ResourceLoadPriority AdjustImagePriority( const ResourceLoadPriority priority_so_far, const ResourceType type, @@ -462,15 +457,6 @@ std::optional<ResourceRequestBlockedReason> UpdateRequestForTransparentPlaceholderImage(FetchParameters& params); - // |virtual_time_pauser| is an output parameter. PrepareRequest may - // create a new WebScopedVirtualTimePauser and set it to - // |virtual_time_pauser|. - std::optional<ResourceRequestBlockedReason> PrepareRequest( - FetchParameters&, - const ResourceFactory&, - WebScopedVirtualTimePauser& virtual_time_pauser, - const KURL& bundle_url_for_uuid_resources); - Resource* CreateResourceForStaticData(const FetchParameters&, const ResourceFactory&); Resource* ResourceForBlockedRequest(const FetchParameters&,
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.cc b/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.cc index cf4c769..f57c3ab 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.cc
@@ -149,8 +149,7 @@ FetchParameters& params, FetchContext& context, WebScopedVirtualTimePauser& virtual_time_pauser, - ResourceLoadPriorityCalculator compute_load_priority_callback, - ResourceRequestTraceCallback trace_callback, + ResourceRequestContext& resource_request_context, const KURL& bundle_url_for_uuid_resources) { ResourceRequest& resource_request = params.MutableResourceRequest(); const ResourceLoaderOptions& options = params.Options(); @@ -195,10 +194,9 @@ ResourceLoadPriority computed_load_priority = resource_request.Priority(); // We should only compute the priority for ResourceRequests whose priority has // not already been set. - if (!resource_request.PriorityHasBeenSet() && - compute_load_priority_callback) { + if (!resource_request.PriorityHasBeenSet()) { computed_load_priority = - std::move(compute_load_priority_callback).Run(params); + resource_request_context.ComputeLoadPriority(params); } CHECK_NE(computed_load_priority, ResourceLoadPriority::kUnresolved); resource_request.SetPriority(computed_load_priority); @@ -243,9 +241,7 @@ context.AddAdditionalRequestHeaders(resource_request); - if (trace_callback) { - std::move(trace_callback).Run(resource_request); - } + resource_request_context.RecordTrace(); const std::optional<ResourceRequestBlockedReason> blocked_reason = context.CanRequest(resource_type, resource_request, @@ -282,8 +278,8 @@ ResourceType resource_type, FetchParameters& params, FetchContext& context, - WebScopedVirtualTimePauser& virtual_time_pauser, - ResourceRequestTraceCallback trace_callback) { + ResourceRequestContext& resource_request_context, + WebScopedVirtualTimePauser& virtual_time_pauser) { DCHECK(RuntimeEnabledFeatures:: MinimimalResourceRequestPrepBeforeCacheLookupEnabled()); ResourceRequest& resource_request = params.MutableResourceRequest(); @@ -317,9 +313,7 @@ context.AddAdditionalRequestHeaders(resource_request); - if (trace_callback) { - std::move(trace_callback).Run(resource_request); - } + resource_request_context.RecordTrace(); if (context.CalculateIfAdSubresource(resource_request, std::nullopt /* alias_url */, @@ -341,7 +335,7 @@ ResourceType resource_type, const FetchClientSettingsObject& fetch_client_settings_object, const KURL& bundle_url_for_uuid_resources, - ResourceLoadPriorityCalculator compute_load_priority_callback, + ResourceRequestContext& resource_request_context, FetchContext& context, FetchParameters& params) { DCHECK(RuntimeEnabledFeatures:: @@ -385,10 +379,9 @@ ResourceLoadPriority computed_load_priority = resource_request.Priority(); // We should only compute the priority for ResourceRequests whose priority has // not already been set. - if (!resource_request.PriorityHasBeenSet() && - compute_load_priority_callback) { + if (!resource_request.PriorityHasBeenSet()) { computed_load_priority = - std::move(compute_load_priority_callback).Run(params); + resource_request_context.ComputeLoadPriority(params); } CHECK_NE(computed_load_priority, ResourceLoadPriority::kUnresolved); resource_request.SetPriority(computed_load_priority);
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.h b/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.h index ba8ad9d..bfb8c910 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_request_utils.h
@@ -7,7 +7,6 @@ #include <optional> -#include "base/functional/callback.h" #include "third_party/blink/public/platform/resource_request_blocked_reason.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/renderer/platform/loader/fetch/fetch_client_settings_object.h" @@ -38,14 +37,21 @@ mojom::blink::FetchPriorityHint fetch_priority_hint, RenderBlockingBehavior render_blocking_behavior); -// A callback type to compute ResourceLoadPriority for the ResourceRequest from -// the given FetchParameters. Returns the computed result. -using ResourceLoadPriorityCalculator = - base::OnceCallback<ResourceLoadPriority(const FetchParameters&)>; +// Used by PrepareResourceRequestForCacheAccess() and +// UpgradeResourceRequestForLoader(). +class ResourceRequestContext { + public: + // Computes the ResourceLoadPriority. This is called if the priority was not + // set. + virtual ResourceLoadPriority ComputeLoadPriority( + const FetchParameters& params) = 0; -// A callback type to enable tracing using the given ResourceRequest. -using ResourceRequestTraceCallback = - base::OnceCallback<void(const ResourceRequest&)>; + // Called to record a trace. + virtual void RecordTrace() = 0; + + protected: + virtual ~ResourceRequestContext() = default; +}; // Prepares the underlying ResourceRequest for `params` with enough information // to do a cache lookup. If a cached value is not used, @@ -63,7 +69,7 @@ ResourceType type, const FetchClientSettingsObject& fetch_client_settings_object, const KURL& bundle_url_for_uuid_resources, - ResourceLoadPriorityCalculator compute_load_priority_callback, + ResourceRequestContext& resource_request_context, FetchContext& context, FetchParameters& params); @@ -87,15 +93,14 @@ FetchParameters& params, FetchContext& context, WebScopedVirtualTimePauser& virtual_time_pauser, - ResourceLoadPriorityCalculator compute_load_priority_callback, - ResourceRequestTraceCallback trace_callback, + ResourceRequestContext& resource_request_context, const KURL& bundle_url_for_uuid_resources); BLINK_PLATFORM_EXPORT void UpgradeResourceRequestForLoaderNew( ResourceType resource_type, FetchParameters& params, FetchContext& context, - WebScopedVirtualTimePauser& virtual_time_pauser, - ResourceRequestTraceCallback trace_callback); + ResourceRequestContext& resource_request_context, + WebScopedVirtualTimePauser& virtual_time_pauser); } // namespace blink
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 416ee94c..d9c228f 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -2521,9 +2521,6 @@ status: "test", }, { - name: "LCPMultipleUpdatesPerElement", - }, - { name: "LegacyWindowsDWriteFontFallback", // Enabled by features::kLegacyWindowsDWriteFontFallback; base_feature: "none", @@ -4377,12 +4374,6 @@ }, }, { - // Makes root scrollbars follow the preferred color scheme by default. - // https://chromestatus.com/feature/5089486318075904 - name: "UsedColorSchemeRootScrollbars", - status: "stable", - }, - { name: "UserActivationSameOriginVisibility", base_feature: "none", public: true,
diff --git a/third_party/blink/renderer/platform/testing/main_thread_isolate.cc b/third_party/blink/renderer/platform/testing/main_thread_isolate.cc index e699fe6..7ffd2570 100644 --- a/third_party/blink/renderer/platform/testing/main_thread_isolate.cc +++ b/third_party/blink/renderer/platform/testing/main_thread_isolate.cc
@@ -8,6 +8,7 @@ #include "third_party/blink/public/web/blink.h" #include "third_party/blink/renderer/platform/bindings/v8_per_isolate_data.h" #include "third_party/blink/renderer/platform/heap/thread_state.h" +#include "third_party/blink/renderer/platform/loader/fetch/memory_cache.h" #include "third_party/blink/renderer/platform/scheduler/public/thread_scheduler.h" namespace blink::test { @@ -18,6 +19,7 @@ MainThreadIsolate::~MainThreadIsolate() { CHECK_NE(nullptr, isolate_); + MemoryCache::Get()->EvictResources(); isolate()->ClearCachesForTesting(); V8PerIsolateData::From(isolate())->ClearScriptRegexpContext(); ThreadState::Current()->CollectAllGarbageForTesting();
diff --git a/third_party/blink/renderer/platform/testing/paint_test_configurations.h b/third_party/blink/renderer/platform/testing/paint_test_configurations.h index 0aa7730..b1e0bd7 100644 --- a/third_party/blink/renderer/platform/testing/paint_test_configurations.h +++ b/third_party/blink/renderer/platform/testing/paint_test_configurations.h
@@ -18,16 +18,14 @@ namespace blink { inline constexpr unsigned kUnderInvalidationChecking = 1 << 0; -inline constexpr unsigned kUsedColorSchemeRootScrollbars = 1 << 1; -inline constexpr unsigned kFluentScrollbar = 1 << 2; -inline constexpr unsigned kHitTestOpaqueness = 1 << 3; -inline constexpr unsigned kElementCapture = 1 << 4; -inline constexpr unsigned kRasterInducingScroll = 1 << 5; +inline constexpr unsigned kFluentScrollbar = 1 << 1; +inline constexpr unsigned kHitTestOpaqueness = 1 << 2; +inline constexpr unsigned kElementCapture = 1 << 3; +inline constexpr unsigned kRasterInducingScroll = 1 << 4; class PaintTestConfigurations : public testing::WithParamInterface<unsigned>, private ScopedPaintUnderInvalidationCheckingForTest, - private ScopedUsedColorSchemeRootScrollbarsForTest, private ScopedHitTestOpaquenessForTest, private ScopedFastNonCompositedScrollHitTestForTest, private ScopedElementCaptureForTest, @@ -36,8 +34,6 @@ PaintTestConfigurations() : ScopedPaintUnderInvalidationCheckingForTest(GetParam() & kUnderInvalidationChecking), - ScopedUsedColorSchemeRootScrollbarsForTest( - GetParam() & kUsedColorSchemeRootScrollbars), ScopedHitTestOpaquenessForTest(GetParam() & kHitTestOpaqueness), ScopedFastNonCompositedScrollHitTestForTest(GetParam() & kHitTestOpaqueness), @@ -67,8 +63,8 @@ base::test::ScopedFeatureList feature_list_; }; -#define PAINT_TEST_SUITE_P_VALUES \ - 0, kUsedColorSchemeRootScrollbars, kFluentScrollbar, kHitTestOpaqueness, \ +#define PAINT_TEST_SUITE_P_VALUES \ + 0, kFluentScrollbar, kHitTestOpaqueness, \ kRasterInducingScroll | kHitTestOpaqueness #define INSTANTIATE_PAINT_TEST_SUITE_P(test_class) \
diff --git a/third_party/blink/renderer/platform/testing/task_environment.cc b/third_party/blink/renderer/platform/testing/task_environment.cc index 562e8fe2..1b78fae 100644 --- a/third_party/blink/renderer/platform/testing/task_environment.cc +++ b/third_party/blink/renderer/platform/testing/task_environment.cc
@@ -14,12 +14,11 @@ namespace blink::test { TaskEnvironment::~TaskEnvironment() { - RunUntilIdle(); - // Run a full GC before resetting the main thread overrider. This ensures that // we can properly clean up objects like PerformanceMonitor that need to call // MainThreadImpl::RemoveTaskTimeObserver(). ThreadState::Current()->CollectAllGarbageForTesting(); + RunUntilIdle(); main_thread_overrider_.reset(); main_thread_isolate_.reset();
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 2ccfb6f..b1c77f5 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -483,8 +483,6 @@ crbug.com/730267 [ Mac11 ] virtual/gpu-rasterization/images/yuv-decode-eligible/webp-no-color-profile-lossy.html [ Failure Pass Timeout ] # Flaky virtual/threaded-prefer-compositing tests -crbug.com/664858 virtual/threaded-prefer-compositing/fast/scroll-behavior/overflow-scroll-animates.html [ Crash Failure Pass Timeout ] -crbug.com/664858 virtual/threaded-prefer-compositing/fast/scroll-behavior/overflow-scroll-root-frame-animates.html [ Crash Failure Pass Timeout ] crbug.com/664858 virtual/threaded-prefer-compositing/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-added.html [ Crash Failure Pass Timeout ] crbug.com/574283 virtual/threaded-prefer-compositing/fast/scroll-behavior/smooth-scroll/main-thread-scrolling-reason-correctness.html [ Crash Failure Pass Timeout ] crbug.com/574283 virtual/threaded-prefer-compositing/fast/scroll-behavior/smooth-scroll/mousewheel-scroll-interrupted.html [ Crash Failure Pass Timeout ] @@ -2631,6 +2629,8 @@ crbug.com/362556327 [ Mac ] external/wpt/pointerevents/coalesced_events_attributes_under_load.https.optional.html?pen [ Skip Timeout ] # ====== New tests from wpt-importer added here ====== +crbug.com/362784002 external/wpt/css/css-text-decor/text-underline-offset-calc.html [ Failure ] +crbug.com/362784002 external/wpt/css/css-text-decor/text-underline-offset-percentage.html [ Failure ] crbug.com/362622397 [ Win ] external/wpt/pointerevents/pointerevent_pointercapture_in_frame.html?pen [ Timeout ] crbug.com/361617757 external/wpt/css/css-masking/clip-path/clip-path-circle-closest-corner.html [ Failure ] crbug.com/361617757 external/wpt/css/css-masking/clip-path/clip-path-circle-farthest-corner.html [ Failure ] @@ -4076,9 +4076,6 @@ crbug.com/874162 [ Debug Mac13-arm64 ] fast/events/middleClickAutoscroll-nested-divs-forbidden.html [ Crash Failure Pass Timeout ] crbug.com/874162 [ Mac Release ] fast/events/middleClickAutoscroll-nested-divs-forbidden.html [ Crash Failure Pass Timeout ] -# Passes in threaded mode, fails without it. This is a real bug. -crbug.com/1112183 fast/scrolling/autoscroll-iframe-no-scrolling.html [ Failure ] - # Sheriff 2018-09-10 crbug.com/881207 fast/js/regress/splice-to-remove.html [ Pass Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index d212ff8..6893e7d 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -24,6 +24,33 @@ " expire, use `never`. A bug will be filed for removing expired suites. ", { + "prefix": "verify-minimal-resource-request-kill-switch", + "platforms": ["Linux"], + "bases": [ + "http/tests/cache", + "http/tests/devtools", + "http/tests/fetch", + "http/tests/inspector-protocol", + "http/tests/loading", + "http/tests/prefetch", + "http/tests/preload", + "http/tests/security", + "http/tests/streams", + "http/tests/xmlhttprequest", + "external/wpt/content-security-policy/", + "external/wpt/cors", + "external/wpt/fetch", + "external/wpt/loading", + "external/wpt/preload", + "external/wpt/streams", + "external/wpt/webtransport"], + "args": [ + "--disable-features=MinimimalResourceRequestPrepBeforeCacheLookup" + ], + "owners": ["sky@google.com"], + "expires": "Nov 1, 2024" + }, + { "prefix": "pna-permission", "platforms": ["Linux", "Mac", "Win"], "bases": ["external/wpt/fetch/private-network-access"], @@ -280,6 +307,7 @@ }, { "prefix": "gpu-rasterization", + "owners": ["vasilyt@chromium.org", "chrome-gpu@google.com"], "platforms": ["Linux", "Mac", "Win"], "bases": ["images", "external/wpt/css/css-images/gradient"], @@ -832,7 +860,8 @@ "bases": [ "external/wpt/css/css-ui/pointer-events-no-scrollbars-001.html", "external/wpt/css/css-ui/pointer-events-no-scrollbars-002.html"], "args": ["--enable-features=OverlayScrollbar"], - "expires": "never" + "expires": "never", + "owners": ["wangxianzhu@chromium.org"] }, "The elastic-overscroll virtual suite is testing a feature that is enabled", "or not based on platform and settings, so it should not expire.", @@ -852,7 +881,8 @@ "platforms": ["Linux", "Mac", "Win"], "bases": [], "args": ["--disable-features=OverlayScrollbar"], - "expires": "never" + "expires": "never", + "owners": ["gastonr@microsoft.com", "gerchiko@microsoft.com", "yshalivskyy@microsoft.com"] }, { "prefix": "fluent-non-overlay-scrollbar", @@ -1566,18 +1596,6 @@ "expires": "Jul 1, 2025" }, { - "prefix": "lcp-multiple-updates-per-element", - "owners": ["haoliuk@chromium.org", "iclelland@chromium.org"], - "platforms": ["Linux", "Mac", "Win"], - "bases": [ - "external/wpt/largest-contentful-paint/update-on-style-change.tentative.html" - ], - "args": [ - "--enable-features=LCPMultipleUpdatesPerElement" - ], - "expires": "Jul 1, 2024" - }, - { "prefix": "low-priority-async-script-execution", "platforms": ["Linux", "Mac", "Win"], "exclusive_tests": "ALL",
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index f0f9e702..cafc1784 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -136808,12 +136808,12 @@ ] ], "masonry-gap-002.html": [ - "6dae0a1a7296dd52c48e5b53d8a903aa2ff4d5c4", + "2c87c4eeda7fec8fcfa7c0762340ffb68f8841ed", [ null, [ [ - "/css/css-grid/masonry/tentative/gap/masonry-gap-001-ref.html", + "/css/css-grid/masonry/tentative/gap/masonry-gap-002-ref.html", "==" ] ], @@ -165590,7 +165590,7 @@ ] ], "overflow-auto-scrollbar-gutter-intrinsic-003.html": [ - "ab247d9ca5a7cac660200cb475feb6b69093e520", + "6827773543b48ecdc39e46e8239292b9e7885256", [ null, [ @@ -165599,7 +165599,23 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 40 + ], + [ + 0, + 5 + ] + ] + ] + ] + } ] ], "overflow-body-propagation-001.html": [ @@ -177661,7 +177677,7 @@ ] ], "textarea-scrollbar-width-none.html": [ - "dcfaf5b6270ee0e0092dc795d33bb01af0b9a695", + "76f2b7f63449cd9b87af939a8ed5a3d42be14605", [ null, [ @@ -177670,7 +177686,23 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 150 + ], + [ + 0, + 10 + ] + ] + ] + ] + } ] ], "transparent-on-root.html": [ @@ -180396,7 +180428,7 @@ ] ], "shape-outside-inset-020.html": [ - "929882733370e26f0adf10d9b0d5c92b0b050ec4", + "a74afb43a1b012e80c5ae72e5a3b4ae0f6db01b6", [ null, [ @@ -180412,7 +180444,7 @@ [ [ 0, - 6 + 8 ], [ 0, @@ -180425,7 +180457,7 @@ ] ], "shape-outside-inset-021.html": [ - "e1d48bff712d860df397739bc4c7849f0e41a70f", + "8c0cef244bee99f33d1e6dc144b23155d48e7bd4", [ null, [ @@ -180434,11 +180466,27 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 8 + ], + [ + 0, + 4 + ] + ] + ] + ] + } ] ], "shape-outside-inset-022.html": [ - "5c51dc1a8eeaeb58db38facda6aa7d6ae4499b57", + "ff1cbe749f2e9536d72ba6216db5ad1d47b64e45", [ null, [ @@ -180447,11 +180495,27 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 8 + ], + [ + 0, + 4 + ] + ] + ] + ] + } ] ], "shape-outside-inset-023.html": [ - "3a97f8327eb03a87a3e0f667942124c4ba94a8b8", + "5b784366940cd6bf41c8f10a14377f39770cc783", [ null, [ @@ -180467,7 +180531,7 @@ [ [ 0, - 6 + 8 ], [ 0, @@ -180480,7 +180544,7 @@ ] ], "shape-outside-inset-024.html": [ - "5de0dad9ebc8ed851eb9df11f6188ed8af093f52", + "1f0fc33ed1f5856cc45557ae6ba544fcbddf0384", [ null, [ @@ -180496,7 +180560,7 @@ [ [ 0, - 6 + 8 ], [ 0, @@ -180509,7 +180573,7 @@ ] ], "shape-outside-inset-025.html": [ - "c843e0f7f13244f56143b19c4042790e85e88598", + "02ac7eb5e5d2e5247ede1dba9aea78ba8e6c74ad", [ null, [ @@ -180518,11 +180582,27 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 8 + ], + [ + 0, + 4 + ] + ] + ] + ] + } ] ], "shape-outside-inset-026.html": [ - "354ddafaa1db787bc73eb36b4c9bfeabbdd2a5c3", + "d2a4eb626944bda9562e4fc2fa087e340583f428", [ null, [ @@ -180531,11 +180611,27 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 8 + ], + [ + 0, + 4 + ] + ] + ] + ] + } ] ], "shape-outside-inset-027.html": [ - "69fb1e78b3e262fff2ce97e7039720c9888688ab", + "a667b0622b5904c97d6014aa1365114864363c99", [ null, [ @@ -180544,7 +180640,23 @@ "==" ] ], - {} + { + "fuzzy": [ + [ + null, + [ + [ + 0, + 8 + ], + [ + 0, + 2 + ] + ] + ] + ] + } ] ], "shape-outside-inset-028.html": [ @@ -210611,7 +210723,7 @@ ] ], "text-underline-offset-002.html": [ - "1b21079b34c23b6fa8889529e67c1a35ef264ae2", + "e11ce695403499c46e1bcc77cfd5bf6212f34d8a", [ null, [ @@ -210623,6 +210735,19 @@ {} ] ], + "text-underline-offset-calc.html": [ + "c8e3f2b88d584b919f8d54b813f56ca850d1d65c", + [ + null, + [ + [ + "/css/css-text-decor/text-underline-offset-calc-ref.html", + "==" + ] + ], + {} + ] + ], "text-underline-offset-negative.html": [ "1c945cc40374e3a92ec517f29b119fafc9b03462", [ @@ -210662,6 +210787,19 @@ {} ] ], + "text-underline-offset-percentage.html": [ + "3e16d949ecbc3ccbb12d9da1a2aa68b94fee2219", + [ + null, + [ + [ + "/css/css-text-decor/text-underline-offset-percentage-ref.html", + "==" + ] + ], + {} + ] + ], "text-underline-offset-scroll-001.html": [ "ee521fa215c7b9102ec6a6805c2866bf433c10a4", [ @@ -280053,6 +280191,19 @@ }, "replaced-elements": { "attributes-for-embedded-content-and-images": { + "canvas-dimension-attributes.html": [ + "536b1cd0c455595372cca3a260f1183e1d221ec5", + [ + null, + [ + [ + "/css/reference/ref-filled-green-200px-square.html", + "==" + ] + ], + {} + ] + ], "img-dim.html": [ "2d636c9417738423141203001302eb344151e295", [ @@ -317317,6 +317468,10 @@ "e1822fa544ec91a113eaa911f69243d767eaf5cc", [] ], + "style-query-no-cycle-expected.txt": [ + "707460938b61f7c361364d6b292f1ab6b6f2e069", + [] + ], "support": { "cq-testcommon.js": [ "2eaca1dd091cbf7c3a406fa02c2696d7a9c258e4", @@ -330870,7 +331025,7 @@ [] ], "masonry-gap-002-ref.html": [ - "834a884f7630844d75730d12b4f7871d0911b637", + "7c985442fad934ef038abb1e5188395dd4fed978", [] ] }, @@ -330894,7 +331049,7 @@ [] ], "masonry-intrinsic-sizing-cols-003-ref.html": [ - "d088b132c29e68905337219f97c2c018f5985f40", + "9ffea0a5d211c24b65fa811915176b8d861a43e9", [] ], "masonry-intrinsic-sizing-cols-004-ref.html": [ @@ -330902,7 +331057,7 @@ [] ], "masonry-intrinsic-sizing-cols-005-ref.html": [ - "99d5d05dd4e06eb23e7b6a2dab59e5e2743a2240", + "e65661bb56958f7772913f953516c2e28e68eacc", [] ], "masonry-intrinsic-sizing-cols-006-ref.html": [ @@ -346494,6 +346649,10 @@ "text-decoration-thickness-interpolation-expected.txt": [ "36d500e85bff872ee3ef7cefa5844a4b114f59fd", [] + ], + "text-underline-offset-interpolation-expected.txt": [ + "e70dfd052a92631a8d9fa6178a48cbc8dd88f620", + [] ] }, "invalidation": { @@ -347232,6 +347391,14 @@ [] ] }, + "text-underline-offset-calc-ref.html": [ + "ae82f4dac6e0a1e3ebef44dfcf5a6cbc5258e59b", + [] + ], + "text-underline-offset-percentage-ref.html": [ + "64ec95905e4c1d0a0198048d12268871d1c5fc60", + [] + ], "tools": { "generate-text-emphasis-line-height-tests.py": [ "e2a4457f38e4659534fc35c794d2000e3c61635f", @@ -393965,14 +394132,6 @@ "59643ca5ba557acb22f73e0033f61ecbb31b955f", [] ], - "pointerevent_pointercapture_in_frame_mouse-expected.txt": [ - "be6da2668f5106e74c5e86b211b944e125d71cd7", - [] - ], - "pointerevent_pointercapture_in_frame_touch-expected.txt": [ - "e94d02d6b0677b91bbfa65b3204e1ad0277a1bb4", - [] - ], "pointerevent_pointermove_after_pointerup_target_removed-expected.txt": [ "8d5fc176e25f1df475f5460d1b906f120916e253", [] @@ -404271,6 +404430,10 @@ "277c8347e975a473eb1526d8a2f4c5b8fab0d71a", [] ], + "SVGGraphicsElement.getBBox-05-expected.txt": [ + "946a6b96ff37c4eab615aa2f89c10c4d7a8f923b", + [] + ], "SVGLength-px-expected.txt": [ "ac5159143dbeaf1eec81d63127b215e6dd092309", [] @@ -459050,6 +459213,13 @@ {} ] ], + "style-query-no-cycle.html": [ + "5a179d38976637780dffcb23829c7ee386ae6371", + [ + null, + {} + ] + ], "style-query-with-unknown-width.html": [ "52f250c2d0d942db2d1e2e7eeae0b89f593cc744", [ @@ -480429,7 +480599,7 @@ ] ], "text-underline-offset-interpolation.html": [ - "5c0e37157c865123033536d2247c207bafac68b2", + "6845cac9e11c937fb477a4cb53f9155c970643de", [ null, {} @@ -480674,7 +480844,7 @@ } }, "text-underline-offset-computed.html": [ - "26861c1565bcada9d14bb6f045bfcddf39cbdaab", + "00494dd051b9cb41d3dac5522ecc1601a3bef52a", [ null, {} @@ -480695,7 +480865,7 @@ ] ], "text-underline-offset-valid.html": [ - "a2323e792592cb0730007a9d3a7a690c6dcff2a2", + "ff7e992b093e01bcb5b156ed302cc48dc4ff382e", [ null, {} @@ -485291,6 +485461,13 @@ {} ] ], + "attr-container-style-query.html": [ + "2cc872509c085ec05c9da512b2388dc1e5bafa78", + [ + null, + {} + ] + ], "attr-invalidation.html": [ "a48556e5ff7273772e1b037114f0112a8773b6a0", [ @@ -628896,7 +629073,7 @@ ] ], "pointerevent_pointercapture_in_frame.html": [ - "9c26c4d5a3869bde8e201653f185a6cb023cb779", + "14be00968fad173347a0e29e0eb285d1283f12f6", [ "pointerevents/pointerevent_pointercapture_in_frame.html?mouse", { @@ -668724,6 +668901,13 @@ {} ] ], + "SVGGraphicsElement.getBBox-05.html": [ + "1d38640d0202ec266613d21fd9c8a480cea697da", + [ + null, + {} + ] + ], "SVGGraphicsElement.getScreenCTM.html": [ "7e5dfc649f89112cb8b4d31352a5b1e8788739fa", [ @@ -677929,7 +678113,7 @@ ] ], "constructor.any.js": [ - "51b1070d413586d159ea3d38304a652f3efea947", + "1143bab72a26ce15bd7c02c0a84164ccb8a26e5f", [ null, { @@ -684757,7 +684941,7 @@ ] ], "audio-decoder.https.any.js": [ - "666d3a159f16adb593ff3f942b409957f7e0f749", + "98ed49897d30461ca7e4f0652a69f6690c9ab043", [ "webcodecs/audio-decoder.https.any.html", { @@ -713321,6 +713505,195 @@ } ] ], + "gatherElements.https.any.js": [ + "ed8af8da33041ecc8aaa558584b1d12f51709da5", + [ + "webnn/validation_tests/gatherElements.https.any.html?cpu", + { + "script_metadata": [ + [ + "title", + "validation tests for WebNN API gatherElements operation" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "variant", + "?cpu" + ], + [ + "variant", + "?gpu" + ], + [ + "variant", + "?npu" + ], + [ + "script", + "../resources/utils_validation.js" + ] + ] + } + ], + [ + "webnn/validation_tests/gatherElements.https.any.html?gpu", + { + "script_metadata": [ + [ + "title", + "validation tests for WebNN API gatherElements operation" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "variant", + "?cpu" + ], + [ + "variant", + "?gpu" + ], + [ + "variant", + "?npu" + ], + [ + "script", + "../resources/utils_validation.js" + ] + ] + } + ], + [ + "webnn/validation_tests/gatherElements.https.any.html?npu", + { + "script_metadata": [ + [ + "title", + "validation tests for WebNN API gatherElements operation" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "variant", + "?cpu" + ], + [ + "variant", + "?gpu" + ], + [ + "variant", + "?npu" + ], + [ + "script", + "../resources/utils_validation.js" + ] + ] + } + ], + [ + "webnn/validation_tests/gatherElements.https.any.worker.html?cpu", + { + "script_metadata": [ + [ + "title", + "validation tests for WebNN API gatherElements operation" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "variant", + "?cpu" + ], + [ + "variant", + "?gpu" + ], + [ + "variant", + "?npu" + ], + [ + "script", + "../resources/utils_validation.js" + ] + ] + } + ], + [ + "webnn/validation_tests/gatherElements.https.any.worker.html?gpu", + { + "script_metadata": [ + [ + "title", + "validation tests for WebNN API gatherElements operation" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "variant", + "?cpu" + ], + [ + "variant", + "?gpu" + ], + [ + "variant", + "?npu" + ], + [ + "script", + "../resources/utils_validation.js" + ] + ] + } + ], + [ + "webnn/validation_tests/gatherElements.https.any.worker.html?npu", + { + "script_metadata": [ + [ + "title", + "validation tests for WebNN API gatherElements operation" + ], + [ + "global", + "window,dedicatedworker" + ], + [ + "variant", + "?cpu" + ], + [ + "variant", + "?gpu" + ], + [ + "variant", + "?npu" + ], + [ + "script", + "../resources/utils_validation.js" + ] + ] + } + ] + ], "gelu.https.any.js": [ "c02c2923af49540d9da82819917e5d983eeedeee", [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/gap/masonry-gap-002-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/gap/masonry-gap-002-ref.html index 834a884..7c985442f 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/gap/masonry-gap-002-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/gap/masonry-gap-002-ref.html
@@ -4,11 +4,11 @@ http://creativecommons.org/publicdomain/zero/1.0/ --> <html><head> - <meta charset="utf-8"> - <title>Reference: Masonry layout with normal `gap` in both axes</title> - <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> - <link rel="author" title="Elika J. Etemad" href="https://fantasai.inkedblade.net/contact"> - <style> +<meta charset="utf-8"> +<title>Reference: Masonry layout with normal `gap` in both axes</title> +<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> +<link rel="author" title="Elika J. Etemad" href="https://fantasai.inkedblade.net/contact"> +<style> html,body { color:black; background-color:white; font:25px/1 "Courier New", monospace; padding:0; margin:0; } @@ -58,5 +58,20 @@ <item>2</item> <item>3</item> </div> + <div style="columns: 3; column-gap: 1em; visibility: hidden;"> + <item>1</item> + <item>2</item> + <item>3</item> + </div> + <div style="columns: 3; column-gap: 1em; visibility: hidden;"> + <item>1</item> + <item>2</item> + <item>3</item> + </div> + <div style="columns: 3; column-gap: 1em; visibility: hidden;"> + <item>1</item> + <item>2</item> + <item>3</item> + </div> </grid>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/gap/masonry-gap-002.html b/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/gap/masonry-gap-002.html index 6dae0a1a..2c87c4ee 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/gap/masonry-gap-002.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/gap/masonry-gap-002.html
@@ -4,18 +4,19 @@ http://creativecommons.org/publicdomain/zero/1.0/ --> <html><head> - <meta charset="utf-8"> - <title>CSS Grid Test: Masonry layout with normal `gap` in both axes</title> - <meta name="assert" - content="Test passes if a 'normal' gap is the initial value, - is resolved to zero, - does not allow margin collapsing, - and inherits as 'normal' in masonry layout"> - <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> - <link rel="author" title="Elika J. Etemad" href="https://fantasai.inkedblade.net/contact"> - <link rel="help" href="https://drafts.csswg.org/css-grid-3/#alignment"> - <link rel="match" href="masonry-gap-001-ref.html"> - <style> +<meta charset="utf-8"> +<title>CSS Grid Test: Masonry layout with normal `gap` in both axes</title> +<meta name="assert" + content="Test passes if a 'normal' gap is the initial value, + is resolved to zero, + does not allow margin collapsing, + and inherits as 'normal' in masonry layout"> +<link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> +<link rel="author" title="Elika J. Etemad" href="https://fantasai.inkedblade.net/contact"> +<link rel="help" href="https://drafts.csswg.org/css-grid-3/#alignment"> +<link rel="match" href="masonry-gap-002-ref.html"> + +<style> html,body { color:black; background-color:white; font:25px/1 "Courier New", monospace; padding:0; margin:0; } @@ -37,7 +38,6 @@ border: 5px solid blue; display: block; } - </style> </head> <body> @@ -62,7 +62,7 @@ <!-- test inheritance of normal as keyword --> -<grid style="gap: 10px; gap: normal"> +<grid style="gap: 10px; gap: normal;"> <div style="columns: 3; gap: inherit;"> <item>1</item> <item>2</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/intrinsic-sizing/masonry-intrinsic-sizing-cols-003-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/intrinsic-sizing/masonry-intrinsic-sizing-cols-003-ref.html index d088b13..9ffea0a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/intrinsic-sizing/masonry-intrinsic-sizing-cols-003-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/intrinsic-sizing/masonry-intrinsic-sizing-cols-003-ref.html
@@ -97,7 +97,7 @@ <item style="grid-row: span 2">2 2</item> <item style="grid-row: span 2">3 3</item> <item>4</item> - <item style="width:3ch; grid-area: 1/2/2/4">5 5</item> + <item style="width:3ch; grid-area: 1/2/2/4">5</item> <item style="width:5ch; grid-area: 2/1/3/4">6</item> <item class="hidden">0</item> @@ -193,7 +193,7 @@ <item style="grid-row: span 2">2 2</item> <item style="grid-row: span 2">3 3</item> <item>4</item> - <item style="width:3ch; grid-area: 1/2/2/4">5 5</item> + <item style="width:3ch; grid-area: 1/2/2/4">5</item> <item style="width:5ch; grid-area: 2/1/3/4">6</item> <item class="hidden">0</item> @@ -291,7 +291,7 @@ <item style="grid-row: span 2">2 2</item> <item style="grid-row: span 2">3 3</item> <item>4</item> - <item style="width:3ch; grid-area: 1/2/2/4">5 5</item> + <item style="width:3ch; grid-area: 1/2/2/4">5</item> <item style="width:5ch; grid-area: 2/1/3/4">6</item> <item class="hidden">0</item> @@ -351,7 +351,7 @@ <item style="grid-row: span 2">2 2</item> <item style="grid-row: span 2">3 3</item> <item>4</item> - <item style="grid-row: span 2">5 5</item> + <item style="grid-row: span 2; width: 2ch;">5 5</item> <item class="hidden" style="grid-area: 2/4/4">0 0</item> </grid>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/intrinsic-sizing/masonry-intrinsic-sizing-cols-005-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/intrinsic-sizing/masonry-intrinsic-sizing-cols-005-ref.html index 99d5d05..e65661bb 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/intrinsic-sizing/masonry-intrinsic-sizing-cols-005-ref.html +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/masonry/tentative/intrinsic-sizing/masonry-intrinsic-sizing-cols-005-ref.html
@@ -54,12 +54,12 @@ <item>9 9</item> </grid> -<grid style="grid-template-columns: 3ch repeat(3,3ch)"> +<grid style="grid-template-columns: 3ch 15px 15px 15px"> + <item style="grid-column:1; grid-row: span 3;">5 5</item> <item>1</item> <item>2</item> <item>3</item> <item>4</item> - <item style="width:3ch; grid-column:1; grid-row: span 2">5 5</item> <item>6</item> <item>7</item> <item>8</item>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-auto-scrollbar-gutter-intrinsic-003.html b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-auto-scrollbar-gutter-intrinsic-003.html index ab247d9c..6827773 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-auto-scrollbar-gutter-intrinsic-003.html +++ b/third_party/blink/web_tests/external/wpt/css/css-overflow/overflow-auto-scrollbar-gutter-intrinsic-003.html
@@ -6,6 +6,7 @@ <link rel="help" href="https://drafts.csswg.org/css-overflow-4/#scrollbar-gutter-property"> <link rel="help" href="https://drafts.csswg.org/css-scrollbars/#scrollbar-width"> <link rel="match" href="overflow-auto-scrollbar-gutter-intrinsic-003-ref.html"> + <meta name="fuzzy" content="maxDifference=0-40; totalPixels=0-5" /> <style> .line {
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scrollbars/textarea-scrollbar-width-none.html b/third_party/blink/web_tests/external/wpt/css/css-scrollbars/textarea-scrollbar-width-none.html index dcfaf5b..76f2b7f6 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-scrollbars/textarea-scrollbar-width-none.html +++ b/third_party/blink/web_tests/external/wpt/css/css-scrollbars/textarea-scrollbar-width-none.html
@@ -5,6 +5,7 @@ <link rel="author" title="Mozilla" href="https://www.mozilla.org"> <link rel="help" href="https://drafts.csswg.org/css-scrollbars-1/#scrollbar-width"> <link rel="match" href="textarea-scrollbar-width-none-ref.html"> +<meta name="fuzzy" content="maxDifference=0-150; totalPixels=0-10"> <style> textarea { scrollbar-width: none;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/animations/text-underline-offset-interpolation-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-text-decor/animations/text-underline-offset-interpolation-expected.txt new file mode 100644 index 0000000..e70dfd0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/animations/text-underline-offset-interpolation-expected.txt
@@ -0,0 +1,36 @@ +This is a testharness.js-based test. +Found 16 FAIL, 0 TIMEOUT, 0 NOTRUN. +[FAIL] CSS Transitions: property <text-underline-offset> from [16px] to [200%] at (0.3) should be [calc(120% + 11.2px)] + assert_equals: expected "calc ( 120 % + 11.2px ) " but got "calc ( 60 % + 11.2px ) " +[FAIL] CSS Transitions with transition: all: property <text-underline-offset> from [16px] to [200%] at (0.3) should be [calc(120% + 11.2px)] + assert_equals: expected "calc ( 120 % + 11.2px ) " but got "calc ( 60 % + 11.2px ) " +[FAIL] CSS Animations: property <text-underline-offset> from [16px] to [200%] at (0.3) should be [calc(120% + 11.2px)] + assert_equals: expected "calc ( 120 % + 11.2px ) " but got "calc ( 60 % + 11.2px ) " +[FAIL] Web Animations: property <text-underline-offset> from [16px] to [200%] at (0.3) should be [calc(120% + 11.2px)] + assert_equals: expected "calc ( 120 % + 11.2px ) " but got "calc ( 60 % + 11.2px ) " +[FAIL] CSS Transitions: property <text-underline-offset> from [100%] to [32px] at (0.3) should be [calc(100% + 9.6px)] + assert_equals: expected "calc ( 100 % + 9.6px ) " but got "calc ( 70 % + 9.6px ) " +[FAIL] CSS Transitions: property <text-underline-offset> from [100%] to [32px] at (0.6) should be [calc(100% + 19.2px)] + assert_equals: expected "calc ( 100 % + 19.2px ) " but got "calc ( 40 % + 19.2px ) " +[FAIL] CSS Transitions: property <text-underline-offset> from [100%] to [32px] at (1) should be [calc(100% + 32px)] + assert_equals: expected "calc ( 100 % + 32px ) " but got "calc ( 0 % + 32px ) " +[FAIL] CSS Transitions with transition: all: property <text-underline-offset> from [100%] to [32px] at (0.3) should be [calc(100% + 9.6px)] + assert_equals: expected "calc ( 100 % + 9.6px ) " but got "calc ( 70 % + 9.6px ) " +[FAIL] CSS Transitions with transition: all: property <text-underline-offset> from [100%] to [32px] at (0.6) should be [calc(100% + 19.2px)] + assert_equals: expected "calc ( 100 % + 19.2px ) " but got "calc ( 40 % + 19.2px ) " +[FAIL] CSS Transitions with transition: all: property <text-underline-offset> from [100%] to [32px] at (1) should be [calc(100% + 32px)] + assert_equals: expected "calc ( 100 % + 32px ) " but got "calc ( 0 % + 32px ) " +[FAIL] CSS Animations: property <text-underline-offset> from [100%] to [32px] at (0.3) should be [calc(100% + 9.6px)] + assert_equals: expected "calc ( 100 % + 9.6px ) " but got "calc ( 70 % + 9.6px ) " +[FAIL] CSS Animations: property <text-underline-offset> from [100%] to [32px] at (0.6) should be [calc(100% + 19.2px)] + assert_equals: expected "calc ( 100 % + 19.2px ) " but got "calc ( 40 % + 19.2px ) " +[FAIL] CSS Animations: property <text-underline-offset> from [100%] to [32px] at (1) should be [calc(100% + 32px)] + assert_equals: expected "calc ( 100 % + 32px ) " but got "calc ( 0 % + 32px ) " +[FAIL] Web Animations: property <text-underline-offset> from [100%] to [32px] at (0.3) should be [calc(100% + 9.6px)] + assert_equals: expected "calc ( 100 % + 9.6px ) " but got "calc ( 70 % + 9.6px ) " +[FAIL] Web Animations: property <text-underline-offset> from [100%] to [32px] at (0.6) should be [calc(100% + 19.2px)] + assert_equals: expected "calc ( 100 % + 19.2px ) " but got "calc ( 40 % + 19.2px ) " +[FAIL] Web Animations: property <text-underline-offset> from [100%] to [32px] at (1) should be [calc(100% + 32px)] + assert_equals: expected "calc ( 100 % + 32px ) " but got "calc ( 0 % + 32px ) " +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/animations/text-underline-offset-interpolation.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/animations/text-underline-offset-interpolation.html index 5c0e3715..6845cac9 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/animations/text-underline-offset-interpolation.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/animations/text-underline-offset-interpolation.html
@@ -9,7 +9,7 @@ <style> .target { - font: 10px sans-serif; + font: 16px sans-serif; } </style> @@ -29,4 +29,212 @@ {at: 1, expect: '0px'}, ]); -</script> +test_interpolation({ + property: 'text-underline-offset', + from: '16px', + to: '0px', +}, [ + {at: 0, expect: '16px'}, + {at: 0.3, expect: '11.2px'}, + {at: 0.6, expect: '6.4px'}, + {at: 1, expect: '0px'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '16px', + to: '32px', +}, [ + {at: 0, expect: '16px'}, + {at: 0.3, expect: '20.8px'}, + {at: 0.6, expect: '25.6px'}, + {at: 1, expect: '32px'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '1em', + to: '0em', +}, [ + {at: 0, expect: '16px'}, + {at: 0.3, expect: '11.2px'}, + {at: 0.6, expect: '6.4px'}, + {at: 1, expect: '0px'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '1em', + to: '2em', +}, [ + {at: 0, expect: '16px'}, + {at: 0.3, expect: '20.8px'}, + {at: 0.6, expect: '25.6px'}, + {at: 1, expect: '32px'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '100%', + to: '0%', +}, [ + {at: 0, expect: '100%'}, + {at: 0.3, expect: '70%'}, + {at: 0.6, expect: '40%'}, + {at: 1, expect: '0%'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '100%', + to: '200%', +}, [ + {at: 0, expect: '100%'}, + {at: 0.3, expect: '130%'}, + {at: 0.6, expect: '160%'}, + {at: 1, expect: '200%'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '16px', + to: '0em', +}, [ + {at: 0, expect: '16px'}, + {at: 0.3, expect: '11.2px'}, + {at: 0.6, expect: '6.4px'}, + {at: 1, expect: '0px'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '16px', + to: '2em', +}, [ + {at: 0, expect: '16px'}, + {at: 0.3, expect: '20.8px'}, + {at: 0.6, expect: '25.6px'}, + {at: 1, expect: '32px'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '16px', + to: '0%', +}, [ + {at: 0, expect: 'calc(0% + 16px)'}, + {at: 0.3, expect: 'calc(0% + 11.2px)'}, + {at: 0.6, expect: 'calc(0% + 6.4px)'}, + {at: 1, expect: '0%'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '16px', + to: '200%', +}, [ + {at: 0, expect: 'calc(0% + 16px)'}, + {at: 0.3, expect: 'calc(120% + 11.2px)'}, + {at: 0.6, expect: 'calc(120% + 6.4px)'}, + {at: 1, expect: '200%'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '1em', + to: '0px', +}, [ + {at: 0, expect: '16px'}, + {at: 0.3, expect: '11.2px'}, + {at: 0.6, expect: '6.4px'}, + {at: 1, expect: '0px'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '1em', + to: '32px', +}, [ + {at: 0, expect: '16px'}, + {at: 0.3, expect: '20.8px'}, + {at: 0.6, expect: '25.6px'}, + {at: 1, expect: '32px'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '1em', + to: '0%', +}, [ + {at: 0, expect: 'calc(0% + 16px)'}, + {at: 0.3, expect: 'calc(0% + 11.2px)'}, + {at: 0.6, expect: 'calc(0% + 6.4px)'}, + {at: 1, expect: '0%'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '1em', + to: '200%', +}, [ + {at: 0, expect: 'calc(0% + 16px)'}, + {at: 0.3, expect: 'calc(60% + 11.2px)'}, + {at: 0.6, expect: 'calc(120% + 6.4px)'}, + {at: 1, expect: '200%'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '100%', + to: '0px', +}, [ + {at: 0, expect: '100%'}, + {at: 0.3, expect: '70%'}, + {at: 0.6, expect: '40%'}, + {at: 1, expect: '0%'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '100%', + to: '32px', +}, [ + {at: 0, expect: 'calc(100% + 0px)'}, + {at: 0.3, expect: 'calc(100% + 9.6px)'}, + {at: 0.6, expect: 'calc(100% + 19.2px)'}, + {at: 1, expect: 'calc(100% + 32px)'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '100%', + to: '0em', +}, [ + {at: 0, expect: 'calc(100% + 0em)'}, + {at: 0.3, expect: 'calc(70% + 0em)'}, + {at: 0.6, expect: 'calc(40% + 0em)'}, + {at: 1, expect: 'calc(0% + 0em)'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '100%', + to: '2em', +}, [ + {at: 0, expect: '100%'}, + {at: 0.3, expect: 'calc(70% + 9.6px)'}, + {at: 0.6, expect: 'calc(40% + 19.2px)'}, + {at: 1, expect: 'calc(0% + 32px)'}, +]); + +test_interpolation({ + property: 'text-underline-offset', + from: '0%', + to: '100%', +}, [ + {at: 0, expect: '0%'}, + {at: 0.3, expect: '30%'}, + {at: 0.6, expect: '60%'}, + {at: 1, expect: '100%'}, +]); +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-002.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-002.html index 1b21079..e11ce69 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-002.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-002.html
@@ -14,7 +14,8 @@ display: flex; } #text, #norm{ - text-decoration: green underline; + text-decoration-color: green; + text-decoration-line: underline; text-decoration-skip-ink: none; font: 20px/1 Ahem; color: transparent;
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-calc-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-calc-ref.html new file mode 100644 index 0000000..ae82f4d --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-calc-ref.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>text-underline-offset calc() support</title> +<link rel="author" title="Zak Ridouh" href="mailto:zakr@apple.com" /> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#underline-offset" /> +<style> +div { + display: flex; + font-size: 22px; +} +.underline { + text-decoration-color: green; + text-decoration-line: underline; + text-decoration-thickness: 15px; + text-decoration-skip-ink: none; +} +.ref { + text-underline-offset: 1em; +} +</style> +<p>Test passes if black and green bar pairs are the same shape and size.</p> +<div> + <span class="underline ref">XXXXXX</span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-calc.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-calc.html new file mode 100644 index 0000000..c8e3f2b8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-calc.html
@@ -0,0 +1,46 @@ +<!DOCTYPE html> +<meta charset="UTF-8"> +<title>text-underline-offset calc() support</title> +<link rel="author" title="Zak Ridouh" href="mailto:zakr@apple.com" /> +<link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#underline-offset" /> +<meta name="assert" content="Test checks whether text-underline-offset supports calc() values."> +<link rel="match" href="text-underline-offset-calc-ref.html"> +<style> +div { + display: flex; + font-size: 22px; +} +.underline { + text-decoration-color: green; + text-decoration-line: underline; + text-decoration-thickness: 15px; + text-decoration-skip-ink: none; +} +.ref { + text-underline-offset: 1em; +} +.test1 { + text-underline-offset: calc(1em); +} +.test2 { + text-underline-offset: calc(100%); +} +.test3 { + text-underline-offset: calc(50% + 11px); +} +.test4 { + text-underline-offset: calc(50% + 0.5em); +} +.test5 { + text-underline-offset: calc(0.5em + 11px); +} +</style> +<p>Test passes if black and green bar pairs are the same shape and size.</p> +<div> + <span class="underline ref">X</span> + <span class="underline test1">X</span> + <span class="underline test2">X</span> + <span class="underline test3">X</span> + <span class="underline test4">X</span> + <span class="underline test5">X</span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-computed.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-computed.html index 26861c15..00494dd 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-computed.html
@@ -14,6 +14,23 @@ <script> test_computed_value("text-underline-offset", "auto"); test_computed_value("text-underline-offset", "calc(10px - 8px)", "2px"); + +test_computed_value("text-underline-offset", "32px", "32px"); +test_computed_value("text-underline-offset", "2em", "32px"); +test_computed_value("text-underline-offset", "200%", "200%"); + +test_computed_value("text-underline-offset", "calc(2em - 0px)", "32px"); +test_computed_value("text-underline-offset", "calc(200% - 0px)", "200%"); +test_computed_value("text-underline-offset", "calc(0.5em - 0px)", "8px"); +test_computed_value("text-underline-offset", "calc(50% - 0px)", "50%"); + +test_computed_value("text-underline-offset", "calc(2em - 8px)", "24px"); +test_computed_value("text-underline-offset", "calc(2em - 0.5em)", "24px"); +test_computed_value("text-underline-offset", "calc(2em - 50%)", "calc(-50% + 32px)"); + +test_computed_value("text-underline-offset", "calc(200% - 8px)"); +test_computed_value("text-underline-offset", "calc(200% - 0.5em)", "calc(200% - 8px)"); +test_computed_value("text-underline-offset", "calc(200% - 50%)", "150%"); </script> </body> </html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-percentage-ref.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-percentage-ref.html new file mode 100644 index 0000000..64ec959 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-percentage-ref.html
@@ -0,0 +1,42 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Reference case for text-underline-offset</title> + <link rel="author" title="Zak Ridouh" href="mailto:zakr@apple.com"> + <link rel="author" title="Apple" href="https://www.apple.com"> + <link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#underline-offset"> + <style> + #main { + border-bottom: 2px solid purple; + display: flex; + } + #text, #norm { + text-decoration-color: green; + text-decoration-line: underline; + text-decoration-thickness: 15px; + font: 20px/2 Arial; + color: transparent; + position: relative; + margin-right: 10px; + } + #text { + text-underline-offset: 5px; + } + #norm { + text-underline-offset: 5px; + } + </style> +</head> +<body > + <p class="instructions">Test passes if the lines are at the same level</p> + <div id="main"> + <div> + <p>left<span id="text">XXXX</span></p> + </div> + <div> + <p><span id="norm">XXXX</span>right</p> + </div> + </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-percentage.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-percentage.html new file mode 100644 index 0000000..3e16d949 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-percentage.html
@@ -0,0 +1,43 @@ +<!DOCTYPE html> +<html> +<head> + <meta charset="utf-8"> + <title>Test case for text-underline-offset percentage support</title> + <link rel="author" title="Zak Ridouh" href="mailto:zakr@apple.com"> + <link rel="author" title="Apple" href="https://www.apple.com"> + <link rel="help" href="https://drafts.csswg.org/css-text-decor-4/#underline-offset"> + <link rel="match" href="text-underline-offset-percentage-ref.html"> + <style> + #main { + border-bottom: 2px solid purple; + display: flex; + } + #text, #norm { + text-decoration-color: green; + text-decoration-line: underline; + text-decoration-thickness: 15px; + font: 20px/2 Arial; + color: transparent; + position: relative; + margin-right: 10px; + } + #text { + text-underline-offset: 25%; + } + #norm { + text-underline-offset: 25%; + } + </style> +</head> +<body > + <p class="instructions">Test passes if the lines are at the same level</p> + <div id="main"> + <div> + <p>left<span id="text">XXXX</span></p> + </div> + <div> + <p><span id="norm">XXXX</span>right</p> + </div> + </div> +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-valid.html b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-valid.html index a2323e79..ff7e992b0 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-text-decor/text-underline-offset-valid.html
@@ -16,6 +16,11 @@ test_valid_value("text-underline-offset", "2001em"); test_valid_value("text-underline-offset", "-49em"); test_valid_value("text-underline-offset", "53px"); +test_valid_value("text-underline-offset", "5%"); +test_valid_value("text-underline-offset", "89%"); +test_valid_value("text-underline-offset", "-30%"); +test_valid_value("text-underline-offset", "187%"); +test_valid_value("text-underline-offset", "calc(45% - 0.3em)"); test_valid_value("text-underline-offset", "calc(40em - 10px)"); test_valid_value("text-underline-offset", "calc(-13em + 50px)"); </script>
diff --git a/third_party/blink/web_tests/external/wpt/dom/observable/tentative/observable-reduce.any.js b/third_party/blink/web_tests/external/wpt/dom/observable/tentative/observable-reduce.any.js new file mode 100644 index 0000000..7c54aa1 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/dom/observable/tentative/observable-reduce.any.js
@@ -0,0 +1,166 @@ +promise_test(async t => { + const source = new Observable(subscriber => { + subscriber.next(1); + subscriber.next(2); + subscriber.next(3); + t.step_timeout(() => subscriber.complete(), 0); + }); + + const reducerArguments = []; + + const promiseToResult = source.reduce((acc, value, index) => { + reducerArguments.push([acc, value, index]); + return acc + value; + }, 0); + + // The reducer should be called immediately when the source emits a value. + assert_equals(reducerArguments.length, 3); + assert_array_equals(reducerArguments[0], [0, 1, 0]); + assert_array_equals(reducerArguments[1], [1, 2, 1]); + assert_array_equals(reducerArguments[2], [3, 3, 2]); + + const result = await promiseToResult; + assert_equals(result, 6); +}, "reduce(): Reduces the values of the Observable, starting with the " + + "initial seed value"); + +promise_test(async () => { + let error = new Error('from the source'); + const source = new Observable(subscriber => { + subscriber.next(1); + subscriber.error(error); + }); + + let thrownError = null; + try { + await source.reduce((acc, value) => acc + value, 0); + } catch (error) { + thrownError = error; + } + + assert_equals(thrownError, error); +}, "reduce(): Rejects if the source observable emits an error"); + +promise_test(async t => { + const source = new Observable(subscriber => { + subscriber.next(1); + subscriber.next(2); + subscriber.next(3); + t.step_timeout(() => subscriber.complete(), 0); + }); + + const reducerArguments = []; + + const promiseToResult = source.reduce((acc, value, index) => { + reducerArguments.push([acc, value, index]); + return acc + value; + }); + + // The reducer should be called immediately when the source emits a value. + assert_equals(reducerArguments.length, 2); + assert_array_equals(reducerArguments[0], [1, 2, 1]); + assert_array_equals(reducerArguments[1], [3, 3, 2]); + + const result = await promiseToResult; + assert_equals(result, 6); +}, "reduce(): Seeds with the first value of the source, if no initial value " + + "is provided"); + +promise_test(async () => { + const logs = []; + + const source = new Observable(subscriber => { + subscriber.addTeardown(() => logs.push('teardown')); + logs.push('next 1'); + subscriber.next(1); + logs.push('next 2'); + subscriber.next(2); + logs.push('try to next 3'); + subscriber.next(3); + logs.push('try to complete'); + subscriber.complete(); + }); + + const error = new Error('from the reducer'); + let thrownError = null; + + try { + await source.reduce((acc, value) => { + if (value === 2) { + logs.push('throw error'); + throw error; + } + return acc + value; + }, 0); + } catch (error) { + thrownError = error; + } + + assert_equals(thrownError, error); + + assert_array_equals(logs, [ + 'next 1', + 'next 2', + 'throw error', + 'teardown', + 'try to next 3', + 'try to complete', + ]); +}, "reduce(): Errors thrown in reducer reject the promise and abort the source"); + +promise_test(async () => { + const source = new Observable(subscriber => { + subscriber.complete(); + }); + + const result = await source.reduce(() => 'reduced', 'seed'); + + assert_equals(result, 'seed'); +}, "reduce(): When source is empty, promise resolves with initial value"); + +promise_test(async () => { + // This tests behavior that is analogous to `[].reduce(() => 'reduced')`, + // which throws a TypeError. + + const source = new Observable(subscriber => { + subscriber.complete(); + }); + + let thrownError = null; + try { + await source.reduce(() => 'reduced'); + } catch (error) { + thrownError = error; + } + + assert_true(thrownError instanceof TypeError); +}, "reduce(): When source is empty, AND no seed value is provided, the " + + "promise rejects with a TypeError"); + +promise_test(async t => { + let tornDown = false; + const source = new Observable((subscriber) => { + subscriber.addTeardown(() => { + tornDown = true; + }); + // Waits forever. + }); + + const abortController = new AbortController(); + + t.step_timeout(() => { + abortController.abort(); + assert_true(tornDown); + }, 0); + + let thrownError = null; + try { + await source.reduce(() => 'reduced', 'seed', { signal: abortController.signal }); + } catch (error) { + thrownError = error; + } + + assert_true(thrownError instanceof DOMException); + assert_equals(thrownError.name, 'AbortError'); +}, "reduce(): Reject with an AbortError if the subscription is aborted " + + "before the source completes");
diff --git a/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/canvas-dimension-attributes.html b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/canvas-dimension-attributes.html new file mode 100644 index 0000000..536b1cd0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/html/rendering/replaced-elements/attributes-for-embedded-content-and-images/canvas-dimension-attributes.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<title>Canvas width and height attributes are used as the surface size, and also to infer aspect ratio</title> +<link rel="author" title="Oriol Brufau" href="obrufau@igalia.com"> +<link rel="help" href="https://html.spec.whatwg.org/multipage/rendering.html#attributes-for-embedded-content-and-images"> +<link rel="match" href="/css/reference/ref-filled-green-200px-square.html"> +<meta name="assert" content=" + Unlike <img>, <canvas> doesn't map its dimension attributes to the dimension properties. + Therefore, the 1st <canvas> should be 100px wide since it infers an aspect ratio of 150 / 150. + The 2nd <canvas> should be 100px tall since it infers an aspect ratio of 150 / 300. + The 3rd <canvas> should be 150px wide since it infers an aspect ratio of 150 / 100. + The 4th <canvas> should be 100px tall since it infers an aspect ratio of 150 / 300."> + +<style> +div { + background: red; + width: 200px; + font-size: 0; +} +canvas { + vertical-align: top; +} +</style> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div> + <canvas id="canvas" width="150" style="background: green; height: 100px"></canvas> + <canvas id="canvas" height="300" style="background: green; width: 100px"></canvas> + <canvas id="canvas" width="150" height="100" style="background: green; height: 100px"></canvas> + <canvas id="canvas" width="150" height="300" style="background: green; width: 50px"></canvas> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/update-on-style-change.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/update-on-style-change.html new file mode 100644 index 0000000..8bc4c496 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/update-on-style-change.html
@@ -0,0 +1,29 @@ +<!DOCTYPE html> +<meta charset="utf-8"> +<title>LargestContentfulPaint entries should NOT be emitted for updates to previous LargestContentfulPaint elements.</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<body> + <script> + promise_test(async (t) => { + assert_implements(window.LargestContentfulPaint, "LargestContentfulPaint is not implemented"); + let lcpEntries = []; + await new Promise(resolve => t.step_timeout(() => { + new PerformanceObserver(list => { + lcpEntries = lcpEntries.concat(list.getEntries()) + if (lcpEntries.length > 1) { + assert_unreached("There shouldn't be more than 1 LCP entry for an element."); + } + if (lcpEntries) { + assert_equals(lcpEntries.length, 1, "There should be only 1 LCP entry for one element. "); + assert_equals(lcpEntries[0].id, "text", "The LCP should have id 'text'"); + resolve(); + } + }).observe({ type: 'largest-contentful-paint', buffered: true }); + }, 200)); + }) + </script> + <div id="text">text</div> + <link rel="stylesheet" href="/resources/slow-style-change.py"> +</body> \ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/update-on-style-change.tentative.html b/third_party/blink/web_tests/external/wpt/largest-contentful-paint/update-on-style-change.tentative.html deleted file mode 100644 index dd34e61..0000000 --- a/third_party/blink/web_tests/external/wpt/largest-contentful-paint/update-on-style-change.tentative.html +++ /dev/null
@@ -1,38 +0,0 @@ -<!DOCTYPE html> -<meta charset="utf-8"> -<title>LargestContentfulPaint entries should generate for updates to previous LargestContentfulPaint nodes.</title> -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> - -<body> - <script> - promise_test(() => { - assert_implements(window.LargestContentfulPaint, "LargestContentfulPaint is not implemented"); - let countLcp = 0; - let firstLcp = null; - const timeoutPromise = new Promise(resolve => step_timeout(() => { - resolve(new Error('Did not observe two LCP entries')) - }, 3 * 1000)); - const testPromise = new Promise(resolve => { - new PerformanceObserver(list => { - const entries = list.getEntries(); - for (const entry of entries) { - ++countLcp; - assert_equals(entry.entryType, 'largest-contentful-paint'); - assert_equals(entry.id, 'text'); - if (countLcp == 1) { - firstLcp = entry; - } else if (countLcp == 2) { - assert_more_than(entry.startTime, firstLcp.startTime); - assert_more_than(entry.size, firstLcp.size); - resolve(); - } - } - }).observe({ entryTypes: ['largest-contentful-paint'] }); - }); - return Promise.race([timeoutPromise, testPromise]); - }) - </script> - <div id="text">text</div> - <link rel="stylesheet" href="/resources/slow-style-change.py"> -</body>
diff --git a/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGGraphicsElement.getBBox-05-expected.txt b/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGGraphicsElement.getBBox-05-expected.txt new file mode 100644 index 0000000..946a6b9 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGGraphicsElement.getBBox-05-expected.txt
@@ -0,0 +1,19 @@ +This is a testharness.js-based test. +[FAIL] image with fill, stroke, markers and clipping + assert_approx_equals: image1.getBBox().x {"fill":true,"stroke":true,"markers":true,"clipped":true} expected 160 +/- 0.1 but got 150 +[FAIL] path with fill, stroke, markers and clipping + assert_approx_equals: path1.getBBox().x {"fill":true,"stroke":true,"markers":true,"clipped":true} expected 6.2 +/- 0.1 but got 10 +[FAIL] path with fill and clipping + assert_approx_equals: path4.getBBox().width {"fill":true,"stroke":false,"markers":false,"clipped":true} expected 90 +/- 0.1 but got 100 +[FAIL] path with stroke + assert_approx_equals: path1.getBBox().x {"fill":false,"stroke":true,"markers":false,"clipped":false} expected 6.2 +/- 0.1 but got 10 +[FAIL] path with markers + assert_approx_equals: path1.getBBox().width {"fill":false,"stroke":false,"markers":true,"clipped":false} expected 112 +/- 0.1 but got 100 +[FAIL] use with fill, stroke, markers and clipping + assert_approx_equals: use1.getBBox().y {"fill":true,"stroke":true,"markers":true,"clipped":true} expected 66 +/- 0.1 but got 70 +[FAIL] foreignObject with fill, stroke, markers and clipping + assert_approx_equals: fo1.getBBox().x {"fill":true,"stroke":true,"markers":true,"clipped":true} expected 53 +/- 0.1 but got 2 +[FAIL] masking-path-07-b.html with fill, stroke, markers and clipping + assert_approx_equals: rect-1.getBBox().x {"fill":true,"stroke":true,"markers":true,"clipped":true} expected 10 +/- 0.1 but got 0 +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGGraphicsElement.getBBox-05.html b/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGGraphicsElement.getBBox-05.html new file mode 100644 index 0000000..1d38640 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/svg/types/scripted/SVGGraphicsElement.getBBox-05.html
@@ -0,0 +1,532 @@ +<!DOCTYPE html> +<title>SVGGraphicsElement.prototype.getBBox for SVGBoundingBoxOptions options</title> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<link rel="help" href="https://svgwg.org/svg2-draft/geometry.html#Sizing"> +<link rel="help" href="https://svgwg.org/svg2-draft/types.html#__svg__SVGGraphicsElement__getBBox"> +<link rel="help" href="https://svgwg.org/svg2-draft/coords.html#BoundingBoxes"> +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" + viewBox="0 0 500 500" width="500px" height="500px"> + <defs> + <clipPath id="rect01" clip-rule="evenodd" clipPathUnits="objectBoundingBox"> + <rect x="0" y="0" width="0.5" height="1.0"/> + </clipPath> + <clipPath id="rect02" clip-rule="evenodd" clipPathUnits="objectBoundingBox"> + <rect x="0.5" y="0" width="0.5" height="1.0"/> + </clipPath> + <clipPath id="rect03" clip-rule="evenodd" clipPathUnits="objectBoundingBox"> + <rect x="0.5" y="0" width="0.5" height="1.0"/> + </clipPath> + <clipPath id="rect04" clip-rule="evenodd" clipPathUnits="objectBoundingBox"> + <rect x="0" y="0" width="0.5" height="1.0"/> + </clipPath> + <clipPath id="rect05" clip-rule="evenodd"> + <rect x="0" y="60" width="10px" height="23px"/> + </clipPath> + <clipPath id="rect06" clip-rule="evenodd"> + <rect x="10" y="60" width="10px" height="23px"/> + </clipPath> + <clipPath id="rect4" clip-rule="evenodd"> + <rect x="200" y="200" width="200" height="200"/> + </clipPath> + <clipPath id="rect-none" clip-rule="evenodd"> + </clipPath> + <clipPath id="rect5" clip-rule="evenodd"> + <rect x="0" y="0" width="100" height="100"/> + </clipPath> + <clipPath id="rect6" clip-rule="evenodd"> + <rect x="150" y="0" width="100" height="100"/> + </clipPath> + <clipPath id="rect7" clip-rule="evenodd"> + <rect x="0" y="100" width="100" height="100"/> + </clipPath> + <clipPath id="rect8" clip-rule="evenodd"> + <rect x="10" y="10" width="180" height="180"/> + </clipPath> + <clipPath id="rect9" clip-rule="evenodd"> + <rect x="100" y="100" width="200" height="200"/> + </clipPath> + + <clipPath id="circle1" clip-rule="evenodd"> + <circle cx="203" cy="203" r="150"/> + </clipPath> + <clipPath id="circle2" clip-rule="evenodd" clipPathUnits="objectBoundingBox"> + <circle cx="0.5" cy="0.5" r="0.25"/> + </clipPath> + <clipPath id="circle3" clip-rule="evenodd"> + <circle cx="100" cy="100" r="50"/> + <circle cx="300" cy="300" r="50"/> + </clipPath> + + <clipPath id="circle4" clip-rule="evenodd"> + <circle cx="50" cy="50" r="50"/> + </clipPath> + <clipPath id="circle5" clip-rule="evenodd"> + <circle cx="150" cy="50" r="50"/> + </clipPath> + <clipPath id="circle6" clip-rule="evenodd"> + <circle cx="50" cy="200" r="50"/> + </clipPath> + <clipPath id="circle7" clip-rule="evenodd" clipPathUnits="objectBoundingBox"> + <circle cx="0.5" cy="0.5" r="0.5"/> + </clipPath> + + <clipPath id="circle8" clip-rule="evenodd" clipPathUnits="userSpaceOnUse"> + <circle cx="110" cy="20" r="90"/> + </clipPath> + + <clipPath id="circle9" clip-rule="evenodd" clipPathUnits="userSpaceOnUse"> + <circle cx="290" cy="20" r="90"/> + </clipPath> + + <clipPath id="circle10" clip-rule="evenodd" clipPathUnits="userSpaceOnUse"> + <circle cx="110" cy="200" r="90"/> + </clipPath> + + <clipPath id="circle11" clip-rule="evenodd"> + <circle cx="0" cy="0" r="150"/> + </clipPath> + + <clipPath id="star" clip-rule="evenodd"> + <path d="M400,25 L619,703 43,283 757,283 181,703 z" /> + </clipPath> + + <marker id="m_atr" markerUnits="strokeWidth" markerWidth="3" markerHeight="3" viewBox="0 0 10 10" refX="5" refY="5"> + <polygon points="0,0 5,5 0,10 10,5" fill="red"/> + </marker> + + <switch> + <rect id="rect-10" x="20" y="20" width="180" height="180" fill="blue" stroke="cyan" stroke-width="8"/> + <rect id="rect-11" x="200" y="20" width="180" height="180" fill="lightgreen" stroke="none" /> + <rect id="rect-12" x="20" y="200" width="180" height="180" fill="darkcyan" stroke="none" /> + </switch> + + <clipPath id="clipCircle1"> + <circle id="c1" cx="100" cy="100" r="50"/> + </clipPath> + + <clipPath id="clipCircle2"> + <circle id="c2" cx="150" cy="150" r="50"/> + </clipPath> + + <clipPath id="clipPath1"> + <path id="p1" d="M10 10l100 0 0 100 -100 0ZM50 50l40 0 0 40 -40 0Z" clip-rule="evenodd"/> + </clipPath> + + <!-- "If a valid 'clip-path' reference is placed on one of the children of a 'clipPath' element, + then the given child element is clipped by the referenced clipping path before OR'ing the + silhouette of the child element with the silhouettes of the other child elements." --> + + <clipPath id="clipRects1"> + <rect x="50" y="30" width="25" height="100"/> + <rect x="25" y="50" width="10" height="10" clip-path="url(#clipTwoCircles)"/> + </clipPath> + + <!-- Test use in a clipPath --> + <clipPath id="clipTwoCircles"> + <use xlink:href="#c1"/> + <use xlink:href="#c2"/> + </clipPath> + + <clipPath id="clipInClip1"> + <use xlink:href="#c2" clip-path="url(#clipCircle1)"/> + <use xlink:href="#p1"/> + </clipPath> + + <clipPath id="clipOnClip1" clip-path="url(#clipCircle1)"> + <use xlink:href="#c2"/> + <use xlink:href="#p1"/> + </clipPath> + + </defs> + + <!-- text --> + <text id="text1" font-size="20px" font-familiy="monospace" fill="red" x="0" y="50" clip-path="url('#rect01')">99</text> + <text id="text2" font-size="20px" font-familiy="monospace" fill="blue" x="100" y="120" clip-path="url('#rect02')">99</text> + <text id="text3" font-size="20px" font-familiy="monospace" clip-path="url('#rect03')" x="0" y="120"> + <tspan x="0" y="50" fill="red">99</tspan> + </text> + <text id="text4" font-size="20px" font-familiy="monospace" clip-path="url('#rect04')" x="0" y="120"> + <tspan x="100" y="120" fill="blue">99</tspan> + </text> + <text id="text5" font-size="20px" font-familiy="monospace" fill="red" x="0" y="80" clip-path="url('#rect05')">99</text> + <text id="text6" font-size="20px" font-familiy="monospace" fill="blue" x="0" y="80" clip-path="url('#rect06')">99</text> + + <!-- image --> + <image id="image1" x="150" y="150" width="200" height="200" preserveApectRatio="none" clip="rect(10px,90px,90px,10px)" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image2" x="2" y="2" width="200" height="200" clip-path="url('#circle1')" preserveApectRatio="none" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image3" x="205" y="2" width="200" height="200" clip-path="url('#circle1')" preserveApectRatio="none" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image4" x="2" y="205" width="200" height="200" clip-path="url('#circle1')" preserveApectRatio="none" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image5" x="205" y="205" width="200" height="200" clip-path="url('#circle1')" preserveApectRatio="none" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image6" x="2" y="2" width="200" height="200" clip-path="url('#circle2')" preserveApectRatio="none" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image7" x="205" y="2" width="200" height="200" clip-path="url('#circle2')" preserveApectRatio="none" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image8" x="2" y="205" width="200" height="200" clip-path="url('#circle2')" preserveApectRatio="none" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image9" x="205" y="205" width="200" height="200" clip-path="url('#circle2')" preserveApectRatio="none" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image10" x="0" y="0" width="400" height="400" clip-path="url('#rect4')" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image11" x="0" y="0" width="400" height="400" clip-path="url('#rect-none')" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image12" x="25" y="43" width="768" height="768" clip-path="url('#star')" preserveApectRatio="none" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image13" x="0" y="0" width="400" height="400" clip-path="url('#circle3')" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <image id="image14" x="0" y="0" width="400" height="400" clip-path="url('#m_atr')" + xlink:href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAIAAACQkWg2AAAAKXRFWHRDcmVhdGlvbiBUaW1lAJCFIDMwIDQgMjAxNCAwOToyODo0MyArMDkwMH73aTcAAAAHdElNRQfeBB4AHhEfV06+AAAACXBIWXMAAB7BAAAewQHDaVRTAAAABGdBTUEAALGPC/xhBQAAABlJREFUeNpjZPj/n4EUwESS6lENoxqGlAYASU8CHux7qQ4AAAAASUVORK5CYII="/> + + <!-- path --> + <path id="path1" d="M10,50 L25,100 H110 V50 Q60,0 10,50" stroke="black" stroke-width="8" stroke-miterlimit="1" stroke-linejoin="miter" fill="lightcyan" marker-mid="url(#m_atr)"/> + <path id="path2" d="M160,50 L175,100 H260 V50 Q210,0 160,50" stroke="black" stroke-width="8" stroke-linejoin="bevel" fill="lightcyan" marker-mid="url(#m_atr)"/> + <path id="path3" d="M10,150 L25,200 H110 V150 Q60,100 10,150" stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan" marker-mid="url(#m_atr)"/> + + + <path id="path4" d="M10,50 L25,100 H110 V50 Q60,0 10,50" stroke="black" stroke-width="8" stroke-miterlimit="1" stroke-linejoin="miter" fill="lightcyan" + marker-mid="url(#m_atr)" clip-path="url(#circle4)"/> + + <path id="path5" d="M160,50 L175,100 H260 V50 Q210,0 160,50" stroke="black" stroke-width="8" stroke-linejoin="bevel" fill="lightcyan" + marker-mid="url(#m_atr)" clip-path="url(#circle5)"/> + + <path id="path6" d="M10,150 L25,200 H110 V150 Q60,100 10,150" stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan" + marker-mid="url(#m_atr)" clip-path="url(#circle6)"/> + + <path id="path7" d="M10,50 L25,100 H110 V50 Q60,0 10,50" + stroke="black" stroke-width="8" stroke-miterlimit="1" stroke-linejoin="miter" fill="lightcyan" + clip-path="url('#rect5')" marker-mid="url(#m_atr)"/> + + <path id="path8" d="M160,50 L175,100 H260 V50 Q210,0 160,50" + stroke="black" stroke-width="8" stroke-linejoin="bevel" fill="lightcyan" + clip-path="url('#rect6')" marker-mid="url(#m_atr)"/> + + <path id="path9" d="M10,150 L25,200 H110 V150 Q60,100 10,150" + stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan" + clip-path="url('#rect7')" marker-mid="url(#m_atr)"/> + + <path id="path10" d="M10,50 L25,100 H110 V50 Q60,0 10,50" + stroke="black" stroke-width="8" stroke-miterlimit="1" stroke-linejoin="miter" fill="lightcyan" + clip-path="url('#circle7')" marker-mid="url(#m_atr)"/> + + <path id="path11" d="M160,50 L175,100 H260 V50 Q210,0 160,50" + stroke="black" stroke-width="8" stroke-linejoin="bevel" fill="lightcyan" + clip-path="url('#circle7')" marker-mid="url(#m_atr)"/> + + <path id="path12" d="M10,150 L25,200 H110 V150 Q60,100 10,150" + stroke="black" stroke-width="8" stroke-linejoin="round" fill="lightcyan" + clip-path="url('#circle7')" marker-mid="url(#m_atr)"/> + + <path id="path13" d="M50,0 C 130,0 50,0 100,50 + C 100,130 100,50 50,100 + C -30,100 50,100 0,50 + C 0,-30 0,50 50,0Z" /> + + <!-- use --> + <use id="use1" xlink:href="#rect-10" x="50" y="50" clip-path="url('#circle8')"/> + <use id="use2" xlink:href="#rect-11" x="50" y="50" clip-path="url('#circle9')"/> + <use id="use3" xlink:href="#rect-12" x="50" y="50" clip-path="url('#circle10')"/> + + <use id="use4" xlink:href="#rect-10" x="2" y="2" width="200" height="200" clip-path="url('#circle11')"/> + <use id="use5" xlink:href="#rect-10" x="205" y="2" width="200" height="200" clip-path="url('#circle11')"/> + <use id="use6" xlink:href="#rect-10" x="2" y="205" width="200" height="200" clip-path="url('#circle11')"/> + <use id="use7" xlink:href="#rect-10" x="205" y="205" width="200" height="200" clip-path="url('#circle11')"/> + + <use id="use8" xlink:href="#rect-10" x="50" y="50" clip-path="url('#m_atr')"/> + + <!-- foreignObject --> + <foreignObject id="fo1" x="2" y="2" width="200" height="200" clip-path="url('#circle1')" clip="rect(2px,102px,102px,2px)"> + <div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;"> +There are issues of dynamic loading required for tiling. According to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed. + </div> + </foreignObject> + <foreignObject id="fo2" x="205" y="2" width="200" height="200" clip-path="url('#circle1')" > + <div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;"> +There are issues of dynamic loading required for tiling. According to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed. + </div> + </foreignObject> + <foreignObject id="fo3" x="2" y="205" width="200" height="200" clip-path="url('#circle1')" > + <div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;"> +There are issues of dynamic loading required for tiling. According to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed. + </div> + </foreignObject> + <foreignObject id="fo4" x="205" y="205" width="200" height="200" clip-path="url('#circle1')" clip="rect(2px,102px,102px,2px)"> + <div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;"> +There are issues of dynamic loading required for tiling. According to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed. + </div> + </foreignObject> + + <foreignObject id="fo5" x="250" y="250" width="200" height="200" clip-path="url('#rect8')"> + <div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;"> +There are issues of dynamic loading required for tiling. According to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed. + </div> + </foreignObject> + + <foreignObject id="fo6" x="0" y="0" width="200" height="200" clip-path="url('#rect9')"> + <div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;"> +There are issues of dynamic loading required for tiling. According to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed. + </div> + </foreignObject> + + <foreignObject id="fo7" x="0" y="0" width="200" height="200" clip-path="url('#rect8')"> + <div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;"> +There are issues of dynamic loading required for tiling. According to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed. + </div> + </foreignObject> + + <foreignObject id="fo8" x="0" y="0" width="200" height="200" clip-path="url('#m_atr')"> + <div xmlns="http://www.w3.org/1999/xhtml" style="background-color:pink;width:100%;height:100%;"> +There are issues of dynamic loading required for tiling. According to 'postpone' attribute of Resource Priorities, the dynamic loading is controlled by positional relation with bounding box of embedded contents and container's viewport. However, each bounding boxes of embedded contents should be whole earth basically when this method is used. (green part on Example) Tiling is impossible unless this situation is changed. + </div> + </foreignObject> + + <!-- --> + <rect id="rect-1" width="200" height="200" fill="blue" clip-path="url(#clipInClip1)"/> + <rect id="rect-2" width="200" height="200" fill="blue" clip-path="url(#clipRects1)"/> + <rect id="rect-3" width="300" height="300" fill="blue" clip-path="url(#clipOnClip1)"/> + + <g clip-path="url(#clipCircle1)" id="g1"> + <use xlink:href="#c2" fill="red"/> + <use xlink:href="#p1" fill="red" fill-rule="evenodd"/> + </g> + +</svg> + +<script> + function assert_bbox(id, opt, x, y, width, height, epsilon) { + if (epsilon == undefined) { + epsilon = 0.1; + } + let bbox = document.getElementById(id).getBBox(opt); + assert_approx_equals(bbox.x, x, epsilon, id + ".getBBox().x " + JSON.stringify(opt)); + assert_approx_equals(bbox.y, y, epsilon, id + ".getBBox().y " + JSON.stringify(opt)); + assert_approx_equals(bbox.width, width, epsilon, id + ".getBBox().width " + JSON.stringify(opt)); + assert_approx_equals(bbox.height, height, epsilon, id + ".getBBox().height " + JSON.stringify(opt)); + } + + function compare_bbox(id1, id2, opt) { + let bbox1 = document.getElementById(id1).getBBox(opt); + let bbox2 = document.getElementById(id2).getBBox(opt); + assert_equals(bbox1.x, bbox2.x, id1 + ".getBBox().x"); + assert_equals(bbox1.y, bbox2.y, id1 + ".getBBox().y"); + assert_approx_equals(bbox1.width, bbox2.width, 0.0002, id1 + ".getBBox().width"); + assert_approx_equals(bbox1.height, bbox2.height, 0.0001, id1 + ".getBBox().height"); + } + + function compare_bbox_without_x(id1, id2, opt) { + let bbox1 = document.getElementById(id1).getBBox(opt); + let bbox2 = document.getElementById(id2).getBBox(opt); + assert_equals(bbox1.y, bbox2.y, id1 + ".getBBox().y"); + assert_approx_equals(bbox1.width, bbox2.width, 0.0002, id1 + ".getBBox().width"); + assert_approx_equals(bbox1.height, bbox2.height, 0.0001, id1 + ".getBBox().height"); + } + +test(t => { + let opt = { fill: true, stroke: false, markers: false, clipped: false }; + compare_bbox("text1", "text3", opt); + compare_bbox("text2", "text4", opt); + compare_bbox("text5", "text6", opt); +}, "text with fill"); + +test(t => { + let opt = { fill: true, stroke: true, markers: true, clipped: true }; + compare_bbox_without_x("text1", "text3", opt); + compare_bbox_without_x("text2", "text4", opt); + compare_bbox_without_x("text5", "text6", opt); +}, "text with fill, stroke, markers and clipping"); + +test(t => { + let opt = { fill: false, stroke: false, markers: false, clipped: true }; + compare_bbox_without_x("text1", "text3", opt); + compare_bbox_without_x("text2", "text4", opt); + compare_bbox_without_x("text5", "text6", opt); +}, "text with clipping"); + +test(t => { + let opt = { fill: true, stroke: true, markers: true, clipped: true }; + assert_bbox("image1", opt, 160, 160, 80, 80); + assert_bbox("image2", opt, 53, 53, 149, 149); + assert_bbox("image3", opt, 205, 53, 148, 149); + assert_bbox("image4", opt, 53, 205, 149, 148); + assert_bbox("image5", opt, 205, 205, 148, 148); + assert_bbox("image6", opt, 52, 52, 100, 100); + assert_bbox("image7", opt, 255, 52, 100, 100); + assert_bbox("image8", opt, 52, 255, 100, 100); + assert_bbox("image9", opt, 255, 255, 100, 100); + assert_bbox("image10", opt, 200, 200, 200, 200); + assert_bbox("image11", opt, 0, 0, 0, 0); + assert_bbox("image12", opt, 43, 43, 714, 660); + assert_bbox("image13", opt, 50, 50, 300, 300); + assert_bbox("image14", opt, 0, 0, 0, 0); +}, "image with fill, stroke, markers and clipping"); + +test(t => { + let opt = { fill: true, stroke: false, markers: false, clipped: false }; + assert_bbox("image1", opt, 150, 150, 200, 200); + assert_bbox("image2", opt, 2, 2, 200, 200); + assert_bbox("image3", opt, 205, 2, 200, 200); + assert_bbox("image4", opt, 2, 205, 200, 200); + assert_bbox("image5", opt, 205, 205, 200, 200); + assert_bbox("image6", opt, 2, 2, 200, 200); + assert_bbox("image7", opt, 205, 2, 200, 200); + assert_bbox("image8", opt, 2, 205, 200, 200); + assert_bbox("image9", opt, 205, 205, 200, 200); + assert_bbox("image10", opt, 0, 0, 400, 400); + assert_bbox("image11", opt, 0, 0, 400, 400); + assert_bbox("image12", opt, 25, 43, 768, 768); + assert_bbox("image13", opt, 0, 0, 400, 400); +}, "image with fill"); + +test(t => { + let opt = { fill: true, stroke: true, markers: true, clipped: true }; + assert_bbox("path1", opt, 6.2, 20.8, 115.8, 91.2, 0.1); + assert_bbox("path2", opt, 156.2, 20.8, 115.8, 91.2, 0.1); + assert_bbox("path3", opt, 6.2, 120.7, 115.8, 91.2, 0.1); + assert_bbox("path4", opt, 6.2, 20.8, 93.8, 79.2, 0.1); + assert_bbox("path5", opt, 156.2, 20.8, 43.8, 79.2, 0.1); + assert_bbox("path6", opt, 6.2, 150, 93.8, 62, 0.1); + assert_bbox("path7", opt, 6.2, 20.8, 93.8, 79.2, 0.1); + assert_bbox("path8", opt, 156.2, 20.8, 93.8, 79.2, 0.1); + assert_bbox("path9", opt, 6.2, 120.8, 93.8, 79.2, 0.1); + assert_bbox("path10", opt, 10, 25, 100, 75); + assert_bbox("path11", opt, 160, 25, 100, 75); + assert_bbox("path12", opt, 10, 125, 100, 75); +}, "path with fill, stroke, markers and clipping"); + +test(t => { + let opt = { fill: true, stroke: false, markers: false, clipped: true }; + assert_bbox("path1", opt, 10, 25, 100, 75); + assert_bbox("path2", opt, 160, 25, 100, 75); + assert_bbox("path3", opt, 10, 125, 100, 75); + assert_bbox("path4", opt, 10, 25, 90, 75); + assert_bbox("path5", opt, 160, 25, 40, 75); + assert_bbox("path6", opt, 10, 150, 90, 50); + assert_bbox("path7", opt, 10, 25, 90, 75); + assert_bbox("path8", opt, 160, 25, 90, 75); + assert_bbox("path9", opt, 10, 125, 90, 75); + assert_bbox("path10", opt, 10, 25, 100, 75); + assert_bbox("path11", opt, 160, 25, 100, 75); + assert_bbox("path12", opt, 10, 125, 100, 75); +}, "path with fill and clipping"); + +test(t => { + let opt = { fill: true, stroke: false, markers: false, clipped: false }; + assert_bbox("path1", opt, 10, 25, 100, 75); + assert_bbox("path2", opt, 160, 25, 100, 75); + assert_bbox("path3", opt, 10, 125, 100, 75); + assert_bbox("path4", opt, 10, 25, 100, 75); + assert_bbox("path5", opt, 160, 25, 100, 75); + assert_bbox("path6", opt, 10, 125, 100, 75); + assert_bbox("path7", opt, 10, 25, 100, 75); + assert_bbox("path8", opt, 160, 25, 100, 75); + assert_bbox("path9", opt, 10, 125, 100, 75); + assert_bbox("path10", opt, 10, 25, 100, 75); + assert_bbox("path11", opt, 160, 25, 100, 75); + assert_bbox("path12", opt, 10, 125, 100, 75); + assert_bbox("path13", opt, 0, 0, 100, 100); +}, "path with fill"); + +test(t => { + let opt = { fill: false, stroke: true, markers: false, clipped: false }; + assert_bbox("path1", opt, 6.2, 20.8, 107.8, 83.2, 0.1); + assert_bbox("path2", opt, 156.2, 20.8, 107.8, 83.2, 0.1); + assert_bbox("path3", opt, 6.2, 120.8, 107.8, 83.2, 0.1); + assert_bbox("path4", opt, 6.2, 20.8, 107.8, 83.2, 0.1); + assert_bbox("path5", opt, 156.2, 20.8, 107.8, 83.2, 0.1); + assert_bbox("path6", opt, 6.2, 120.8, 107.8, 83.2, 0.1); + assert_bbox("path7", opt, 6.2, 20.8, 107.8, 83.2, 0.1); + assert_bbox("path8", opt, 156.2, 20.8, 107.8, 83.2, 0.1); + assert_bbox("path9", opt, 6.2, 120.8, 107.8, 83.2, 0.1); + assert_bbox("path10", opt, 6.2, 20.8, 107.8, 83.2, 0.1); + assert_bbox("path11", opt, 156.2, 20.8, 107.8, 83.2, 0.1); + assert_bbox("path12", opt, 6.2, 120.8, 107.8, 83.2, 0.1); +}, "path with stroke"); + +test(t => { + let opt = { fill: false, stroke: false, markers: true, clipped: false }; + assert_bbox("path1", opt, 10, 25, 112, 87); + assert_bbox("path2", opt, 160, 25, 112, 87); + assert_bbox("path3", opt, 10, 125, 112, 87); + assert_bbox("path4", opt, 10, 25, 112, 87); + assert_bbox("path5", opt, 160, 25, 112, 87); + assert_bbox("path6", opt, 10, 125, 112, 87); + assert_bbox("path7", opt, 10, 25, 112, 87); + assert_bbox("path8", opt, 160, 25, 112, 87); + assert_bbox("path9", opt, 10, 125, 112, 87); + assert_bbox("path10", opt, 10, 25, 112, 87); + assert_bbox("path11", opt, 160, 25, 112, 87); + assert_bbox("path12", opt, 10, 125, 112, 87); +}, "path with markers"); + +test(t => { + let opt = { fill: true, stroke: false, markers: false, clipped: false }; + assert_bbox("use1", opt, 70, 70, 180, 180); + assert_bbox("use2", opt, 250, 70, 180, 180); + assert_bbox("use3", opt, 70, 250, 180, 180); + assert_bbox("use4", opt, 22, 22, 180, 180); + assert_bbox("use5", opt, 225, 22, 180, 180); + assert_bbox("use6", opt, 22, 225, 180, 180); + assert_bbox("use7", opt, 225, 225, 180, 180); +}, "use with fill"); + +test(t => { + let opt = { fill: true, stroke: true, markers: true, clipped: true }; + assert_bbox("use1", opt, 70, 66, 180, 94); + assert_bbox("use2", opt, 250, 70, 180, 90); + assert_bbox("use3", opt, 70, 250, 180, 90); + assert_bbox("use4", opt, 18, 18, 134, 134); + assert_bbox("use5", opt, 221, 18, 134, 134); + assert_bbox("use6", opt, 18, 221, 134, 134); + assert_bbox("use7", opt, 221, 221, 134, 134); + assert_bbox("use8", opt, 0, 0, 0, 0); +}, "use with fill, stroke, markers and clipping"); + +test(t => { + let opt = { fill: true, stroke: false, markers: false, clipped: false }; + assert_bbox("fo1", opt, 2, 2, 200, 200); + assert_bbox("fo2", opt, 205, 2, 200, 200); + assert_bbox("fo3", opt, 2, 205, 200, 200); + assert_bbox("fo4", opt, 205, 205, 200, 200); + assert_bbox("fo5", opt, 250, 250, 200, 200); + assert_bbox("fo6", opt, 0, 0, 200, 200); + assert_bbox("fo7", opt, 0, 0, 200, 200); +}, "foreignObject with fill"); + +test(t => { + let opt = { fill: true, stroke: true, markers: true, clipped: true }; + assert_bbox("fo1", opt, 53, 53, 51, 51); + assert_bbox("fo2", opt, 205, 53, 148, 149); + assert_bbox("fo3", opt, 53, 205, 149, 148); + assert_bbox("fo4", opt, 207, 207, 100, 100); + assert_bbox("fo5", opt, 0, 0, 0, 0); + assert_bbox("fo6", opt, 100, 100, 100, 100); + assert_bbox("fo7", opt, 10, 10, 180, 180); + assert_bbox("fo8", opt, 0, 0, 0, 0); +}, "foreignObject with fill, stroke, markers and clipping"); + +// from http://www.w3.org/Graphics/SVG/Test/20110816/harness/htmlObjectApproved/masking-path-07-b.html +test(t => { + let opt = { fill: true, stroke: true, markers: true, clipped: true }; + assert_bbox("rect-1", opt, 10, 10, 140, 140); + assert_bbox("rect-2", opt, 50, 30, 25, 100); + assert_bbox("rect-3", opt, 50, 50, 100, 100); + assert_bbox("g1", opt, 50, 50, 100, 100); +}, "masking-path-07-b.html with fill, stroke, markers and clipping"); +</script>
diff --git a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any.js b/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any.js index 51b1070d..1143bab 100644 --- a/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any.js +++ b/third_party/blink/web_tests/external/wpt/wasm/jsapi/table/constructor.any.js
@@ -206,3 +206,8 @@ assert_throws_js(TypeError, () => new WebAssembly.Table(argument, "cannot be used as a wasm function")); assert_throws_js(TypeError, () => new WebAssembly.Table(argument, 37)); }, "initialize anyfunc table with a bad default value"); + +test(() => { + assert_throws_js(RangeError, () => + new WebAssembly.Table({ "element": "anyfunc", "initial": 3, "maximum": 2 }, 37)); +}, "initialize anyfunc table with a bad default value and a bad descriptor");
diff --git a/third_party/blink/web_tests/external/wpt/webcodecs/audio-decoder.https.any.js b/third_party/blink/web_tests/external/wpt/webcodecs/audio-decoder.https.any.js index 666d3a15..98ed498 100644 --- a/third_party/blink/web_tests/external/wpt/webcodecs/audio-decoder.https.any.js +++ b/third_party/blink/web_tests/external/wpt/webcodecs/audio-decoder.https.any.js
@@ -5,6 +5,8 @@ const detachedArrayBuffer = new ArrayBuffer(4); var b = detachedArrayBuffer.transferToFixedLength(); +const emptyArrayBuffer = new ArrayBuffer(0); + const invalidConfigs = [ { comment: 'Missing codec', @@ -60,6 +62,40 @@ description: detachedArrayBuffer }, }, + { + comment: 'Vorbis without description', + config: { + codec: 'vorbis', + sampleRate: 48000, + numberOfChannels: 2, + }, + }, + { + comment: 'Vorbis with empty description', + config: { + codec: 'vorbis', + sampleRate: 48000, + numberOfChannels: 2, + description: emptyArrayBuffer, + }, + }, + { + comment: 'Flac without description', + config: { + codec: 'flac', + sampleRate: 48000, + numberOfChannels: 2, + }, + }, + { + comment: 'Flac with empty description', + config: { + codec: 'flac', + sampleRate: 48000, + numberOfChannels: 2, + description: emptyArrayBuffer, + }, + }, ]; invalidConfigs.forEach(entry => {
diff --git a/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-animates.html b/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-animates.html index 0c43e26..056d650 100644 --- a/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-animates.html +++ b/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-animates.html
@@ -28,38 +28,16 @@ } internals.settings.setScrollAnimatorEnabled(true); -function smoothScrollPromise(container) { - let firstScrollPosition = undefined; - let lastScrollPosition = undefined; - return new Promise((resolve, reject) => { - const scrollendListener = () => { - container.removeEventListener('scroll', scrollListener); - if (lastScrollPosition == firstScrollPosition) { - reject('expected multiple scroll events with a smooth scroll'); - } else { - resolve(); - } - } - container.addEventListener('scrollend', scrollendListener, { once: true }); - const scrollListener = () => { - if (firstScrollPosition == undefined) { - firstScrollPosition = container.scrollTop; - } - lastScrollPosition = container.scrollTop; - } - container.addEventListener('scroll', scrollListener); - }); -} - promise_test(async () => { const container = document.getElementById("container"); await waitForCompositorCommit(); await waitForScrollReset(container); - const animatedScroll = smoothScrollPromise(container); const pos = elementCenter(container); await mouseClick(pos.x, pos.y); - await keyboardScroll("PageDown", container); - await animatedScroll; + await Promise.all([ + animatedScrollPromise(container), + keyboardScroll("PageDown", container), + ]); assert_true(container.scrollTop > 0); }, 'Overflow scrolls are animated');
diff --git a/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-root-frame-animates-expected.txt b/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-root-frame-animates-expected.txt deleted file mode 100644 index 9c5e90f..0000000 --- a/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-root-frame-animates-expected.txt +++ /dev/null
@@ -1,11 +0,0 @@ -Tests that overflow scrolls on the root frame are animated. - -On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE". - -PASS window.scrollY is not document.body.scrollHeight - window.innerHeight -PASS window.scrollY is > 0 -PASS window.scrollY is > prevScrollY -PASS successfullyParsed is true - -TEST COMPLETE -
diff --git a/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-root-frame-animates.html b/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-root-frame-animates.html index 39aeffaf..817ccf1 100644 --- a/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-root-frame-animates.html +++ b/third_party/blink/web_tests/fast/scroll-behavior/overflow-scroll-root-frame-animates.html
@@ -1,4 +1,9 @@ <!DOCTYPE html> +<script src="../../resources/testharness.js"></script> +<script src="../../resources/testharnessreport.js"></script> +<script src="../../resources/gesture-util.js"></script> +<title>Tests that overflow scrolls on the root element are animated.</title> + <style> #content { width: 750px; @@ -6,50 +11,23 @@ background-color: blue; } </style> -<script src="../../resources/js-test.js"></script> -<script src="../../resources/run-after-layout-and-paint.js"></script> + <div id="content"></div> -<div id="console"></div> + <script> - -jsTestIsAsync = true; - -var prevScrollY; -var scrollStart; - -function runTest() { - internals.settings.setScrollAnimatorEnabled(true); - - window.addEventListener("scroll", onWindowScroll); - - runAfterLayoutAndPaint(function() { - eventSender.keyDown('End'); - }); +if (!window.internals) { + assert_unreached("This test must be run in the test harness"); } +internals.settings.setScrollAnimatorEnabled(true); -function onWindowScroll() { - if (typeof prevScrollY === 'undefined') { - shouldNotBe("window.scrollY", - "document.body.scrollHeight - window.innerHeight"); - shouldBeGreaterThan("window.scrollY", "0"); - prevScrollY = window.scrollY; - - if (window.scrollY === document.body.scrollHeight - window.innerHeight) { - // We wont get another scroll event. The failure was reported above - // but return early to prevent a timeout. - finishJSTest(); - } - } else { - shouldBeGreaterThan("window.scrollY", "prevScrollY"); - finishJSTest(); - } -} - -description("Tests that overflow scrolls on the root frame are animated."); - -if (window.eventSender) - runTest(); -else - debug("FAIL: This test requires window.eventSender."); - +promise_test(async () => { + await waitForCompositorCommit(); + await waitForScrollReset(document.scrollingElement); + await Promise.all([ + animatedScrollPromise(document), + keyboardScroll("End", document), + ]); + assert_true( + window.scrollY >= document.body.scrollHeight - window.innerHeight); +}, "Tests that overflow scrolls on the root element are animated."); </script>
diff --git a/third_party/blink/web_tests/fast/scrolling/autoscroll-iframe-no-scrolling.html b/third_party/blink/web_tests/fast/scrolling/autoscroll-iframe-no-scrolling.html index 1d68352..6f91d7ef 100644 --- a/third_party/blink/web_tests/fast/scrolling/autoscroll-iframe-no-scrolling.html +++ b/third_party/blink/web_tests/fast/scrolling/autoscroll-iframe-no-scrolling.html
@@ -31,6 +31,7 @@ body { width: 410px; height: 410px; + margin: 0px; } #scroller { width: 300px; @@ -67,16 +68,31 @@ }); } -window.addEventListener('load', () => { +function cancelAutoScroll() { + return new Promise((resolve, reject) => { + if (!window.eventSender) { + reject(); + } else { + const LEFT_BUTTON = 0; + eventSender.mouseDown(LEFT_BUTTON); + eventSender.mouseUp(LEFT_BUTTON); + resolve(); + } + }); +} + +scrollable.addEventListener('load', () => { var inner_scroller = frames[0].document.getElementById('scroller'); inner_scroller.scrollTop = 1000; promise_test(async t => { + await waitForCompositorReady(); + const MIDDLE_CLICK_AUTOSCROLL_RADIUS = 15; // from blink::kNoMiddleClickAutoscrollRadius var rect = scrollable.getBoundingClientRect(); - var startX = rect.left + 50; - var startY = rect.top + 50; + var startX = rect.left + inner_scroller.clientWidth / 3; + var startY = rect.top + inner_scroller.clientHeight / 3; var endX = startX; - var endY = startY + 30 * MIDDLE_CLICK_AUTOSCROLL_RADIUS; + var endY = startY + window.visualViewport.height * 0.75; assert_equals(inner_scroller.scrollTop, inner_scroller.scrollHeight - inner_scroller.clientHeight, "Inner scroller starts fully scrolled."); @@ -84,18 +100,33 @@ assert_equals(frames[0].window.scrollY, 0, "IFrame starts unscrolled."); // Autoscroll over the inner scroller. + let scrollEventPromise = waitForScrollEvent(document); + let scrollEndPromise = waitForScrollendEvent(document); await autoScroll(startX, startY, endX, endY); - await waitForAnimationEndTimeBased( () => { return window.scrollY; } ); + await scrollEventPromise; + await cancelAutoScroll(); + await scrollEndPromise; + assert_true(window.scrollY > 0, "Main frame should have scrolled for the first scroll."); assert_equals(frames[0].window.scrollY, 0, "Iframe frame should not scroll"); - // Autoscroll over the iframe. - startX = rect.right - 20; + // Reset the scroll offset of the document so that the events in the next phase + // of the test are sent to a consistent target for each test iteration. + await waitForScrollReset(); + assert_equals(window.scrollY, 0, "Scroll should be reset."); + + // Autoscroll over the iframe. Ensure the pointer is over the iframe and not the inner + // scroller. + startX = rect.right - (rect.width - inner_scroller.clientWidth) / 2; endX = startX; + scrollEventPromise = waitForScrollEvent(document); + scrollEndPromise = waitForScrollendEvent(document); await autoScroll(startX, startY, endX, endY); - await waitForAnimationEndTimeBased( () => { return window.scrollY; } ); - assert_true(window.scrollY > 0, "Main frame should not scroll"); - assert_equals(frames[0].window.scrollY, 0, "IFrame must NOT scroll."); + await scrollEventPromise; + await cancelAutoScroll(); + await scrollEndPromise; + assert_true(window.scrollY > 0, "Main frame should have scrolled for the second scroll."); + assert_equals(frames[0].window.scrollY, 0, "Iframe frame should not scroll"); }); }); -</script> +</script> \ No newline at end of file
diff --git a/third_party/blink/web_tests/fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html b/third_party/blink/web_tests/fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html index 2206691..df56707c 100644 --- a/third_party/blink/web_tests/fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html +++ b/third_party/blink/web_tests/fast/scrolling/document-level-touchmove-event-listener-passive-by-default.html
@@ -4,7 +4,7 @@ <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> <script src="../../resources/gesture-util.js"></script> -<body onload=runTest()> +<body> <div id="touchDiv"> </div> </body> @@ -15,28 +15,26 @@ } </style> <script> -var touch_div = document.getElementById("touchDiv"); -var rect = touch_div.getBoundingClientRect(); -var x = rect.left + rect.width / 2; -var y = rect.top + rect.height / 2; -var cancelable = true; -var touch_move_arrived = false; -document.addEventListener("touchmove", function (event) { - cancelable = event.cancelable; - touch_move_arrived = true; - event.preventDefault(); -}); function injectInput() { + const touch_div = document.getElementById("touchDiv"); + const rect = touch_div.getBoundingClientRect(); + const x = rect.left + rect.width / 2; + const y = rect.top + rect.height / 2; return smoothScroll(10, x, y, GestureSourceType.TOUCH_INPUT, "down"); } -function runTest() { +window.onload = async () => { promise_test (async () => { + const touchMovePromise = waitForEvent(document, 'touchmove'); await waitForCompositorCommit(); await injectInput(); - await waitFor(()=> { return touch_move_arrived; }); - assert_false(cancelable); - }, "Touchmove events are non-cancelable since the event listener is treated as passive."); -} + await touchMovePromise.then((event) => { + assert_false(event.cancelable); + event.preventDefault(); + }); + }, "Touchmove events are non-cancelable since the event listener is " + + "treated as passive."); +}; + </script>
diff --git a/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-multiple-iframes-expected.txt b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-multiple-iframes-expected.txt new file mode 100644 index 0000000..de9d03e --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-multiple-iframes-expected.txt
@@ -0,0 +1,104 @@ +Tests that `Page.frameSubtreeWillBeDetached` event is emitted for each iFrame before the frames are detached +... creating and navigating iframe http://127.0.0.1:8000/inspector-protocol/resources/same_origin_iframe.html +... iframe created and navigated +... creating and navigating iframe http://127.0.0.1:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... creating and navigating iframe http://oopif.test:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... creating and navigating iframe http://devtools.test:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... removing all the iframes +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 0> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 1> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 0> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 2> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 3> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 2> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 4> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 5> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 4> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 6> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 7> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 6> + reason : remove + } + sessionId : <string> +} +... done removing all the iframes +
diff --git a/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-nested-iframes-expected.txt b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-nested-iframes-expected.txt new file mode 100644 index 0000000..846addc --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-site-isolation-trials/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-nested-iframes-expected.txt
@@ -0,0 +1,110 @@ +Tests that `Page.frameSubtreeWillBeDetached` event is emitted before the frame subtree is detached +... creating and navigating iframe http://127.0.0.1:8000/inspector-protocol/resources/same_origin_iframe.html +... iframe created and navigated +... removing the frame +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 0> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 1> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 0> + reason : remove + } + sessionId : <string> +} +... done removing the frame +... creating and navigating iframe http://127.0.0.1:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... removing the frame +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 2> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 3> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 2> + reason : remove + } + sessionId : <string> +} +... done removing the frame +... creating and navigating iframe http://oopif.test:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... removing the frame +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 4> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 5> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 4> + reason : remove + } + sessionId : <string> +} +... done removing the frame +... creating and navigating iframe http://devtools.test:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... removing the frame +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 6> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 7> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 6> + reason : remove + } + sessionId : <string> +} +... done removing the frame +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-multiple-iframes-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-multiple-iframes-expected.txt new file mode 100644 index 0000000..d15edb0 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-multiple-iframes-expected.txt
@@ -0,0 +1,96 @@ +Tests that `Page.frameSubtreeWillBeDetached` event is emitted for each iFrame before the frames are detached +... creating and navigating iframe http://127.0.0.1:8000/inspector-protocol/resources/same_origin_iframe.html +... iframe created and navigated +... creating and navigating iframe http://127.0.0.1:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... creating and navigating iframe http://oopif.test:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... creating and navigating iframe http://devtools.test:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... removing all the iframes +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 0> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 1> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 0> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 2> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 3> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 2> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 4> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 4> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 5> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 6> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 5> + reason : remove + } + sessionId : <string> +} +... done removing all the iframes +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-multiple-iframes.js b/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-multiple-iframes.js new file mode 100644 index 0000000..e9847ec --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-multiple-iframes.js
@@ -0,0 +1,38 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function (/** @type {import('test_runner').TestRunner} */ testRunner) { + const {session, dp} = await testRunner.startBlank( + 'Tests that `Page.frameSubtreeWillBeDetached` event is emitted for each iFrame before the frames are detached'); + + const testUrls = [ + // Page -> same origin iframe -> same origin iframe. + 'http://127.0.0.1:8000/inspector-protocol/resources/same_origin_iframe.html', + // Page -> same origin iframe -> cross origin iframe. + 'http://127.0.0.1:8000/inspector-protocol/resources/cross_origin_iframe.html', + // Page -> cross origin iframe -> same origin iframe. + 'http://oopif.test:8000/inspector-protocol/resources/cross_origin_iframe.html', + // Page -> cross origin iframe -> cross origin iframe. + 'http://devtools.test:8000/inspector-protocol/resources/cross_origin_iframe.html', + ]; + + const frameSubtreeWillBeDetachedHelper = await testRunner.loadScript( + './resources/frame-subtree-will-be-detached-helper.js'); + const navigationHelper = await testRunner.loadScript( + '../resources/navigation-helper.js'); + + await frameSubtreeWillBeDetachedHelper.initTest(testRunner, dp, session, + navigationHelper); + + for (const url of testUrls) { + await frameSubtreeWillBeDetachedHelper.createAndWaitIframe(testRunner, session, + navigationHelper, url); + } + + testRunner.log('... removing all the iframes'); + await session.evaluate('document.body.innerHTML = ""'); + testRunner.log('... done removing all the iframes'); + + testRunner.completeTest(); +}); \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-nested-iframes-expected.txt b/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-nested-iframes-expected.txt new file mode 100644 index 0000000..1fe0775 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-nested-iframes-expected.txt
@@ -0,0 +1,102 @@ +Tests that `Page.frameSubtreeWillBeDetached` event is emitted before the frame subtree is detached +... creating and navigating iframe http://127.0.0.1:8000/inspector-protocol/resources/same_origin_iframe.html +... iframe created and navigated +... removing the frame +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 0> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 1> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 0> + reason : remove + } + sessionId : <string> +} +... done removing the frame +... creating and navigating iframe http://127.0.0.1:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... removing the frame +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 2> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 3> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 2> + reason : remove + } + sessionId : <string> +} +... done removing the frame +... creating and navigating iframe http://oopif.test:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... removing the frame +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 4> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 4> + reason : remove + } + sessionId : <string> +} +... done removing the frame +... creating and navigating iframe http://devtools.test:8000/inspector-protocol/resources/cross_origin_iframe.html +... iframe created and navigated +... removing the frame +Received event{ + method : Page.frameSubtreeWillBeDetached + params : { + frameId : <string 5> + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 6> + reason : remove + } + sessionId : <string> +} +Received event{ + method : Page.frameDetached + params : { + frameId : <string 5> + reason : remove + } + sessionId : <string> +} +... done removing the frame +
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-nested-iframes.js b/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-nested-iframes.js new file mode 100644 index 0000000..eb10e652 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/page/frame-subtree-will-be-detached-nested-iframes.js
@@ -0,0 +1,42 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function (/** @type {import('test_runner').TestRunner} */ testRunner) { + const {session, dp} = await testRunner.startBlank( + 'Tests that `Page.frameSubtreeWillBeDetached` event is emitted before the frame subtree is detached'); + + const testUrls = [ + // Page -> same origin iframe -> same origin iframe. + 'http://127.0.0.1:8000/inspector-protocol/resources/same_origin_iframe.html', + // Page -> same origin iframe -> cross origin iframe. + 'http://127.0.0.1:8000/inspector-protocol/resources/cross_origin_iframe.html', + // Page -> cross origin iframe -> same origin iframe. + 'http://oopif.test:8000/inspector-protocol/resources/cross_origin_iframe.html', + // Page -> cross origin iframe -> cross origin iframe. + 'http://devtools.test:8000/inspector-protocol/resources/cross_origin_iframe.html', + ]; + + const frameSubtreeWillBeDetachedHelper = await testRunner.loadScript( + './resources/frame-subtree-will-be-detached-helper.js'); + const navigationHelper = await testRunner.loadScript( + '../resources/navigation-helper.js'); + + await frameSubtreeWillBeDetachedHelper.initTest(testRunner, dp, session, + navigationHelper); + + async function navigateAndRemoveIframe(url) { + await frameSubtreeWillBeDetachedHelper.createAndWaitIframe(testRunner, session, + navigationHelper, url); + + testRunner.log('... removing the frame'); + await session.evaluate('frame.remove()'); + testRunner.log(`... done removing the frame`); + } + + for (const url of testUrls) { + await navigateAndRemoveIframe(url); + } + + testRunner.completeTest(); +}); \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/page/resources/frame-subtree-will-be-detached-helper.js b/third_party/blink/web_tests/http/tests/inspector-protocol/page/resources/frame-subtree-will-be-detached-helper.js new file mode 100644 index 0000000..47512bb --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/page/resources/frame-subtree-will-be-detached-helper.js
@@ -0,0 +1,43 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async () => { + async function initTest(testRunner, dp, session, navigationHelper) { + const stableNames = ['sessionId', 'callFrames']; + const stableValues = ['parentFrameId', 'frameId', 'targetId',]; + + const logEvent = (event) => { + testRunner.log(event, 'Received event', stableNames, stableValues); + }; + + /** + * Set up the CDP protocol target. Sets events listeners, sets auto attach and + * enables the Page domain. + */ + await navigationHelper.initProtocolRecursively(dp, session, + async (dp) => { + dp.Page.onFrameDetached(event => { + if (event.params.reason !== 'swap') { + logEvent(event); + } + }); + dp.Page.onFrameSubtreeWillBeDetached(logEvent); + }); + } + + async function createAndWaitIframe(testRunner, session, navigationHelper, url) { + const nestedIframeLoadedPromise = navigationHelper.onceFrameStoppedLoading( + 'resources/empty.html'); + testRunner.log(`... creating and navigating iframe ${url}`); + await session.evaluate(` + window.frame = document.createElement('iframe'); + frame.src = '${url}'; + document.body.appendChild(frame); + `); + await nestedIframeLoadedPromise; + testRunner.log(`... iframe created and navigated`); + } + + return {createAndWaitIframe, initTest}; +})(); \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/cross_origin_iframe.html b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/cross_origin_iframe.html new file mode 100644 index 0000000..c38a47f51 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/cross_origin_iframe.html
@@ -0,0 +1,7 @@ +<!-- +Copyright 2024 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<!DOCTYPE html> +<iframe src='http://oopif.test:8000/inspector-protocol/resources/empty.html'></iframe>
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js index 58f95cac..2cf9d24 100644 --- a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/inspector-protocol-test.js
@@ -22,6 +22,7 @@ this._fetch = fetch; this._params = params; this._browserSession = new TestRunner.Session(this, ''); + this._stableValues = new Map(); } static get stabilizeNames() { @@ -69,9 +70,9 @@ this._completeTest.call(null); } - log(item, title, stabilizeNames) { + log(item, title, stabilizeNames, stabilizeValues) { if (typeof item === 'object') - return this._logObject(item, title, stabilizeNames); + return this._logObject(item, title, stabilizeNames, stabilizeValues); this._log.call(null, item); } @@ -84,8 +85,9 @@ return this._params; } - _logObject(object, title, stabilizeNames = TestRunner.stabilizeNames) { + _logObject(object, title, stabilizeNames = TestRunner.stabilizeNames, stabilizeValues = []) { var lines = []; + const stableValues = this._stableValues; function dumpValue(value, prefix, prefixWithName) { if (typeof value === 'object' && value !== null) { @@ -111,8 +113,14 @@ continue; var prefixWithName = ' ' + prefix + name + ' : '; var value = object[name]; - if (stabilizeNames && stabilizeNames.includes(name)) + if (stabilizeValues && stabilizeValues.includes(name)) { + if (!stableValues.has(value)) { + stableValues.set(value, `<${typeof value} ${stableValues.size}>`); + } + value = stableValues.get(value); + } else if (stabilizeNames && stabilizeNames.includes(name)) { value = `<${typeof value}>`; + } dumpValue(value, ' ' + prefix, prefixWithName); } lines.push(prefix + '}');
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/navigation-helper.js b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/navigation-helper.js new file mode 100644 index 0000000..4209eb1f --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/navigation-helper.js
@@ -0,0 +1,79 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(() => { + // Map from urlSuffix to list of resolve functions. + const frameNavigatedDelegatesMap = new Map(); + // Map frameId to list of resolve functions. + const frameStoppedLoadingDelegatesMap = new Map(); + + async function initProtocolRecursively(dp, session, initDelegate) { + await dp.Target.setAutoAttach( + {autoAttach: true, waitForDebuggerOnStart: true, flatten: true}); + + dp.Target.onAttachedToTarget(async event => { + const childDp = session.createChild( + event.params.sessionId).protocol; + await initProtocolRecursively(childDp, session, initDelegate); + }); + + dp.Page.onFrameNavigated(event => { + // Check if there are any frameNavigated delegates that need to be + // resolved. + frameNavigatedDelegatesMap.keys().forEach(urlSuffix => { + if (event.params.frame.url.endsWith(urlSuffix)) { + for (const resolve of frameNavigatedDelegatesMap.get(urlSuffix)) { + resolve(event.params.frameId); + } + frameNavigatedDelegatesMap.delete(urlSuffix); + } + }); + }); + + dp.Page.onFrameStoppedLoading(event => { + // Check if there are any frameStoppedLoading delegates that need to be + // resolved. + (frameStoppedLoadingDelegatesMap.get(event.frameId) ?? []).forEach( + resolve => { + resolve(); + }); + }); + + await initDelegate(dp); + + await dp.Page.enable(); + await dp.Runtime.runIfWaitingForDebugger(); + }; + + function onceFrameNavigated(urlSuffix) { + return new Promise(resolve => { + if (frameNavigatedDelegatesMap.get(urlSuffix) === undefined) { + frameNavigatedDelegatesMap.set(urlSuffix, []); + } + frameNavigatedDelegatesMap.get(urlSuffix).push(resolve); + }); + } + + async function onceFrameStoppedLoading(urlSuffix) { + const frameId = await onceFrameNavigated(urlSuffix); + return new Promise(resolve => { + if (frameStoppedLoadingDelegatesMap.get(frameId) === undefined) { + frameStoppedLoadingDelegatesMap.set(frameId, []); + } + frameStoppedLoadingDelegatesMap.get(frameId).push(resolve); + }); + } + + return { + // Call the initDelegate function on the given session and all the attached + // in future targets. + initProtocolRecursively, + // Returns a promise that resolves when a frame with the given urlSuffix + // has been navigated. + onceFrameNavigated, + // Returns a promise that resolves when a frame with the given urlSuffix + // has been navigated and stopped loading. + onceFrameStoppedLoading + }; +})() \ No newline at end of file
diff --git a/third_party/blink/web_tests/http/tests/inspector-protocol/resources/same_origin_iframe.html b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/same_origin_iframe.html new file mode 100644 index 0000000..7541fc9 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/inspector-protocol/resources/same_origin_iframe.html
@@ -0,0 +1,7 @@ +<!-- +Copyright 2024 The Chromium Authors +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<!DOCTYPE html> +<iframe src='http://127.0.0.1:8000/inspector-protocol/resources/empty.html'></iframe>
diff --git a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt index 1ed17acc..9a8823c 100644 --- a/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt +++ b/third_party/blink/web_tests/http/tests/serviceworker/webexposed/global-interface-listing-service-worker-expected.txt
@@ -1361,6 +1361,7 @@ method inspect method last method map + method reduce method some method subscribe method switchMap
diff --git a/third_party/blink/web_tests/virtual/attribution-reporting-aggregatable-debug/DIR_METADATA b/third_party/blink/web_tests/virtual/attribution-reporting-aggregatable-debug/DIR_METADATA new file mode 100644 index 0000000..45ce9f2 --- /dev/null +++ b/third_party/blink/web_tests/virtual/attribution-reporting-aggregatable-debug/DIR_METADATA
@@ -0,0 +1,6 @@ +monorail: { + component: "Internals>AttributionReporting" +} +buganizer_public: { + component_id: 1456103 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/attribution-reporting-in-browser-migration/DIR_METADATA b/third_party/blink/web_tests/virtual/attribution-reporting-in-browser-migration/DIR_METADATA new file mode 100644 index 0000000..45ce9f2 --- /dev/null +++ b/third_party/blink/web_tests/virtual/attribution-reporting-in-browser-migration/DIR_METADATA
@@ -0,0 +1,6 @@ +monorail: { + component: "Internals>AttributionReporting" +} +buganizer_public: { + component_id: 1456103 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/cookie-deprecation-label/DIR_METADATA b/third_party/blink/web_tests/virtual/cookie-deprecation-label/DIR_METADATA new file mode 100644 index 0000000..9058063 --- /dev/null +++ b/third_party/blink/web_tests/virtual/cookie-deprecation-label/DIR_METADATA
@@ -0,0 +1,6 @@ +monorail: { + component: "Internals>Network>Cookies" +} +buganizer_public: { + component_id: 1456343 +} \ No newline at end of file
diff --git a/third_party/blink/web_tests/virtual/lcp-multiple-updates-per-element/README.md b/third_party/blink/web_tests/virtual/lcp-multiple-updates-per-element/README.md deleted file mode 100644 index 9bb755b..0000000 --- a/third_party/blink/web_tests/virtual/lcp-multiple-updates-per-element/README.md +++ /dev/null
@@ -1 +0,0 @@ -This directory is used for running web platform tests that require enabling the --enable-features=LCPMultipleUpdatesPerElement flag.
diff --git a/third_party/blink/web_tests/virtual/verify-minimal-resource-request-kill-switch/README.md b/third_party/blink/web_tests/virtual/verify-minimal-resource-request-kill-switch/README.md new file mode 100644 index 0000000..90905a46 --- /dev/null +++ b/third_party/blink/web_tests/virtual/verify-minimal-resource-request-kill-switch/README.md
@@ -0,0 +1,7 @@ +# Test suite that disables MinimimalResourceRequestPrepBeforeCacheLookup + +This virtual suites verifies the kill switch +MinimimalResourceRequestPrepBeforeCacheLookup works. The kill switch is rather +invasive, and easy to regress. + +See bug 359910398.
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt index ba3030d6c..5b02af9 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-dedicated-worker-expected.txt
@@ -1432,6 +1432,7 @@ [Worker] method inspect [Worker] method last [Worker] method map +[Worker] method reduce [Worker] method some [Worker] method subscribe [Worker] method switchMap
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt index 50e6189..ef06e3e 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-expected.txt
@@ -7000,6 +7000,7 @@ method inspect method last method map + method reduce method some method subscribe method switchMap
diff --git a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt index ae0837be..79b08b3 100644 --- a/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt +++ b/third_party/blink/web_tests/webexposed/global-interface-listing-shared-worker-expected.txt
@@ -1301,6 +1301,7 @@ [Worker] method inspect [Worker] method last [Worker] method map +[Worker] method reduce [Worker] method some [Worker] method subscribe [Worker] method switchMap
diff --git a/third_party/boringssl/src b/third_party/boringssl/src index f1b043c..d3c1afd 160000 --- a/third_party/boringssl/src +++ b/third_party/boringssl/src
@@ -1 +1 @@ -Subproject commit f1b043c28352a4e79114324ca2e86df33922e843 +Subproject commit d3c1afdc1b3ca24469c895dff659cff3accb6c56
diff --git a/third_party/chromite b/third_party/chromite index d088a2e..2aa46d5 160000 --- a/third_party/chromite +++ b/third_party/chromite
@@ -1 +1 @@ -Subproject commit d088a2e0aeba09f7c9fda5f6105fc275af13f01c +Subproject commit 2aa46d5583da48a991526b3849ce3993b82c06c8
diff --git a/third_party/closure_compiler/externs/bluetooth_private.js b/third_party/closure_compiler/externs/bluetooth_private.js index f3af112..81269fe 100644 --- a/third_party/closure_compiler/externs/bluetooth_private.js +++ b/third_party/closure_compiler/externs/bluetooth_private.js
@@ -59,6 +59,8 @@ JNI_ENVIRONMENT: 'jniEnvironment', JNI_THREAD_ATTACH: 'jniThreadAttach', WAKELOCK: 'wakelock', + UNEXPECTED_STATE: 'unexpectedState', + SOCKET_ERROR: 'socketError', }; /**
diff --git a/third_party/crossbench b/third_party/crossbench index 4a6a61d..4bac63a 160000 --- a/third_party/crossbench +++ b/third_party/crossbench
@@ -1 +1 @@ -Subproject commit 4a6a61d7a060123c387c21d296b73ffecd9de2a2 +Subproject commit 4bac63a1a8c5c2079ee915f3568802fa96ec591e
diff --git a/third_party/depot_tools b/third_party/depot_tools index 1f6ef16..aaaca28 160000 --- a/third_party/depot_tools +++ b/third_party/depot_tools
@@ -1 +1 @@ -Subproject commit 1f6ef165b726ed7316b8e88666390e90a82e8e50 +Subproject commit aaaca2863c2bf13df8b9256cb53a276c7ebbfc07
diff --git a/third_party/devtools-frontend-internal b/third_party/devtools-frontend-internal index 6f01cd3..2693858 160000 --- a/third_party/devtools-frontend-internal +++ b/third_party/devtools-frontend-internal
@@ -1 +1 @@ -Subproject commit 6f01cd303a3c15410a17512002f66c72e6a8e5e6 +Subproject commit 2693858869047a9bc7ca57362c543793b85f69a8
diff --git a/third_party/devtools-frontend/src b/third_party/devtools-frontend/src index 25ba340..1f7b38e 160000 --- a/third_party/devtools-frontend/src +++ b/third_party/devtools-frontend/src
@@ -1 +1 @@ -Subproject commit 25ba3401dee476c69cb9df7be12fea0b9a9377d4 +Subproject commit 1f7b38eb44bce769dd9c25d9a24fb1c00193fb16
diff --git a/third_party/lit/v3_0/BUILD.gn b/third_party/lit/v3_0/BUILD.gn index f009b5d..125008d 100644 --- a/third_party/lit/v3_0/BUILD.gn +++ b/third_party/lit/v3_0/BUILD.gn
@@ -24,6 +24,7 @@ "//chrome/browser/resources/app_settings:build_ts", "//chrome/browser/resources/browser_switch:build_ts", "//chrome/browser/resources/commerce/product_specifications:build_ts", + "//chrome/browser/resources/downloads:build_ts", "//chrome/browser/resources/feedback:build_ts", "//chrome/browser/resources/internals/user_education:build_ts", "//chrome/browser/resources/intro:build_ts",
diff --git a/third_party/perfetto b/third_party/perfetto index 05564d1..700c45e 160000 --- a/third_party/perfetto +++ b/third_party/perfetto
@@ -1 +1 @@ -Subproject commit 05564d1572f910f8e8e50eba47ef8d7163e4ee0a +Subproject commit 700c45efcea755315945adc001f31b3d1e51c226
diff --git a/third_party/polymer/v3_0/BUILD.gn b/third_party/polymer/v3_0/BUILD.gn index 8b716a9..dffdf173 100644 --- a/third_party/polymer/v3_0/BUILD.gn +++ b/third_party/polymer/v3_0/BUILD.gn
@@ -159,7 +159,6 @@ "//ui/webui/resources/cr_components/certificate_manager:build_ts", "//ui/webui/resources/cr_components/customize_themes:build_ts", "//ui/webui/resources/cr_components/help_bubble:build_ts", - "//ui/webui/resources/cr_components/history_clusters:build_ts", "//ui/webui/resources/cr_components/history_embeddings:build_ts", "//ui/webui/resources/cr_components/searchbox:build_ts", "//ui/webui/resources/cr_elements:build_ts",
diff --git a/third_party/rust/adler2/v2/BUILD.gn b/third_party/rust/adler2/v2/BUILD.gn new file mode 100644 index 0000000..257f2b0 --- /dev/null +++ b/third_party/rust/adler2/v2/BUILD.gn
@@ -0,0 +1,41 @@ +# 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. + +# @generated from third_party/rust/chromium_crates_io/BUILD.gn.hbs by +# tools/crates/gnrt. +# Do not edit! + +import("//build/rust/cargo_crate.gni") + +cargo_crate("lib") { + crate_name = "adler2" + epoch = "2" + crate_type = "rlib" + crate_root = + "//third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/src/lib.rs" + sources = [ + "//third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/src/algo.rs", + "//third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/src/lib.rs", + ] + inputs = [] + + build_native_rust_unit_tests = false + edition = "2021" + cargo_pkg_version = "2.0.0" + cargo_pkg_authors = "Jonas Schievink <jonasschievink@gmail.com>, oyvindln <oyvindln@users.noreply.github.com>" + cargo_pkg_name = "adler2" + cargo_pkg_description = + "A simple clean-room implementation of the Adler-32 checksum" + library_configs -= [ "//build/config/compiler:chromium_code" ] + library_configs += [ "//build/config/compiler:no_chromium_code" ] + executable_configs -= [ "//build/config/compiler:chromium_code" ] + executable_configs += [ "//build/config/compiler:no_chromium_code" ] + proc_macro_configs -= [ "//build/config/compiler:chromium_code" ] + proc_macro_configs += [ "//build/config/compiler:no_chromium_code" ] + + # Only for usage from third-party crates. Add the crate to + # //third_party/rust/chromium_crates_io/Cargo.toml to use + # it from first-party code. + visibility = [ "//third_party/rust/*" ] +}
diff --git a/third_party/rust/adler2/v2/README.chromium b/third_party/rust/adler2/v2/README.chromium new file mode 100644 index 0000000..872b9201 --- /dev/null +++ b/third_party/rust/adler2/v2/README.chromium
@@ -0,0 +1,9 @@ +Name: adler2 +URL: https://crates.io/crates/adler2 +Description: A simple clean-room implementation of the Adler-32 checksum +Version: 2.0.0 +Security Critical: yes +Shipped: yes +License: Apache 2.0 +License File: //third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-APACHE +Revision: 8f1f7897870fae9825a92c578a5adbd02f09830e
diff --git a/third_party/rust/chromium_crates_io/Cargo.lock b/third_party/rust/chromium_crates_io/Cargo.lock index c914951..0e9ed92 100644 --- a/third_party/rust/chromium_crates_io/Cargo.lock +++ b/third_party/rust/chromium_crates_io/Cargo.lock
@@ -8,6 +8,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -222,11 +227,11 @@ [[package]] name = "flate2" -version = "1.0.31" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.8.0", ] [[package]] @@ -318,6 +323,14 @@ ] [[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler2", +] + +[[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -335,7 +348,7 @@ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.7.4", ] [[package]]
diff --git a/third_party/rust/chromium_crates_io/supply-chain/audits.toml b/third_party/rust/chromium_crates_io/supply-chain/audits.toml index bf2a10a6..c84a329 100644 --- a/third_party/rust/chromium_crates_io/supply-chain/audits.toml +++ b/third_party/rust/chromium_crates_io/supply-chain/audits.toml
@@ -76,6 +76,20 @@ can be found at go/image-crate-chromium-security-review. ''' +[[audits.adler2]] +who = "Lukasz Anforowicz <lukasza@chromium.org>" +criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"] +version = "2.0.0" +notes = ''' +This audit has been reviewed in https://crrev.com/c/5811890 + +The crate is fairly easy to read thanks to its small size and rich comments. + +I've grepped for `-i cipher`, `-i crypto`, `\bfs\b`, `\bnet\b`, and +`\bunsafe\b`. There were no hits (except for a comment in `README.md` +and `lib.rs` pointing out "Zero `unsafe`"). +''' + [[audits.aho-corasick]] who = "danakj@chromium.org" criteria = ["safe-to-run", "does-not-implement-crypto"] @@ -885,6 +899,10 @@ criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-2"] delta = "1.0.30 -> 1.0.31" notes = """ +WARNING: This certification is a result of a **partial** audit. The +`any_zlib` code has **not** been audited. See the audit of 1.0.30 for +more details. + Only benign changes: * Comment-only changes in `.rs` files @@ -893,6 +911,22 @@ the previous audit notes for 1.0.30) """ +[[audits.flate2]] +who = "Lukasz Anforowicz <lukasza@chromium.org>" +criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-2"] +delta = "1.0.31 -> 1.0.33" +notes = """ +WARNING: This certification is a result of a **partial** audit. The +`any_zlib` code has **not** been audited. See the audit of 1.0.30 for +more details. + +This delta audit has been reviewed in https://crrev.com/c/5811890 +The delta can be seen at https://diff.rs/flate2/1.0.31/1.0.33 +The delta bumps up `miniz_oxide` dependency to `0.8.0` +The delta also contains some changes to `src/ffi/c.rs` which is *NOT* used by Chromium +and therefore hasn't been covered by this partial audit. +""" + [[audits.font-types]] who = "Lukasz Anforowicz <lukasza@chromium.org>" criteria = ["ub-risk-0", "safe-to-deploy", "does-not-implement-crypto"] @@ -1101,6 +1135,22 @@ can be found at go/image-crate-chromium-security-review. ''' +[[audits.miniz_oxide]] +who = "Lukasz Anforowicz <lukasza@chromium.org>" +criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-0"] +delta = "0.7.4 -> 0.8.0" +notes = ''' +This delta audit has been reviewed in https://crrev.com/c/5811890 + +The delta can be inspected at https://diff.rs/miniz_oxide/0.7.4/0.8.0 +and is fairly small (changes related to `const fn` and to `adler2` +switch). + +I've grepped for `-i cipher`, `-i crypto`, `\bfs\b`, `\bnet\b`, and +`\bunsafe\b`. There were no hits (except for comments in `core.rs` +and in `Readme.md`). +''' + [[audits.nom]] who = "danakj@chromium.org" criteria = ["does-not-implement-crypto", "safe-to-deploy", "ub-risk-1"] @@ -2090,7 +2140,7 @@ [[trusted.libc]] criteria = ["safe-to-deploy", "does-not-implement-crypto", "ub-risk-2"] -user-id = 5820 # the8472 +user-id = 5820 start = "2020-03-17" end = "2025-05-23" notes = """
diff --git a/third_party/rust/chromium_crates_io/supply-chain/config.toml b/third_party/rust/chromium_crates_io/supply-chain/config.toml index 3ae83ce..92fa174 100644 --- a/third_party/rust/chromium_crates_io/supply-chain/config.toml +++ b/third_party/rust/chromium_crates_io/supply-chain/config.toml
@@ -41,6 +41,9 @@ ub-risk-3 = "ub-risk-3" ub-risk-4 = "ub-risk-4" +[policy."adler2:2.0.0"] +criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"] + [policy."adler:1.0.2"] criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"] @@ -113,7 +116,7 @@ [policy."fend-core:1.5.1"] criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"] -[policy."flate2:1.0.31"] +[policy."flate2:1.0.33"] criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"] [policy."font-types:0.6.0"] @@ -158,6 +161,9 @@ [policy."miniz_oxide:0.7.4"] criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"] +[policy."miniz_oxide:0.8.0"] +criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"] + [policy."nom:7.1.3"] criteria = ["crypto-safe", "safe-to-deploy", "ub-risk-2"]
diff --git a/third_party/rust/chromium_crates_io/supply-chain/imports.lock b/third_party/rust/chromium_crates_io/supply-chain/imports.lock index bd74c47..05a86ab 100644 --- a/third_party/rust/chromium_crates_io/supply-chain/imports.lock +++ b/third_party/rust/chromium_crates_io/supply-chain/imports.lock
@@ -2,12 +2,6 @@ # cargo-vet imports lock [[publisher.libc]] -version = "0.2.155" -when = "2024-05-17" -user-id = 5820 -user-login = "the8472" - -[[publisher.libc]] version = "0.2.158" when = "2024-08-19" user-id = 55123 @@ -21,13 +15,6 @@ user-name = "Kenny Kerr" [[publisher.windows-targets]] -version = "0.52.5" -when = "2024-04-12" -user-id = 64539 -user-login = "kennykerr" -user-name = "Kenny Kerr" - -[[publisher.windows-targets]] version = "0.52.6" when = "2024-07-03" user-id = 64539
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.cargo-checksum.json similarity index 100% copy from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/.cargo-checksum.json copy to third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.cargo-checksum.json
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.cargo_vcs_info.json new file mode 100644 index 0000000..9758448 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.cargo_vcs_info.json
@@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "8f1f7897870fae9825a92c578a5adbd02f09830e" + }, + "path_in_vcs": "" +} \ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.github/workflows/ci.yml b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.github/workflows/ci.yml new file mode 100644 index 0000000..cf31894 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.github/workflows/ci.yml
@@ -0,0 +1,81 @@ +name: CI + +on: + push: + branches: + - master + - staging + - trying + pull_request: + branches: + - master + +env: + CARGO_TERM_COLOR: always + RUSTFLAGS: "--deny warnings" + MSRV: 1.31.0 + NO_STD_TARGET: thumbv6m-none-eabi + +jobs: + test: + strategy: + matrix: + rust: + - stable + - nightly + os: + - ubuntu-latest + - macOS-latest + - windows-latest + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ matrix.rust }} + override: true + - name: Build + run: cargo build --all --all-targets + - name: Run tests + run: | + cargo test --all --all-targets + cargo test --all --no-default-features + + no-std: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + target: ${{ env.NO_STD_TARGET }} + - name: Build + run: cargo build --verbose --no-default-features --target ${{ env.NO_STD_TARGET }} + + msrv: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ env.MSRV }} + override: true + - name: Build + run: cargo build --verbose + + lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + override: true + components: rustfmt + - name: Check code formatting + run: cargo fmt -- --check
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.gitignore b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.gitignore new file mode 100644 index 0000000..34676005 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/.gitignore
@@ -0,0 +1,3 @@ +target +Cargo.lock +cliff.toml
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/CHANGELOG.md b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/CHANGELOG.md new file mode 100644 index 0000000..9ddf18b --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/CHANGELOG.md
@@ -0,0 +1,77 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +--- +## [2.0.0](https://github.com/Frommi/miniz_oxide/compare/1.0.2..2.0.0) - 2024-08-04 + +First release of adler2 - fork of adler crate as the original is unmaintained and archived + +##### Changes since last version of Adler: + +### Bug Fixes + +- **(core)** change to rust 2021 edition, update repository info and links, update author info - ([867b115](https://github.com/Frommi/miniz_oxide/commit/867b115bad79bf62098f2acccc81bf53ec5a125d)) - oyvindln +- **(core)** simplify some code and fix benches - ([128fb9c](https://github.com/Frommi/miniz_oxide/commit/128fb9cb6cad5c3a54fb0b6c68549d80b79a1fe0)) - oyvindln + +### Changelog of original adler crate + +--- + +## [1.0.2 - 2021-02-26](https://github.com/jonas-schievink/adler/releases/tag/v1.0.2) + +- Fix doctest on big-endian systems ([#9]). + +[#9]: https://github.com/jonas-schievink/adler/pull/9 + +## [1.0.1 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.1) + +### Fixes + +- Fix documentation on docs.rs. + +## [1.0.0 - 2020-11-08](https://github.com/jonas-schievink/adler/releases/tag/v1.0.0) + +### Fixes + +- Fix `cargo test --no-default-features` ([#5]). + +### Improvements + +- Extended and clarified documentation. +- Added more rustdoc examples. +- Extended CI to test the crate with `--no-default-features`. + +### Breaking Changes + +- `adler32_reader` now takes its generic argument by value instead of as a `&mut`. +- Renamed `adler32_reader` to `adler32`. + +## [0.2.3 - 2020-07-11](https://github.com/jonas-schievink/adler/releases/tag/v0.2.3) + +- Process 4 Bytes at a time, improving performance by up to 50% ([#2]). + +## [0.2.2 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.2) + +- Bump MSRV to 1.31.0. + +## [0.2.1 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.1) + +- Add a few `#[inline]` annotations to small functions. +- Fix CI badge. +- Allow integration into libstd. + +## [0.2.0 - 2020-06-27](https://github.com/jonas-schievink/adler/releases/tag/v0.2.0) + +- Support `#![no_std]` when using `default-features = false`. +- Improve performance by around 7x. +- Support Rust 1.8.0. +- Improve API naming. + +## [0.1.0 - 2020-06-26](https://github.com/jonas-schievink/adler/releases/tag/v0.1.0) + +Initial release. + + +[#2]: https://github.com/jonas-schievink/adler/pull/2 +[#5]: https://github.com/jonas-schievink/adler/pull/5
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/Cargo.toml new file mode 100644 index 0000000..d8610a8 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/Cargo.toml
@@ -0,0 +1,97 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "adler2" +version = "2.0.0" +authors = [ + "Jonas Schievink <jonasschievink@gmail.com>", + "oyvindln <oyvindln@users.noreply.github.com>", +] +build = false +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "A simple clean-room implementation of the Adler-32 checksum" +documentation = "https://docs.rs/adler2/" +readme = "README.md" +keywords = [ + "checksum", + "integrity", + "hash", + "adler32", + "zlib", +] +categories = ["algorithms"] +license = "0BSD OR MIT OR Apache-2.0" +repository = "https://github.com/oyvindln/adler2" + +[package.metadata.docs.rs] +rustdoc-args = ["--cfg=docsrs"] + +[package.metadata.release] +no-dev-version = true +pre-release-commit-message = "Release {{version}}" +tag-message = "{{version}}" + +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +replace = """ +## Unreleased + +No changes. + +## [{{version}} - {{date}}](https://github.com/jonas-schievink/adler/releases/tag/v{{version}}) +""" +search = """ +## Unreleased +""" + +[[package.metadata.release.pre-release-replacements]] +file = "README.md" +replace = 'adler = "{{version}}"' +search = 'adler = "[a-z0-9\\.-]+"' + +[[package.metadata.release.pre-release-replacements]] +file = "src/lib.rs" +replace = "https://docs.rs/adler/{{version}}" +search = 'https://docs.rs/adler/[a-z0-9\.-]+' + +[lib] +name = "adler2" +path = "src/lib.rs" + +[[bench]] +name = "bench" +path = "benches/bench.rs" +harness = false + +[dependencies.compiler_builtins] +version = "0.1.2" +optional = true + +[dependencies.core] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-core" + +[dev-dependencies.criterion] +version = "0.3.2" + +[features] +default = ["std"] +rustc-dep-of-std = [ + "core", + "compiler_builtins", +] +std = []
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/Cargo.toml.orig new file mode 100644 index 0000000..3251882 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/Cargo.toml.orig
@@ -0,0 +1,69 @@ +[package] +name = "adler2" +version = "2.0.0" +authors = ["Jonas Schievink <jonasschievink@gmail.com>", "oyvindln <oyvindln@users.noreply.github.com>"] +description = "A simple clean-room implementation of the Adler-32 checksum" +documentation = "https://docs.rs/adler2/" +repository = "https://github.com/oyvindln/adler2" +keywords = ["checksum", "integrity", "hash", "adler32", "zlib"] +categories = ["algorithms"] +readme = "README.md" +license = "0BSD OR MIT OR Apache-2.0" +edition = "2021" + +[[bench]] +name = "bench" +harness = false + +[dependencies] +# Internal features, only used when building as part of libstd, not part of the +# stable interface of this crate. +core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } +compiler_builtins = { version = '0.1.2', optional = true } + +[dev-dependencies] +criterion = "0.3.2" + +[features] +# Disable default features to enable `#![no_std]` support. +default = ["std"] +std = [] + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +rustc-dep-of-std = ['core', 'compiler_builtins'] + + +[package.metadata.docs.rs] +rustdoc-args = [ "--cfg=docsrs" ] + +# cargo-release configuration +[package.metadata.release] +tag-message = "{{version}}" +no-dev-version = true +pre-release-commit-message = "Release {{version}}" + +# Change the changelog's `Unreleased` section to refer to this release and +# prepend a new `Unreleased` section +[[package.metadata.release.pre-release-replacements]] +file = "CHANGELOG.md" +search = "## Unreleased\n" +replace = """ +## Unreleased + +No changes. + +## [{{version}} - {{date}}](https://github.com/jonas-schievink/adler/releases/tag/v{{version}}) +""" + +# Bump the version inside the example manifest in `README.md` +[[package.metadata.release.pre-release-replacements]] +file = "README.md" +search = 'adler = "[a-z0-9\\.-]+"' +replace = 'adler = "{{version}}"' + +# Bump the version referenced by the `html_root_url` attribute in `lib.rs` +[[package.metadata.release.pre-release-replacements]] +file = "src/lib.rs" +search = "https://docs.rs/adler/[a-z0-9\\.-]+" +replace = "https://docs.rs/adler/{{version}}"
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-0BSD b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-0BSD new file mode 100644 index 0000000..89336aac --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-0BSD
@@ -0,0 +1,12 @@ +Copyright (C) Jonas Schievink <jonasschievink@gmail.com> + +Permission to use, copy, modify, and/or distribute this software for +any purpose with or without fee is hereby granted. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN +AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-APACHE b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-APACHE new file mode 100644 index 0000000..c98d27d --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-APACHE
@@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/LICENSE-2.0 + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + https://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License.
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-MIT b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-MIT new file mode 100644 index 0000000..31aa7938 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/LICENSE-MIT
@@ -0,0 +1,23 @@ +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE.
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/README.md b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/README.md new file mode 100644 index 0000000..25e7571 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/README.md
@@ -0,0 +1,46 @@ +# Adler-32 checksums for Rust + +This is a fork of the adler crate as the [original](https://github.com/jonas-schievink/adler) has been archived and is no longer updated by it's author + +[](https://crates.io/crates/adler) +[](https://docs.rs/adler/) + + +This crate provides a simple implementation of the Adler-32 checksum, used in +the zlib compression format. + +Please refer to the [changelog](CHANGELOG.md) to see what changed in the last +releases. + +## Features + +- Permissively licensed (0BSD) clean-room implementation. +- Zero dependencies. +- Zero `unsafe`. +- Decent performance (3-4 GB/s) (see note). +- Supports `#![no_std]` (with `default-features = false`). + +## Usage + +Add an entry to your `Cargo.toml`: + +```toml +[dependencies] +adler2 = "2.0.0" +``` + +Check the [API Documentation](https://docs.rs/adler/) for how to use the +crate's functionality. + +## Rust version support + +Currently, this crate supports all Rust versions starting at Rust 1.56.0. + +Bumping the Minimum Supported Rust Version (MSRV) is *not* considered a breaking +change, but will not be done without good reasons. The latest 3 stable Rust +versions will always be supported no matter what. + +## Performance + +Due to the way the algorithm works this crate and the fact that it's not possible to use explicit simd in safe rust currently, this crate benefits drastically from being compiled with newer cpu instructions enabled (using e.g ```RUSTFLAGS=-C target-feature'+sse4.1``` or ```-C target-cpu=x86-64-v2```/```-C target-cpu=x86-64-v3``` arguments depending on what cpu support is being targeted.) +Judging by the crate benchmarks, on a Ryzen 5600, compiling with SSE 4.1 (enabled in x86-64-v2 feature level) enabled can give a ~50-150% speedup, enabling the LZCNT instruction (enabled in x86-64-v3 feature level) can give a further ~50% speedup,
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/RELEASE_PROCESS.md b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/RELEASE_PROCESS.md new file mode 100644 index 0000000..71a36734 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/RELEASE_PROCESS.md
@@ -0,0 +1,13 @@ +# What to do to publish a new release + +1. Ensure all notable changes are in the changelog under "Unreleased". + +2. Execute `cargo release <level>` to bump version(s), tag and publish + everything. External subcommand, must be installed with `cargo install + cargo-release`. + + `<level>` can be one of `major|minor|patch`. If this is the first release + (`0.1.0`), use `minor`, since the version starts out as `0.0.0`. + +3. Go to the GitHub releases, edit the just-pushed tag. Copy the release notes + from the changelog.
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/benches/bench.rs b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/benches/bench.rs new file mode 100644 index 0000000..29d87c1 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/benches/bench.rs
@@ -0,0 +1,109 @@ +extern crate adler2; +extern crate criterion; + +use adler2::{adler32_slice, Adler32}; +use criterion::{criterion_group, criterion_main, Criterion, Throughput}; + +fn simple(c: &mut Criterion) { + { + const SIZE: usize = 100; + + let mut group = c.benchmark_group("simple-100b"); + group.throughput(Throughput::Bytes(SIZE as u64)); + group.bench_function("zeroes-100", |bencher| { + bencher.iter(|| { + adler32_slice(&[0; SIZE]); + }); + }); + group.bench_function("ones-100", |bencher| { + bencher.iter(|| { + adler32_slice(&[0xff; SIZE]); + }); + }); + } + + { + const SIZE: usize = 1024; + + let mut group = c.benchmark_group("simple-1k"); + group.throughput(Throughput::Bytes(SIZE as u64)); + + group.bench_function("zeroes-1k", |bencher| { + bencher.iter(|| { + adler32_slice(&[0; SIZE]); + }); + }); + + group.bench_function("ones-1k", |bencher| { + bencher.iter(|| { + adler32_slice(&[0xff; SIZE]); + }); + }); + } + + { + const SIZE: usize = 1024 * 1024; + + let mut group = c.benchmark_group("simple-1m"); + group.throughput(Throughput::Bytes(SIZE as u64)); + group.bench_function("zeroes-1m", |bencher| { + bencher.iter(|| { + adler32_slice(&[0; SIZE]); + }); + }); + + group.bench_function("ones-1m", |bencher| { + bencher.iter(|| { + adler32_slice(&[0xff; SIZE]); + }); + }); + } +} + +fn chunked(c: &mut Criterion) { + const SIZE: usize = 16 * 1024 * 1024; + + let data = vec![0xAB; SIZE]; + + let mut group = c.benchmark_group("chunked-16m"); + group.throughput(Throughput::Bytes(SIZE as u64)); + group.bench_function("5552", |bencher| { + bencher.iter(|| { + let mut h = Adler32::new(); + for chunk in data.chunks(5552) { + h.write_slice(chunk); + } + h.checksum() + }); + }); + group.bench_function("8k", |bencher| { + bencher.iter(|| { + let mut h = Adler32::new(); + for chunk in data.chunks(8 * 1024) { + h.write_slice(chunk); + } + h.checksum() + }); + }); + group.bench_function("64k", |bencher| { + bencher.iter(|| { + let mut h = Adler32::new(); + for chunk in data.chunks(64 * 1024) { + h.write_slice(chunk); + } + h.checksum() + }); + }); + group.bench_function("1m", |bencher| { + bencher.iter(|| { + let mut h = Adler32::new(); + for chunk in data.chunks(1024 * 1024) { + h.write_slice(chunk); + } + h.checksum() + }); + }); +} + +criterion_group!(benches, simple, chunked); +criterion_main!(benches);
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/src/algo.rs b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/src/algo.rs new file mode 100644 index 0000000..14addd8 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/src/algo.rs
@@ -0,0 +1,155 @@ +use crate::Adler32; +use std::ops::{AddAssign, MulAssign, RemAssign}; + +impl Adler32 { + pub(crate) fn compute(&mut self, bytes: &[u8]) { + // The basic algorithm is, for every byte: + // a = (a + byte) % MOD + // b = (b + a) % MOD + // where MOD = 65521. + // + // For efficiency, we can defer the `% MOD` operations as long as neither a nor b overflows: + // - Between calls to `write`, we ensure that a and b are always in range 0..MOD. + // - We use 32-bit arithmetic in this function. + // - Therefore, a and b must not increase by more than 2^32-MOD without performing a `% MOD` + // operation. + // + // According to Wikipedia, b is calculated as follows for non-incremental checksumming: + // b = n×D1 + (n−1)×D2 + (n−2)×D3 + ... + Dn + n*1 (mod 65521) + // Where n is the number of bytes and Di is the i-th Byte. We need to change this to account + // for the previous values of a and b, as well as treat every input Byte as being 255: + // b_inc = n×255 + (n-1)×255 + ... + 255 + n*65520 + // Or in other words: + // b_inc = n*65520 + n(n+1)/2*255 + // The max chunk size is thus the largest value of n so that b_inc <= 2^32-65521. + // 2^32-65521 = n*65520 + n(n+1)/2*255 + // Plugging this into an equation solver since I can't math gives n = 5552.18..., so 5552. + // + // On top of the optimization outlined above, the algorithm can also be parallelized with a + // bit more work: + // + // Note that b is a linear combination of a vector of input bytes (D1, ..., Dn). + // + // If we fix some value k<N and rewrite indices 1, ..., N as + // + // 1_1, 1_2, ..., 1_k, 2_1, ..., 2_k, ..., (N/k)_k, + // + // then we can express a and b in terms of sums of smaller sequences kb and ka: + // + // ka(j) := D1_j + D2_j + ... + D(N/k)_j where j <= k + // kb(j) := (N/k)*D1_j + (N/k-1)*D2_j + ... + D(N/k)_j where j <= k + // + // a = ka(1) + ka(2) + ... + ka(k) + 1 + // b = k*(kb(1) + kb(2) + ... + kb(k)) - 1*ka(2) - ... - (k-1)*ka(k) + N + // + // We use this insight to unroll the main loop and process k=4 bytes at a time. + // The resulting code is highly amenable to SIMD acceleration, although the immediate speedups + // stem from increased pipeline parallelism rather than auto-vectorization. + // + // This technique is described in-depth (here:)[https://software.intel.com/content/www/us/\ + // en/develop/articles/fast-computation-of-fletcher-checksums.html] + + const MOD: u32 = 65521; + const CHUNK_SIZE: usize = 5552 * 4; + + let mut a = u32::from(self.a); + let mut b = u32::from(self.b); + let mut a_vec = U32X4([0; 4]); + let mut b_vec = a_vec; + + let (bytes, remainder) = bytes.split_at(bytes.len() - bytes.len() % 4); + + // iterate over 4 bytes at a time + let chunk_iter = bytes.chunks_exact(CHUNK_SIZE); + let remainder_chunk = chunk_iter.remainder(); + for chunk in chunk_iter { + for byte_vec in chunk.chunks_exact(4) { + let val = U32X4::from(byte_vec); + a_vec += val; + b_vec += a_vec; + } + + b += CHUNK_SIZE as u32 * a; + a_vec %= MOD; + b_vec %= MOD; + b %= MOD; + } + // special-case the final chunk because it may be shorter than the rest + for byte_vec in remainder_chunk.chunks_exact(4) { + let val = U32X4::from(byte_vec); + a_vec += val; + b_vec += a_vec; + } + b += remainder_chunk.len() as u32 * a; + a_vec %= MOD; + b_vec %= MOD; + b %= MOD; + + // combine the sub-sum results into the main sum + b_vec *= 4; + b_vec.0[1] += MOD - a_vec.0[1]; + b_vec.0[2] += (MOD - a_vec.0[2]) * 2; + b_vec.0[3] += (MOD - a_vec.0[3]) * 3; + for &av in a_vec.0.iter() { + a += av; + } + for &bv in b_vec.0.iter() { + b += bv; + } + + // iterate over the remaining few bytes in serial + for &byte in remainder.iter() { + a += u32::from(byte); + b += a; + } + + self.a = (a % MOD) as u16; + self.b = (b % MOD) as u16; + } +} + +#[derive(Copy, Clone)] +struct U32X4([u32; 4]); + +impl U32X4 { + #[inline] + fn from(bytes: &[u8]) -> Self { + U32X4([ + u32::from(bytes[0]), + u32::from(bytes[1]), + u32::from(bytes[2]), + u32::from(bytes[3]), + ]) + } +} + +impl AddAssign<Self> for U32X4 { + #[inline] + fn add_assign(&mut self, other: Self) { + // Implement this in a primitive manner to help out the compiler a bit. + self.0[0] += other.0[0]; + self.0[1] += other.0[1]; + self.0[2] += other.0[2]; + self.0[3] += other.0[3]; + } +} + +impl RemAssign<u32> for U32X4 { + #[inline] + fn rem_assign(&mut self, quotient: u32) { + self.0[0] %= quotient; + self.0[1] %= quotient; + self.0[2] %= quotient; + self.0[3] %= quotient; + } +} + +impl MulAssign<u32> for U32X4 { + #[inline] + fn mul_assign(&mut self, rhs: u32) { + self.0[0] *= rhs; + self.0[1] *= rhs; + self.0[2] *= rhs; + self.0[3] *= rhs; + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/src/lib.rs new file mode 100644 index 0000000..559108a --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/adler2-2.0.0/src/lib.rs
@@ -0,0 +1,287 @@ +//! Adler-32 checksum implementation. +//! +//! This implementation features: +//! +//! - Permissively licensed (0BSD) clean-room implementation. +//! - Zero dependencies. +//! - Zero `unsafe`. +//! - Decent performance (3-4 GB/s). +//! - `#![no_std]` support (with `default-features = false`). + +#![doc(html_root_url = "https://docs.rs/adler2/2.0.0")] +// Deny a few warnings in doctests, since rustdoc `allow`s many warnings by default +#![doc(test(attr(deny(unused_imports, unused_must_use))))] +#![cfg_attr(docsrs, feature(doc_cfg))] +#![warn(missing_debug_implementations)] +#![forbid(unsafe_code)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(not(feature = "std"))] +extern crate core as std; + +mod algo; + +use std::hash::Hasher; + +#[cfg(feature = "std")] +use std::io::{self, BufRead}; + +/// Adler-32 checksum calculator. +/// +/// An instance of this type is equivalent to an Adler-32 checksum: It can be created in the default +/// state via [`new`] (or the provided `Default` impl), or from a precalculated checksum via +/// [`from_checksum`], and the currently stored checksum can be fetched via [`checksum`]. +/// +/// This type also implements `Hasher`, which makes it easy to calculate Adler-32 checksums of any +/// type that implements or derives `Hash`. This also allows using Adler-32 in a `HashMap`, although +/// that is not recommended (while every checksum is a hash function, they are not necessarily a +/// good one). +/// +/// # Examples +/// +/// Basic, piecewise checksum calculation: +/// +/// ``` +/// use adler2::Adler32; +/// +/// let mut adler = Adler32::new(); +/// +/// adler.write_slice(&[0, 1, 2]); +/// adler.write_slice(&[3, 4, 5]); +/// +/// assert_eq!(adler.checksum(), 0x00290010); +/// ``` +/// +/// Using `Hash` to process structures: +/// +/// ``` +/// use std::hash::Hash; +/// use adler2::Adler32; +/// +/// #[derive(Hash)] +/// struct Data { +/// byte: u8, +/// word: u16, +/// big: u64, +/// } +/// +/// let mut adler = Adler32::new(); +/// +/// let data = Data { byte: 0x1F, word: 0xABCD, big: !0 }; +/// data.hash(&mut adler); +/// +/// // hash value depends on architecture endianness +/// if cfg!(target_endian = "little") { +/// assert_eq!(adler.checksum(), 0x33410990); +/// } +/// if cfg!(target_endian = "big") { +/// assert_eq!(adler.checksum(), 0x331F0990); +/// } +/// +/// ``` +/// +/// [`new`]: #method.new +/// [`from_checksum`]: #method.from_checksum +/// [`checksum`]: #method.checksum +#[derive(Debug, Copy, Clone)] +pub struct Adler32 { + a: u16, + b: u16, +} + +impl Adler32 { + /// Creates a new Adler-32 instance with default state. + #[inline] + pub fn new() -> Self { + Self::default() + } + + /// Creates an `Adler32` instance from a precomputed Adler-32 checksum. + /// + /// This allows resuming checksum calculation without having to keep the `Adler32` instance + /// around. + /// + /// # Example + /// + /// ``` + /// # use adler2::Adler32; + /// let parts = [ + /// "rust", + /// "acean", + /// ]; + /// let whole = adler2::adler32_slice(b"rustacean"); + /// + /// let mut sum = Adler32::new(); + /// sum.write_slice(parts[0].as_bytes()); + /// let partial = sum.checksum(); + /// + /// // ...later + /// + /// let mut sum = Adler32::from_checksum(partial); + /// sum.write_slice(parts[1].as_bytes()); + /// assert_eq!(sum.checksum(), whole); + /// ``` + #[inline] + pub const fn from_checksum(sum: u32) -> Self { + Adler32 { + a: sum as u16, + b: (sum >> 16) as u16, + } + } + + /// Returns the calculated checksum at this point in time. + #[inline] + pub fn checksum(&self) -> u32 { + (u32::from(self.b) << 16) | u32::from(self.a) + } + + /// Adds `bytes` to the checksum calculation. + /// + /// If efficiency matters, this should be called with Byte slices that contain at least a few + /// thousand Bytes. + pub fn write_slice(&mut self, bytes: &[u8]) { + self.compute(bytes); + } +} + +impl Default for Adler32 { + #[inline] + fn default() -> Self { + Adler32 { a: 1, b: 0 } + } +} + +impl Hasher for Adler32 { + #[inline] + fn finish(&self) -> u64 { + u64::from(self.checksum()) + } + + fn write(&mut self, bytes: &[u8]) { + self.write_slice(bytes); + } +} + +/// Calculates the Adler-32 checksum of a byte slice. +/// +/// This is a convenience function around the [`Adler32`] type. +/// +/// [`Adler32`]: struct.Adler32.html +pub fn adler32_slice(data: &[u8]) -> u32 { + let mut h = Adler32::new(); + h.write_slice(data); + h.checksum() +} + +/// Calculates the Adler-32 checksum of a `BufRead`'s contents. +/// +/// The passed `BufRead` implementor will be read until it reaches EOF (or until it reports an +/// error). +/// +/// If you only have a `Read` implementor, you can wrap it in `std::io::BufReader` before calling +/// this function. +/// +/// # Errors +/// +/// Any error returned by the reader are bubbled up by this function. +/// +/// # Examples +/// +/// ```no_run +/// # fn run() -> Result<(), Box<dyn std::error::Error>> { +/// use adler2::adler32; +/// +/// use std::fs::File; +/// use std::io::BufReader; +/// +/// let file = File::open("input.txt")?; +/// let mut file = BufReader::new(file); +/// +/// adler32(&mut file)?; +/// # Ok(()) } +/// # fn main() { run().unwrap() } +/// ``` +#[cfg(feature = "std")] +#[cfg_attr(docsrs, doc(cfg(feature = "std")))] +pub fn adler32<R: BufRead>(mut reader: R) -> io::Result<u32> { + let mut h = Adler32::new(); + loop { + let len = { + let buf = reader.fill_buf()?; + if buf.is_empty() { + return Ok(h.checksum()); + } + + h.write_slice(buf); + buf.len() + }; + reader.consume(len); + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn zeroes() { + assert_eq!(adler32_slice(&[]), 1); + assert_eq!(adler32_slice(&[0]), 1 | 1 << 16); + assert_eq!(adler32_slice(&[0, 0]), 1 | 2 << 16); + assert_eq!(adler32_slice(&[0; 100]), 0x00640001); + assert_eq!(adler32_slice(&[0; 1024]), 0x04000001); + assert_eq!(adler32_slice(&[0; 1024 * 1024]), 0x00f00001); + } + + #[test] + fn ones() { + assert_eq!(adler32_slice(&[0xff; 1024]), 0x79a6fc2e); + assert_eq!(adler32_slice(&[0xff; 1024 * 1024]), 0x8e88ef11); + } + + #[test] + fn mixed() { + assert_eq!(adler32_slice(&[1]), 2 | 2 << 16); + assert_eq!(adler32_slice(&[40]), 41 | 41 << 16); + + assert_eq!(adler32_slice(&[0xA5; 1024 * 1024]), 0xd5009ab1); + } + + /// Example calculation from https://en.wikipedia.org/wiki/Adler-32. + #[test] + fn wiki() { + assert_eq!(adler32_slice(b"Wikipedia"), 0x11E60398); + } + + #[test] + fn resume() { + let mut adler = Adler32::new(); + adler.write_slice(&[0xff; 1024]); + let partial = adler.checksum(); + assert_eq!(partial, 0x79a6fc2e); // from above + adler.write_slice(&[0xff; 1024 * 1024 - 1024]); + assert_eq!(adler.checksum(), 0x8e88ef11); // from above + + // Make sure that we can resume computing from the partial checksum via `from_checksum`. + let mut adler = Adler32::from_checksum(partial); + adler.write_slice(&[0xff; 1024 * 1024 - 1024]); + assert_eq!(adler.checksum(), 0x8e88ef11); // from above + } + + #[cfg(feature = "std")] + #[test] + fn bufread() { + use std::io::BufReader; + fn test(data: &[u8], checksum: u32) { + // `BufReader` uses an 8 KB buffer, so this will test buffer refilling. + let mut buf = BufReader::new(data); + let real_sum = adler32(&mut buf).unwrap(); + assert_eq!(checksum, real_sum); + } + + test(&[], 1); + test(&[0; 1024], 0x04000001); + test(&[0; 1024 * 1024], 0x00f00001); + test(&[0xA5; 1024 * 1024], 0xd5009ab1); + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/.cargo_vcs_info.json deleted file mode 100644 index 79bf0a6..0000000 --- a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/.cargo_vcs_info.json +++ /dev/null
@@ -1,6 +0,0 @@ -{ - "git": { - "sha1": "93c81772305a102f1ec846bd12713dd7bf1e3f04" - }, - "path_in_vcs": "" -} \ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/MAINTENANCE.md b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/MAINTENANCE.md deleted file mode 100644 index c032c25..0000000 --- a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/MAINTENANCE.md +++ /dev/null
@@ -1,21 +0,0 @@ -This document explains how to perform the project's maintenance tasks. - -### Creating a new release - -#### Artifacts - -* a tag of the version number -* a new [crate version](https://crates.io/crates/flate2/versions) - -#### Process - -To generate all the artifacts above, one proceeds as follows: - -1. `git checkout -b release-<next-version>` - move to a branch to prepare making changes to the repository. *Changes cannot be made to `main` as it is protected.* -2. Edit `Cargo.toml` to the next package version. -3. `gh pr create` to create a new PR for the current branch and **get it merged**. -4. `cargo publish` to create a new release on `crates.io`. -5. `git tag <next-version>` to remember the commit. -6. `git push --tags` to push the new tag. -7. Go to the newly created release page on GitHub and edit it by pressing the "Generate Release Notes" and the `@` button. Save the release. -
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/.cargo-checksum.json similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/.cargo-checksum.json rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/.cargo-checksum.json
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/.cargo_vcs_info.json new file mode 100644 index 0000000..400c5269 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/.cargo_vcs_info.json
@@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "50852c6138789b255d5b2dfea2abb1a1dda99e99" + }, + "path_in_vcs": "" +} \ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/CHANGELOG.md b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/CHANGELOG.md similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/CHANGELOG.md rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/CHANGELOG.md
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/Cargo.lock b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/Cargo.lock similarity index 85% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/Cargo.lock rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/Cargo.lock index 1327ce7b1..ed1ee99d 100644 --- a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/Cargo.lock +++ b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/Cargo.lock
@@ -3,16 +3,19 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "cc" -version = "1.0.88" +version = "1.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02f341c093d19155a6e41631ce5971aac4e9a868262212153124c15fa22d1cdc" +checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +dependencies = [ + "shlex", +] [[package]] name = "cfg-if" @@ -49,7 +52,7 @@ [[package]] name = "flate2" -version = "1.0.31" +version = "1.0.33" dependencies = [ "cloudflare-zlib-sys", "crc32fast", @@ -80,9 +83,9 @@ [[package]] name = "libz-ng-sys" -version = "1.1.15" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6409efc61b12687963e602df8ecf70e8ddacf95bc6576bcf16e3ac6328083c5" +checksum = "4436751a01da56f1277f323c80d584ffad94a3d14aecd959dd0dff75aa73a438" dependencies = [ "cmake", "libc", @@ -99,9 +102,9 @@ [[package]] name = "libz-sys" -version = "1.1.15" +version = "1.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" +checksum = "d2d16453e800a8cf6dd2fc3eb4bc99b786a9b90c663b8559a5b1a041bf89e472" dependencies = [ "cc", "cmake", @@ -112,11 +115,11 @@ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", ] [[package]] @@ -171,6 +174,12 @@ ] [[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] name = "vcpkg" version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/Cargo.toml similarity index 97% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/Cargo.toml rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/Cargo.toml index bdded41..1970fe9 100644 --- a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/Cargo.toml +++ b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/Cargo.toml
@@ -11,8 +11,9 @@ [package] edition = "2018" +rust-version = "1.56.1" name = "flate2" -version = "1.0.31" +version = "1.0.33" authors = [ "Alex Crichton <alex@alexcrichton.com>", "Josh Triplett <josh@joshtriplett.org>", @@ -172,7 +173,7 @@ version = "1.2.0" [dependencies.libz-ng-sys] -version = "1.1.8" +version = "1.1.16" optional = true [dependencies.libz-rs-sys] @@ -185,12 +186,12 @@ default-features = false [dependencies.libz-sys] -version = "1.1.8" +version = "1.1.20" optional = true default-features = false [dependencies.miniz_oxide] -version = "0.7.1" +version = "0.8.0" features = ["with-alloc"] optional = true default-features = false @@ -237,6 +238,6 @@ ] [target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies.miniz_oxide] -version = "0.7.1" +version = "0.8.0" features = ["with-alloc"] default-features = false
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/Cargo.toml.orig similarity index 85% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/Cargo.toml.orig rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/Cargo.toml.orig index aa205d42..47c7421d 100644 --- a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/Cargo.toml.orig +++ b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/Cargo.toml.orig
@@ -1,10 +1,11 @@ [package] name = "flate2" authors = ["Alex Crichton <alex@alexcrichton.com>", "Josh Triplett <josh@joshtriplett.org>"] -version = "1.0.31" +version = "1.0.33" edition = "2018" license = "MIT OR Apache-2.0" readme = "README.md" +rust-version = "1.56.1" keywords = ["gzip", "deflate", "zlib", "zlib-ng", "encoding"] categories = ["compression", "api-bindings"] repository = "https://github.com/rust-lang/flate2-rs" @@ -18,15 +19,15 @@ exclude = [".*"] [dependencies] -libz-sys = { version = "1.1.8", optional = true, default-features = false } -libz-ng-sys = { version = "1.1.8", optional = true } +libz-sys = { version = "1.1.20", optional = true, default-features = false } +libz-ng-sys = { version = "1.1.16", optional = true } libz-rs-sys = { version = "0.2.1", optional = true, default-features = false, features = ["std", "rust-allocator"] } cloudflare-zlib-sys = { version = "0.3.0", optional = true } -miniz_oxide = { version = "0.7.1", optional = true, default-features = false, features = ["with-alloc"] } +miniz_oxide = { version = "0.8.0", optional = true, default-features = false, features = ["with-alloc"] } crc32fast = "1.2.0" [target.'cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))'.dependencies] -miniz_oxide = { version = "0.7.1", default-features = false, features = ["with-alloc"] } +miniz_oxide = { version = "0.8.0", default-features = false, features = ["with-alloc"] } [dev-dependencies] rand = "0.8"
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/LICENSE-APACHE b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/LICENSE-APACHE similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/LICENSE-APACHE rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/LICENSE-APACHE
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/LICENSE-MIT b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/LICENSE-MIT similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/LICENSE-MIT rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/LICENSE-MIT
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/MAINTENANCE.md b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/MAINTENANCE.md new file mode 100644 index 0000000..25c35f4 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/MAINTENANCE.md
@@ -0,0 +1,28 @@ +This document explains how to perform the project's maintenance tasks. + +### Repository Configuration + +Some repository settings, including branch protection and required approvals, are managed in the +[Rust team repo](https://github.com/rust-lang/team/blob/master/repos/rust-lang/flate2-rs.toml). +See the [repository schema](https://github.com/rust-lang/team/blob/aaa8039a2420a07cab9bbaca3885b3ad95a256a7/docs/toml-schema.md?plain=1#L248) +for supported directives. + +### Creating a new release + +#### Artifacts + +* a tag of the version number +* a new [crate version](https://crates.io/crates/flate2/versions) + +#### Process + +To generate all the artifacts above, one proceeds as follows: + +1. `git checkout -b release-<next-version>` - create a branch to make changes to the repository. *Changes cannot be made to `main` as it is protected.* +2. Edit `Cargo.toml` to update the package version to `<next-version>`. +3. Create a new PR for the branch (e.g. using `gh pr create`) and **get it approved and merged**. +4. Pull the `main` branch and ensure that you are at the merged commit. +4. `cargo publish` to create a new release on `crates.io`. +5. `git tag <next-version>` to remember the commit. +6. `git push --tags` to push the new tag. +7. Go to the newly created release page on GitHub and edit it by pressing the "Generate Release Notes" and the `@` button. Save the release.
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/README.md b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/README.md similarity index 82% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/README.md rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/README.md index 23ce043d..6536593 100644 --- a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/README.md +++ b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/README.md
@@ -23,9 +23,18 @@ ## MSRV (Minimum Supported Rust Version) Policy -This crate supports the current stable and the last stable for the latest version. -For example, if the current stable is 1.64, this crate supports 1.64 and 1.63. -Older stables may work, but we don't guarantee these will continue to work. +This crate supports the current and previous stable versions of the Rust compiler. +For example, if the current stable is 1.80, this crate supports 1.80 and 1.79. + +Other compiler versions may work, but failures may not be treated as a `flate2` bug. + +The `Cargo.toml` file specifies a `rust-version` for which builds of the current version +passed at some point. This value is indicative only, and may change at any time. + +The `rust-version` is a best-effort measured value and is different to the MSRV. The +`rust-version` can be incremented by a PR in order to pass tests, as long as the MSRV +continues to hold. When the `rust-version` increases, the next release should be a minor +version, to allow any affected users to pin to a previous minor version. ## Compression
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/compress_file.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/compress_file.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/compress_file.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/compress_file.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/decompress_file.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/decompress_file.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/decompress_file.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/decompress_file.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflatedecoder-bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflatedecoder-bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflatedecoder-bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflatedecoder-bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflatedecoder-read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflatedecoder-read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflatedecoder-read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflatedecoder-read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflatedecoder-write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflatedecoder-write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflatedecoder-write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflatedecoder-write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflateencoder-bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflateencoder-bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflateencoder-bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflateencoder-bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflateencoder-read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflateencoder-read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflateencoder-read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflateencoder-read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflateencoder-write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflateencoder-write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/deflateencoder-write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/deflateencoder-write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzbuilder.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzbuilder.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzbuilder.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzbuilder.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzdecoder-bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzdecoder-bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzdecoder-bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzdecoder-bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzdecoder-read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzdecoder-read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzdecoder-read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzdecoder-read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzdecoder-write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzdecoder-write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzdecoder-write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzdecoder-write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzencoder-bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzencoder-bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzencoder-bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzencoder-bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzencoder-read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzencoder-read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzencoder-read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzencoder-read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzencoder-write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzencoder-write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzencoder-write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzencoder-write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzmultidecoder-bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzmultidecoder-bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzmultidecoder-bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzmultidecoder-bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzmultidecoder-read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzmultidecoder-read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/gzmultidecoder-read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/gzmultidecoder-read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/hello_world.txt b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/hello_world.txt similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/hello_world.txt rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/hello_world.txt
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/hello_world.txt.gz b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/hello_world.txt.gz similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/hello_world.txt.gz rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/hello_world.txt.gz Binary files differ
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibdecoder-bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibdecoder-bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibdecoder-bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibdecoder-bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibdecoder-read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibdecoder-read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibdecoder-read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibdecoder-read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibdecoder-write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibdecoder-write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibdecoder-write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibdecoder-write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibencoder-bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibencoder-bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibencoder-bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibencoder-bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibencoder-read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibencoder-read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibencoder-read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibencoder-read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibencoder-write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibencoder-write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/examples/zlibencoder-write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/examples/zlibencoder-write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/bufreader.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/bufreader.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/bufreader.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/bufreader.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/crc.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/crc.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/crc.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/crc.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/mod.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/mod.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/mod.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/mod.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/c.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/c.rs similarity index 98% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/c.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/c.rs index 0c3e4e8..867f2f9 100644 --- a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/c.rs +++ b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/c.rs
@@ -263,7 +263,9 @@ (*raw).avail_out = 0; match rc { - MZ_DATA_ERROR | MZ_STREAM_ERROR => mem::decompress_failed(self.inner.msg()), + MZ_DATA_ERROR | MZ_STREAM_ERROR | MZ_MEM_ERROR => { + mem::decompress_failed(self.inner.msg()) + } MZ_OK => Ok(Status::Ok), MZ_BUF_ERROR => Ok(Status::BufError), MZ_STREAM_END => Ok(Status::StreamEnd), @@ -431,6 +433,7 @@ pub use libz::Z_DEFLATED as MZ_DEFLATED; pub use libz::Z_FINISH as MZ_FINISH; pub use libz::Z_FULL_FLUSH as MZ_FULL_FLUSH; + pub use libz::Z_MEM_ERROR as MZ_MEM_ERROR; pub use libz::Z_NEED_DICT as MZ_NEED_DICT; pub use libz::Z_NO_FLUSH as MZ_NO_FLUSH; pub use libz::Z_OK as MZ_OK;
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/mod.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/mod.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/mod.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/mod.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/rust.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/rust.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/rust.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/rust.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/mod.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/mod.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/mod.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/mod.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/lib.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/lib.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/lib.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/mem.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/mem.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/mem.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/mem.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zio.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zio.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zio.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zio.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/bufread.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/bufread.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/bufread.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/bufread.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/mod.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/mod.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/mod.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/mod.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/corrupt-gz-file.bin b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/corrupt-gz-file.bin similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/corrupt-gz-file.bin rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/corrupt-gz-file.bin Binary files differ
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/early-flush.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/early-flush.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/early-flush.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/early-flush.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/empty-read.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/empty-read.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/empty-read.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/empty-read.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/good-file.gz b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/good-file.gz similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/good-file.gz rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/good-file.gz Binary files differ
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/good-file.txt b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/good-file.txt similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/good-file.txt rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/good-file.txt
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/gunzip.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/gunzip.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/gunzip.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/gunzip.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/multi.gz b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/multi.gz similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/multi.gz rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/multi.gz Binary files differ
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/multi.txt b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/multi.txt similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/multi.txt rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/multi.txt
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/zero-write.rs b/third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/zero-write.rs similarity index 100% rename from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/tests/zero-write.rs rename to third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/tests/zero-write.rs
diff --git a/third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/.cargo-checksum.json b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/.cargo-checksum.json similarity index 100% copy from third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/.cargo-checksum.json copy to third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/.cargo-checksum.json
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/.cargo_vcs_info.json b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/.cargo_vcs_info.json new file mode 100644 index 0000000..1defcb3 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/.cargo_vcs_info.json
@@ -0,0 +1,6 @@ +{ + "git": { + "sha1": "58cf901875b2a5b3c9eeb844bd534f6cee54f847" + }, + "path_in_vcs": "miniz_oxide" +} \ No newline at end of file
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/Cargo.toml b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/Cargo.toml new file mode 100644 index 0000000..5ee8b8c --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/Cargo.toml
@@ -0,0 +1,86 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2021" +name = "miniz_oxide" +version = "0.8.0" +authors = [ + "Frommi <daniil.liferenko@gmail.com>", + "oyvindln <oyvindln@users.noreply.github.com>", +] +build = false +exclude = [ + "benches/*", + "tests/*", +] +autobins = false +autoexamples = false +autotests = false +autobenches = false +description = "DEFLATE compression and decompression library rewritten in Rust based on miniz" +homepage = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" +documentation = "https://docs.rs/miniz_oxide" +readme = "Readme.md" +keywords = [ + "zlib", + "miniz", + "deflate", + "encoding", +] +categories = ["compression"] +license = "MIT OR Zlib OR Apache-2.0" +repository = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" +resolver = "1" + +[lib] +name = "miniz_oxide" +path = "src/lib.rs" + +[dependencies.adler2] +version = "2.0" +default-features = false + +[dependencies.alloc] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-alloc" + +[dependencies.compiler_builtins] +version = "0.1.2" +optional = true + +[dependencies.core] +version = "1.0.0" +optional = true +package = "rustc-std-workspace-core" + +[dependencies.simd-adler32] +version = "0.3.3" +optional = true +default-features = false + +[features] +default = ["with-alloc"] +rustc-dep-of-std = [ + "core", + "alloc", + "compiler_builtins", + "adler2/rustc-dep-of-std", +] +simd = ["simd-adler32"] +std = [] +with-alloc = [] + +[lints.rust.unexpected_cfgs] +level = "warn" +priority = 0 +check-cfg = ["cfg(fuzzing)"]
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/Cargo.toml.orig b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/Cargo.toml.orig new file mode 100644 index 0000000..dab4e33 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/Cargo.toml.orig
@@ -0,0 +1,43 @@ +[package] +name = "miniz_oxide" +authors = ["Frommi <daniil.liferenko@gmail.com>", "oyvindln <oyvindln@users.noreply.github.com>"] +version = "0.8.0" +license = "MIT OR Zlib OR Apache-2.0" +readme = "Readme.md" +keywords = ["zlib", "miniz", "deflate", "encoding"] +categories = ["compression"] +repository = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" +homepage = "https://github.com/Frommi/miniz_oxide/tree/master/miniz_oxide" +documentation = "https://docs.rs/miniz_oxide" +description = "DEFLATE compression and decompression library rewritten in Rust based on miniz" +edition = "2021" +exclude = ["benches/*", "tests/*"] + +[lib] +name = "miniz_oxide" + +[dependencies] +adler2 = { version = "2.0", default-features = false} +simd-adler32 = { version = "0.3.3", default-features = false, optional = true } + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' } +alloc = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-alloc' } +compiler_builtins = { version = '0.1.2', optional = true } + +[features] +default = ["with-alloc"] +with-alloc = [] +std = [] + +# Internal feature, only used when building as part of libstd, not part of the +# stable interface of this crate. +rustc-dep-of-std = ['core', 'alloc', 'compiler_builtins', 'adler2/rustc-dep-of-std'] + +simd = ['simd-adler32'] + +# Disable unexpected cfg name warning from to !cfg(fuzzing) - compiler is not aware of the fuzzing feature since it comes from the environment +# see https://github.com/rust-fuzz/cargo-fuzz/issues/372 +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(fuzzing)'] }
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE new file mode 100644 index 0000000..64c5379 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE
@@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Frommi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-APACHE.md b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-APACHE.md new file mode 100644 index 0000000..f433b1a5 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-APACHE.md
@@ -0,0 +1,177 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-MIT.md b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-MIT.md new file mode 100644 index 0000000..64c5379 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-MIT.md
@@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Frommi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE.
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-ZLIB.md b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-ZLIB.md new file mode 100644 index 0000000..7f513d1 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-ZLIB.md
@@ -0,0 +1,11 @@ +Copyright (c) 2020 Frommi + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution.
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/Readme.md b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/Readme.md new file mode 100644 index 0000000..6c177b0 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/Readme.md
@@ -0,0 +1,44 @@ +# miniz_oxide + +A fully safe, pure rust replacement for the [miniz](https://github.com/richgel999/miniz) DEFLATE/zlib encoder/decoder. +The main intention of this crate is to be used as a back-end for the [flate2](https://github.com/alexcrichton/flate2-rs), but it can also be used on its own. Using flate2 with the ```rust_backend``` feature provides an easy to use streaming API for miniz_oxide. + +The library is fully [no_std](https://docs.rust-embedded.org/book/intro/no-std.html). By default, the `with-alloc` feature is enabled, which requires the use of the `alloc` and `collection` crates as it allocates memory. + +The `std` feature additionally turns on things only available if `no_std` is not used. Currently this only means implementing [Error](https://doc.rust-lang.org/stable/std/error/trait.Error.html) for the `DecompressError` error struct returned by the simple decompression functions if enabled together with `with-alloc`. + +Using the library with `default-features = false` removes the dependency on `alloc` +and `collection` crates, making it suitable for systems without an allocator. +Running without allocation reduces crate functionality: + +- The `deflate` module is removed completely +- Some `inflate` functions which return a `Vec` are removed + +miniz_oxide 0.5.x and 0.6.x Requires at least rust 1.40.0 0.3.x requires at least rust 0.36.0. + +miniz_oxide features no use of unsafe code. + +miniz_oxide can optionally be made to use a simd-accelerated version of adler32 via the [simd-adler32](https://crates.io/crates/simd-adler32) crate by enabling the 'simd' feature. This is not enabled by default as due to the use of simd intrinsics, the simd-adler32 has to use unsafe. The default setup uses the [adler](https://crates.io/crates/adler) crate which features no unsafe code. + +## Usage +Simple compression/decompression: +```rust + +use miniz_oxide::deflate::compress_to_vec; +use miniz_oxide::inflate::decompress_to_vec; + +fn roundtrip(data: &[u8]) { + // Compress the input + let compressed = compress_to_vec(data, 6); + // Decompress the compressed input and limit max output size to avoid going out of memory on large/malformed input. + let decompressed = decompress_to_vec_with_limit(compressed.as_slice(), 60000).expect("Failed to decompress!"); + // Check roundtrip succeeded + assert_eq!(data, decompressed); +} + +fn main() { + roundtrip("Hello, world!".as_bytes()); +} + +``` +These simple functions will do everything in one go and are thus not recommended for use cases outside of prototyping/testing as real world data can have any size and thus result in very large memory allocations for the output Vector. Consider using miniz_oxide via [flate2](https://github.com/alexcrichton/flate2-rs) which makes it easy to do streaming (de)compression or the low-level streaming functions instead.
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/buffer.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/buffer.rs new file mode 100644 index 0000000..f246c07 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/buffer.rs
@@ -0,0 +1,58 @@ +//! Buffer wrappers implementing default so we can allocate the buffers with `Box::default()` +//! to avoid stack copies. Box::new() doesn't at the moment, and using a vec means we would lose +//! static length info. + +use crate::deflate::core::{LZ_DICT_SIZE, MAX_MATCH_LEN}; + +/// Size of the buffer of lz77 encoded data. +pub const LZ_CODE_BUF_SIZE: usize = 64 * 1024; +/// Size of the output buffer. +pub const OUT_BUF_SIZE: usize = (LZ_CODE_BUF_SIZE * 13) / 10; +pub const LZ_DICT_FULL_SIZE: usize = LZ_DICT_SIZE + MAX_MATCH_LEN - 1 + 1; + +/// Size of hash values in the hash chains. +pub const LZ_HASH_BITS: i32 = 15; +/// How many bits to shift when updating the current hash value. +pub const LZ_HASH_SHIFT: i32 = (LZ_HASH_BITS + 2) / 3; +/// Size of the chained hash tables. +pub const LZ_HASH_SIZE: usize = 1 << LZ_HASH_BITS; + +#[inline] +pub fn update_hash(current_hash: u16, byte: u8) -> u16 { + ((current_hash << LZ_HASH_SHIFT) ^ u16::from(byte)) & (LZ_HASH_SIZE as u16 - 1) +} + +pub struct HashBuffers { + pub dict: [u8; LZ_DICT_FULL_SIZE], + pub next: [u16; LZ_DICT_SIZE], + pub hash: [u16; LZ_DICT_SIZE], +} + +impl HashBuffers { + #[inline] + pub fn reset(&mut self) { + *self = HashBuffers::default(); + } +} + +impl Default for HashBuffers { + fn default() -> HashBuffers { + HashBuffers { + dict: [0; LZ_DICT_FULL_SIZE], + next: [0; LZ_DICT_SIZE], + hash: [0; LZ_DICT_SIZE], + } + } +} + +pub struct LocalBuf { + pub b: [u8; OUT_BUF_SIZE], +} + +impl Default for LocalBuf { + fn default() -> LocalBuf { + LocalBuf { + b: [0; OUT_BUF_SIZE], + } + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/core.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/core.rs new file mode 100644 index 0000000..3e822a2 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/core.rs
@@ -0,0 +1,2469 @@ +//! Streaming compression functionality. + +use alloc::boxed::Box; +use core::convert::TryInto; +use core::{cmp, mem}; + +use super::super::*; +use super::deflate_flags::*; +use super::CompressionLevel; +use crate::deflate::buffer::{ + update_hash, HashBuffers, LocalBuf, LZ_CODE_BUF_SIZE, LZ_DICT_FULL_SIZE, LZ_HASH_BITS, + LZ_HASH_SHIFT, LZ_HASH_SIZE, OUT_BUF_SIZE, +}; +use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER, MZ_ADLER32_INIT}; +use crate::DataFormat; + +// Currently not bubbled up outside this module, so can fill in with more +// context eventually if needed. +type Result<T, E = Error> = core::result::Result<T, E>; +struct Error {} + +const MAX_PROBES_MASK: i32 = 0xFFF; + +const MAX_SUPPORTED_HUFF_CODESIZE: usize = 32; + +/// Length code for length values. +#[rustfmt::skip] +const LEN_SYM: [u16; 256] = [ + 257, 258, 259, 260, 261, 262, 263, 264, 265, 265, 266, 266, 267, 267, 268, 268, + 269, 269, 269, 269, 270, 270, 270, 270, 271, 271, 271, 271, 272, 272, 272, 272, + 273, 273, 273, 273, 273, 273, 273, 273, 274, 274, 274, 274, 274, 274, 274, 274, + 275, 275, 275, 275, 275, 275, 275, 275, 276, 276, 276, 276, 276, 276, 276, 276, + 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, 277, + 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, 278, + 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, 279, + 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, 280, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, 281, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, 282, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, 283, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, + 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 284, 285 +]; + +/// Number of extra bits for length values. +#[rustfmt::skip] +const LEN_EXTRA: [u8; 256] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 0 +]; + +/// Distance codes for distances smaller than 512. +#[rustfmt::skip] +const SMALL_DIST_SYM: [u8; 512] = [ + 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, + 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, + 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, 14, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, + 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17, 17 +]; + +/// Number of extra bits for distances smaller than 512. +#[rustfmt::skip] +const SMALL_DIST_EXTRA: [u8; 512] = [ + 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 +]; + +/// Base values to calculate distances above 512. +#[rustfmt::skip] +const LARGE_DIST_SYM: [u8; 128] = [ + 0, 0, 18, 19, 20, 20, 21, 21, 22, 22, 22, 22, 23, 23, 23, 23, + 24, 24, 24, 24, 24, 24, 24, 24, 25, 25, 25, 25, 25, 25, 25, 25, + 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, 26, + 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, 27, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, + 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 +]; + +/// Number of extra bits distances above 512. +#[rustfmt::skip] +const LARGE_DIST_EXTRA: [u8; 128] = [ + 0, 0, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, + 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, + 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13, 13 +]; + +#[rustfmt::skip] +const BITMASKS: [u32; 17] = [ + 0x0000, 0x0001, 0x0003, 0x0007, 0x000F, 0x001F, 0x003F, 0x007F, 0x00FF, + 0x01FF, 0x03FF, 0x07FF, 0x0FFF, 0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF +]; + +/// The maximum number of checks for matches in the hash table the compressor will make for each +/// compression level. +const NUM_PROBES: [u32; 11] = [0, 1, 6, 32, 16, 32, 128, 256, 512, 768, 1500]; + +#[derive(Copy, Clone)] +struct SymFreq { + key: u16, + sym_index: u16, +} + +pub mod deflate_flags { + /// Whether to use a zlib wrapper. + pub const TDEFL_WRITE_ZLIB_HEADER: u32 = 0x0000_1000; + /// Should we compute the adler32 checksum. + pub const TDEFL_COMPUTE_ADLER32: u32 = 0x0000_2000; + /// Should we use greedy parsing (as opposed to lazy parsing where look ahead one or more + /// bytes to check for better matches.) + pub const TDEFL_GREEDY_PARSING_FLAG: u32 = 0x0000_4000; + /// Used in miniz to skip zero-initializing hash and dict. We don't do this here, so + /// this flag is ignored. + pub const TDEFL_NONDETERMINISTIC_PARSING_FLAG: u32 = 0x0000_8000; + /// Only look for matches with a distance of 0. + pub const TDEFL_RLE_MATCHES: u32 = 0x0001_0000; + /// Only use matches that are at least 6 bytes long. + pub const TDEFL_FILTER_MATCHES: u32 = 0x0002_0000; + /// Force the compressor to only output static blocks. (Blocks using the default huffman codes + /// specified in the deflate specification.) + pub const TDEFL_FORCE_ALL_STATIC_BLOCKS: u32 = 0x0004_0000; + /// Force the compressor to only output raw/uncompressed blocks. + pub const TDEFL_FORCE_ALL_RAW_BLOCKS: u32 = 0x0008_0000; +} + +/// Strategy setting for compression. +/// +/// The non-default settings offer some special-case compression variants. +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum CompressionStrategy { + /// Don't use any of the special strategies. + Default = 0, + /// Only use matches that are at least 5 bytes long. + Filtered = 1, + /// Don't look for matches, only huffman encode the literals. + HuffmanOnly = 2, + /// Only look for matches with a distance of 1, i.e do run-length encoding only. + RLE = 3, + /// Only use static/fixed blocks. (Blocks using the default huffman codes + /// specified in the deflate specification.) + Fixed = 4, +} + +/// A list of deflate flush types. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum TDEFLFlush { + /// Normal operation. + /// + /// Compress as much as there is space for, and then return waiting for more input. + None = 0, + + /// Try to flush all the current data and output an empty raw block. + Sync = 2, + + /// Same as [`Sync`][Self::Sync], but reset the dictionary so that the following data does not + /// depend on previous data. + Full = 3, + + /// Try to flush everything and end the deflate stream. + /// + /// On success this will yield a [`TDEFLStatus::Done`] return status. + Finish = 4, +} + +impl From<MZFlush> for TDEFLFlush { + fn from(flush: MZFlush) -> Self { + match flush { + MZFlush::None => TDEFLFlush::None, + MZFlush::Sync => TDEFLFlush::Sync, + MZFlush::Full => TDEFLFlush::Full, + MZFlush::Finish => TDEFLFlush::Finish, + _ => TDEFLFlush::None, // TODO: ??? What to do ??? + } + } +} + +impl TDEFLFlush { + pub const fn new(flush: i32) -> Result<Self, MZError> { + match flush { + 0 => Ok(TDEFLFlush::None), + 2 => Ok(TDEFLFlush::Sync), + 3 => Ok(TDEFLFlush::Full), + 4 => Ok(TDEFLFlush::Finish), + _ => Err(MZError::Param), + } + } +} + +/// Return status of compression. +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum TDEFLStatus { + /// Usage error. + /// + /// This indicates that either the [`CompressorOxide`] experienced a previous error, or the + /// stream has already been [`TDEFLFlush::Finish`]'d. + BadParam = -2, + + /// Error putting data into output buffer. + /// + /// This usually indicates a too-small buffer. + PutBufFailed = -1, + + /// Compression succeeded normally. + Okay = 0, + + /// Compression succeeded and the deflate stream was ended. + /// + /// This is the result of calling compression with [`TDEFLFlush::Finish`]. + Done = 1, +} + +const MAX_HUFF_SYMBOLS: usize = 288; +/// Size of hash chain for fast compression mode. +const LEVEL1_HASH_SIZE_MASK: u32 = 4095; +/// The number of huffman tables used by the compressor. +/// Literal/length, Distances and Length of the huffman codes for the other two tables. +const MAX_HUFF_TABLES: usize = 3; +/// Literal/length codes +const MAX_HUFF_SYMBOLS_0: usize = 288; +/// Distance codes. +const MAX_HUFF_SYMBOLS_1: usize = 32; +/// Huffman length values. +const MAX_HUFF_SYMBOLS_2: usize = 19; +/// Size of the chained hash table. +pub(crate) const LZ_DICT_SIZE: usize = 32_768; +/// Mask used when stepping through the hash chains. +const LZ_DICT_SIZE_MASK: usize = (LZ_DICT_SIZE as u32 - 1) as usize; +/// The minimum length of a match. +const MIN_MATCH_LEN: u8 = 3; +/// The maximum length of a match. +pub(crate) const MAX_MATCH_LEN: usize = 258; + +const DEFAULT_FLAGS: u32 = NUM_PROBES[4] | TDEFL_WRITE_ZLIB_HEADER; + +mod zlib { + const DEFAULT_CM: u8 = 8; + const DEFAULT_CINFO: u8 = 7 << 4; + const _DEFAULT_FDICT: u8 = 0; + const DEFAULT_CMF: u8 = DEFAULT_CM | DEFAULT_CINFO; + /// The 16-bit value consisting of CMF and FLG must be divisible by this to be valid. + const FCHECK_DIVISOR: u8 = 31; + + /// Generate FCHECK from CMF and FLG (without FCKECH )so that they are correct according to the + /// specification, i.e (CMF*256 + FCHK) % 31 = 0. + /// Returns flg with the FCHKECK bits added (any existing FCHECK bits are ignored). + fn add_fcheck(cmf: u8, flg: u8) -> u8 { + let rem = ((usize::from(cmf) * 256) + usize::from(flg)) % usize::from(FCHECK_DIVISOR); + + // Clear existing FCHECK if any + let flg = flg & 0b11100000; + + // Casting is safe as rem can't overflow since it is a value mod 31 + // We can simply add the value to flg as (31 - rem) will never be above 2^5 + flg + (FCHECK_DIVISOR - rem as u8) + } + + const fn zlib_level_from_flags(flags: u32) -> u8 { + use super::NUM_PROBES; + + let num_probes = flags & (super::MAX_PROBES_MASK as u32); + if flags & super::TDEFL_GREEDY_PARSING_FLAG != 0 { + if num_probes <= 1 { + 0 + } else { + 1 + } + } else if num_probes >= NUM_PROBES[9] { + 3 + } else { + 2 + } + } + + /// Get the zlib header for the level using the default window size and no + /// dictionary. + fn header_from_level(level: u8) -> [u8; 2] { + let cmf = DEFAULT_CMF; + [cmf, add_fcheck(cmf, level << 6)] + } + + /// Create a zlib header from the given compression flags. + /// Only level is considered. + pub fn header_from_flags(flags: u32) -> [u8; 2] { + let level = zlib_level_from_flags(flags); + header_from_level(level) + } + + #[cfg(test)] + mod test { + #[test] + fn zlib() { + use super::super::*; + use super::*; + + let test_level = |level, expected| { + let flags = create_comp_flags_from_zip_params( + level, + MZ_DEFAULT_WINDOW_BITS, + CompressionStrategy::Default as i32, + ); + assert_eq!(zlib_level_from_flags(flags), expected); + }; + + assert_eq!(zlib_level_from_flags(DEFAULT_FLAGS), 2); + test_level(0, 0); + test_level(1, 0); + test_level(2, 1); + test_level(3, 1); + for i in 4..=8 { + test_level(i, 2) + } + test_level(9, 3); + test_level(10, 3); + } + + #[test] + fn test_header() { + let header = super::header_from_level(3); + assert_eq!( + ((usize::from(header[0]) * 256) + usize::from(header[1])) % 31, + 0 + ); + } + } +} + +fn memset<T: Copy>(slice: &mut [T], val: T) { + for x in slice { + *x = val + } +} + +#[cfg(test)] +#[inline] +fn write_u16_le(val: u16, slice: &mut [u8], pos: usize) { + slice[pos] = val as u8; + slice[pos + 1] = (val >> 8) as u8; +} + +// Read the two bytes starting at pos and interpret them as an u16. +#[inline] +const fn read_u16_le(slice: &[u8], pos: usize) -> u16 { + // The compiler is smart enough to optimize this into an unaligned load. + slice[pos] as u16 | ((slice[pos + 1] as u16) << 8) +} + +/// Main compression struct. +pub struct CompressorOxide { + lz: LZOxide, + params: ParamsOxide, + /// Put HuffmanOxide on the heap with default trick to avoid + /// excessive stack copies. + huff: Box<HuffmanOxide>, + dict: DictOxide, +} + +impl CompressorOxide { + /// Create a new `CompressorOxide` with the given flags. + /// + /// # Notes + /// This function may be changed to take different parameters in the future. + pub fn new(flags: u32) -> Self { + CompressorOxide { + lz: LZOxide::new(), + params: ParamsOxide::new(flags), + huff: Box::default(), + dict: DictOxide::new(flags), + } + } + + /// Get the adler32 checksum of the currently encoded data. + pub const fn adler32(&self) -> u32 { + self.params.adler32 + } + + /// Get the return status of the previous [`compress`](fn.compress.html) + /// call with this compressor. + pub const fn prev_return_status(&self) -> TDEFLStatus { + self.params.prev_return_status + } + + /// Get the raw compressor flags. + /// + /// # Notes + /// This function may be deprecated or changed in the future to use more rust-style flags. + pub const fn flags(&self) -> i32 { + self.params.flags as i32 + } + + /// Returns whether the compressor is wrapping the data in a zlib format or not. + pub const fn data_format(&self) -> DataFormat { + if (self.params.flags & TDEFL_WRITE_ZLIB_HEADER) != 0 { + DataFormat::Zlib + } else { + DataFormat::Raw + } + } + + /// Reset the state of the compressor, keeping the same parameters. + /// + /// This avoids re-allocating data. + pub fn reset(&mut self) { + // LZ buf and huffman has no settings or dynamic memory + // that needs to be saved, so we simply replace them. + self.lz = LZOxide::new(); + self.params.reset(); + *self.huff = HuffmanOxide::default(); + self.dict.reset(); + } + + /// Set the compression level of the compressor. + /// + /// Using this to change level after compression has started is supported. + /// # Notes + /// The compression strategy will be reset to the default one when this is called. + pub fn set_compression_level(&mut self, level: CompressionLevel) { + let format = self.data_format(); + self.set_format_and_level(format, level as u8); + } + + /// Set the compression level of the compressor using an integer value. + /// + /// Using this to change level after compression has started is supported. + /// # Notes + /// The compression strategy will be reset to the default one when this is called. + pub fn set_compression_level_raw(&mut self, level: u8) { + let format = self.data_format(); + self.set_format_and_level(format, level); + } + + /// Update the compression settings of the compressor. + /// + /// Changing the `DataFormat` after compression has started will result in + /// a corrupted stream. + /// + /// # Notes + /// This function mainly intended for setting the initial settings after e.g creating with + /// `default` or after calling `CompressorOxide::reset()`, and behaviour may be changed + /// to disallow calling it after starting compression in the future. + pub fn set_format_and_level(&mut self, data_format: DataFormat, level: u8) { + let flags = create_comp_flags_from_zip_params( + level.into(), + data_format.to_window_bits(), + CompressionStrategy::Default as i32, + ); + self.params.update_flags(flags); + self.dict.update_flags(flags); + } +} + +impl Default for CompressorOxide { + /// Initialize the compressor with a level of 4, zlib wrapper and + /// the default strategy. + fn default() -> Self { + CompressorOxide { + lz: LZOxide::new(), + params: ParamsOxide::new(DEFAULT_FLAGS), + huff: Box::default(), + dict: DictOxide::new(DEFAULT_FLAGS), + } + } +} + +/// Callback function and user used in `compress_to_output`. +pub struct CallbackFunc<'a> { + pub put_buf_func: &'a mut dyn FnMut(&[u8]) -> bool, +} + +impl<'a> CallbackFunc<'a> { + fn flush_output( + &mut self, + saved_output: SavedOutputBufferOxide, + params: &mut ParamsOxide, + ) -> i32 { + // TODO: As this could be unsafe since + // we can't verify the function pointer + // this whole function should maybe be unsafe as well. + let call_success = (self.put_buf_func)(¶ms.local_buf.b[0..saved_output.pos]); + + if !call_success { + params.prev_return_status = TDEFLStatus::PutBufFailed; + return params.prev_return_status as i32; + } + + params.flush_remaining as i32 + } +} + +struct CallbackBuf<'a> { + pub out_buf: &'a mut [u8], +} + +impl<'a> CallbackBuf<'a> { + fn flush_output( + &mut self, + saved_output: SavedOutputBufferOxide, + params: &mut ParamsOxide, + ) -> i32 { + if saved_output.local { + let n = cmp::min(saved_output.pos, self.out_buf.len() - params.out_buf_ofs); + (self.out_buf[params.out_buf_ofs..params.out_buf_ofs + n]) + .copy_from_slice(¶ms.local_buf.b[..n]); + + params.out_buf_ofs += n; + if saved_output.pos != n { + params.flush_ofs = n as u32; + params.flush_remaining = (saved_output.pos - n) as u32; + } + } else { + params.out_buf_ofs += saved_output.pos; + } + + params.flush_remaining as i32 + } +} + +enum CallbackOut<'a> { + Func(CallbackFunc<'a>), + Buf(CallbackBuf<'a>), +} + +impl<'a> CallbackOut<'a> { + fn new_output_buffer<'b>( + &'b mut self, + local_buf: &'b mut [u8], + out_buf_ofs: usize, + ) -> OutputBufferOxide<'b> { + let is_local; + let buf_len = OUT_BUF_SIZE - 16; + let chosen_buffer = match *self { + CallbackOut::Buf(ref mut cb) if cb.out_buf.len() - out_buf_ofs >= OUT_BUF_SIZE => { + is_local = false; + &mut cb.out_buf[out_buf_ofs..out_buf_ofs + buf_len] + } + _ => { + is_local = true; + &mut local_buf[..buf_len] + } + }; + + OutputBufferOxide { + inner: chosen_buffer, + inner_pos: 0, + local: is_local, + bit_buffer: 0, + bits_in: 0, + } + } +} + +struct CallbackOxide<'a> { + in_buf: Option<&'a [u8]>, + in_buf_size: Option<&'a mut usize>, + out_buf_size: Option<&'a mut usize>, + out: CallbackOut<'a>, +} + +impl<'a> CallbackOxide<'a> { + fn new_callback_buf(in_buf: &'a [u8], out_buf: &'a mut [u8]) -> Self { + CallbackOxide { + in_buf: Some(in_buf), + in_buf_size: None, + out_buf_size: None, + out: CallbackOut::Buf(CallbackBuf { out_buf }), + } + } + + fn new_callback_func(in_buf: &'a [u8], callback_func: CallbackFunc<'a>) -> Self { + CallbackOxide { + in_buf: Some(in_buf), + in_buf_size: None, + out_buf_size: None, + out: CallbackOut::Func(callback_func), + } + } + + fn update_size(&mut self, in_size: Option<usize>, out_size: Option<usize>) { + if let (Some(in_size), Some(size)) = (in_size, self.in_buf_size.as_mut()) { + **size = in_size; + } + + if let (Some(out_size), Some(size)) = (out_size, self.out_buf_size.as_mut()) { + **size = out_size + } + } + + fn flush_output( + &mut self, + saved_output: SavedOutputBufferOxide, + params: &mut ParamsOxide, + ) -> i32 { + if saved_output.pos == 0 { + return params.flush_remaining as i32; + } + + self.update_size(Some(params.src_pos), None); + match self.out { + CallbackOut::Func(ref mut cf) => cf.flush_output(saved_output, params), + CallbackOut::Buf(ref mut cb) => cb.flush_output(saved_output, params), + } + } +} + +struct OutputBufferOxide<'a> { + pub inner: &'a mut [u8], + pub inner_pos: usize, + pub local: bool, + + pub bit_buffer: u32, + pub bits_in: u32, +} + +impl<'a> OutputBufferOxide<'a> { + fn put_bits(&mut self, bits: u32, len: u32) { + // TODO: Removing this assertion worsens performance + // Need to figure out why + assert!(bits <= ((1u32 << len) - 1u32)); + self.bit_buffer |= bits << self.bits_in; + self.bits_in += len; + + while self.bits_in >= 8 { + self.inner[self.inner_pos] = self.bit_buffer as u8; + self.inner_pos += 1; + self.bit_buffer >>= 8; + self.bits_in -= 8; + } + } + + const fn save(&self) -> SavedOutputBufferOxide { + SavedOutputBufferOxide { + pos: self.inner_pos, + bit_buffer: self.bit_buffer, + bits_in: self.bits_in, + local: self.local, + } + } + + fn load(&mut self, saved: SavedOutputBufferOxide) { + self.inner_pos = saved.pos; + self.bit_buffer = saved.bit_buffer; + self.bits_in = saved.bits_in; + self.local = saved.local; + } + + fn pad_to_bytes(&mut self) { + if self.bits_in != 0 { + let len = 8 - self.bits_in; + self.put_bits(0, len); + } + } +} + +struct SavedOutputBufferOxide { + pub pos: usize, + pub bit_buffer: u32, + pub bits_in: u32, + pub local: bool, +} + +struct BitBuffer { + pub bit_buffer: u64, + pub bits_in: u32, +} + +impl BitBuffer { + fn put_fast(&mut self, bits: u64, len: u32) { + self.bit_buffer |= bits << self.bits_in; + self.bits_in += len; + } + + fn flush(&mut self, output: &mut OutputBufferOxide) -> Result<()> { + let pos = output.inner_pos; + { + // isolation to please borrow checker + let inner = &mut output.inner[pos..pos + 8]; + let bytes = u64::to_le_bytes(self.bit_buffer); + inner.copy_from_slice(&bytes); + } + match output.inner_pos.checked_add((self.bits_in >> 3) as usize) { + Some(n) if n <= output.inner.len() => output.inner_pos = n, + _ => return Err(Error {}), + } + self.bit_buffer >>= self.bits_in & !7; + self.bits_in &= 7; + Ok(()) + } +} + +/// A struct containing data about huffman codes and symbol frequencies. +/// +/// NOTE: Only the literal/lengths have enough symbols to actually use +/// the full array. It's unclear why it's defined like this in miniz, +/// it could be for cache/alignment reasons. +struct HuffmanOxide { + /// Number of occurrences of each symbol. + pub count: [[u16; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES], + /// The bits of the huffman code assigned to the symbol + pub codes: [[u16; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES], + /// The length of the huffman code assigned to the symbol. + pub code_sizes: [[u8; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES], +} + +/// Tables used for literal/lengths in `HuffmanOxide`. +const LITLEN_TABLE: usize = 0; +/// Tables for distances. +const DIST_TABLE: usize = 1; +/// Tables for the run-length encoded huffman lengths for literals/lengths/distances. +const HUFF_CODES_TABLE: usize = 2; + +/// Status of RLE encoding of huffman code lengths. +struct Rle { + pub z_count: u32, + pub repeat_count: u32, + pub prev_code_size: u8, +} + +impl Rle { + fn prev_code_size( + &mut self, + packed_code_sizes: &mut [u8], + packed_pos: &mut usize, + h: &mut HuffmanOxide, + ) -> Result<()> { + let mut write = |buf| write(buf, packed_code_sizes, packed_pos); + let counts = &mut h.count[HUFF_CODES_TABLE]; + if self.repeat_count != 0 { + if self.repeat_count < 3 { + counts[self.prev_code_size as usize] = + counts[self.prev_code_size as usize].wrapping_add(self.repeat_count as u16); + let code = self.prev_code_size; + write(&[code, code, code][..self.repeat_count as usize])?; + } else { + counts[16] = counts[16].wrapping_add(1); + write(&[16, (self.repeat_count - 3) as u8][..])?; + } + self.repeat_count = 0; + } + + Ok(()) + } + + fn zero_code_size( + &mut self, + packed_code_sizes: &mut [u8], + packed_pos: &mut usize, + h: &mut HuffmanOxide, + ) -> Result<()> { + let mut write = |buf| write(buf, packed_code_sizes, packed_pos); + let counts = &mut h.count[HUFF_CODES_TABLE]; + if self.z_count != 0 { + if self.z_count < 3 { + counts[0] = counts[0].wrapping_add(self.z_count as u16); + write(&[0, 0, 0][..self.z_count as usize])?; + } else if self.z_count <= 10 { + counts[17] = counts[17].wrapping_add(1); + write(&[17, (self.z_count - 3) as u8][..])?; + } else { + counts[18] = counts[18].wrapping_add(1); + write(&[18, (self.z_count - 11) as u8][..])?; + } + self.z_count = 0; + } + + Ok(()) + } +} + +fn write(src: &[u8], dst: &mut [u8], dst_pos: &mut usize) -> Result<()> { + match dst.get_mut(*dst_pos..*dst_pos + src.len()) { + Some(s) => s.copy_from_slice(src), + None => return Err(Error {}), + } + *dst_pos += src.len(); + Ok(()) +} + +impl Default for HuffmanOxide { + fn default() -> Self { + HuffmanOxide { + count: [[0; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES], + codes: [[0; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES], + code_sizes: [[0; MAX_HUFF_SYMBOLS]; MAX_HUFF_TABLES], + } + } +} + +impl HuffmanOxide { + fn radix_sort_symbols<'a>( + symbols0: &'a mut [SymFreq], + symbols1: &'a mut [SymFreq], + ) -> &'a mut [SymFreq] { + let mut hist = [[0; 256]; 2]; + + for freq in symbols0.iter() { + hist[0][(freq.key & 0xFF) as usize] += 1; + hist[1][((freq.key >> 8) & 0xFF) as usize] += 1; + } + + let mut n_passes = 2; + if symbols0.len() == hist[1][0] { + n_passes -= 1; + } + + let mut current_symbols = symbols0; + let mut new_symbols = symbols1; + + for (pass, hist_item) in hist.iter().enumerate().take(n_passes) { + let mut offsets = [0; 256]; + let mut offset = 0; + for i in 0..256 { + offsets[i] = offset; + offset += hist_item[i]; + } + + for sym in current_symbols.iter() { + let j = ((sym.key >> (pass * 8)) & 0xFF) as usize; + new_symbols[offsets[j]] = *sym; + offsets[j] += 1; + } + + mem::swap(&mut current_symbols, &mut new_symbols); + } + + current_symbols + } + + fn calculate_minimum_redundancy(symbols: &mut [SymFreq]) { + match symbols.len() { + 0 => (), + 1 => symbols[0].key = 1, + n => { + symbols[0].key += symbols[1].key; + let mut root = 0; + let mut leaf = 2; + for next in 1..n - 1 { + if (leaf >= n) || (symbols[root].key < symbols[leaf].key) { + symbols[next].key = symbols[root].key; + symbols[root].key = next as u16; + root += 1; + } else { + symbols[next].key = symbols[leaf].key; + leaf += 1; + } + + if (leaf >= n) || (root < next && symbols[root].key < symbols[leaf].key) { + symbols[next].key = symbols[next].key.wrapping_add(symbols[root].key); + symbols[root].key = next as u16; + root += 1; + } else { + symbols[next].key = symbols[next].key.wrapping_add(symbols[leaf].key); + leaf += 1; + } + } + + symbols[n - 2].key = 0; + for next in (0..n - 2).rev() { + symbols[next].key = symbols[symbols[next].key as usize].key + 1; + } + + let mut avbl = 1; + let mut used = 0; + let mut dpth = 0; + let mut root = (n - 2) as i32; + let mut next = (n - 1) as i32; + while avbl > 0 { + while (root >= 0) && (symbols[root as usize].key == dpth) { + used += 1; + root -= 1; + } + while avbl > used { + symbols[next as usize].key = dpth; + next -= 1; + avbl -= 1; + } + avbl = 2 * used; + dpth += 1; + used = 0; + } + } + } + } + + fn enforce_max_code_size(num_codes: &mut [i32], code_list_len: usize, max_code_size: usize) { + if code_list_len <= 1 { + return; + } + + num_codes[max_code_size] += num_codes[max_code_size + 1..].iter().sum::<i32>(); + let total = num_codes[1..=max_code_size] + .iter() + .rev() + .enumerate() + .fold(0u32, |total, (i, &x)| total + ((x as u32) << i)); + + for _ in (1 << max_code_size)..total { + num_codes[max_code_size] -= 1; + for i in (1..max_code_size).rev() { + if num_codes[i] != 0 { + num_codes[i] -= 1; + num_codes[i + 1] += 2; + break; + } + } + } + } + + fn optimize_table( + &mut self, + table_num: usize, + table_len: usize, + code_size_limit: usize, + static_table: bool, + ) { + let mut num_codes = [0i32; MAX_SUPPORTED_HUFF_CODESIZE + 1]; + let mut next_code = [0u32; MAX_SUPPORTED_HUFF_CODESIZE + 1]; + + if static_table { + for &code_size in &self.code_sizes[table_num][..table_len] { + num_codes[code_size as usize] += 1; + } + } else { + let mut symbols0 = [SymFreq { + key: 0, + sym_index: 0, + }; MAX_HUFF_SYMBOLS]; + let mut symbols1 = [SymFreq { + key: 0, + sym_index: 0, + }; MAX_HUFF_SYMBOLS]; + + let mut num_used_symbols = 0; + for i in 0..table_len { + if self.count[table_num][i] != 0 { + symbols0[num_used_symbols] = SymFreq { + key: self.count[table_num][i], + sym_index: i as u16, + }; + num_used_symbols += 1; + } + } + + let symbols = Self::radix_sort_symbols( + &mut symbols0[..num_used_symbols], + &mut symbols1[..num_used_symbols], + ); + Self::calculate_minimum_redundancy(symbols); + + for symbol in symbols.iter() { + num_codes[symbol.key as usize] += 1; + } + + Self::enforce_max_code_size(&mut num_codes, num_used_symbols, code_size_limit); + + memset(&mut self.code_sizes[table_num][..], 0); + memset(&mut self.codes[table_num][..], 0); + + let mut last = num_used_symbols; + for (i, &num_item) in num_codes + .iter() + .enumerate() + .take(code_size_limit + 1) + .skip(1) + { + let first = last - num_item as usize; + for symbol in &symbols[first..last] { + self.code_sizes[table_num][symbol.sym_index as usize] = i as u8; + } + last = first; + } + } + + let mut j = 0; + next_code[1] = 0; + for i in 2..=code_size_limit { + j = (j + num_codes[i - 1]) << 1; + next_code[i] = j as u32; + } + + for (&code_size, huff_code) in self.code_sizes[table_num] + .iter() + .take(table_len) + .zip(self.codes[table_num].iter_mut().take(table_len)) + { + if code_size == 0 { + continue; + } + + let mut code = next_code[code_size as usize]; + next_code[code_size as usize] += 1; + + let mut rev_code = 0; + for _ in 0..code_size { + rev_code = (rev_code << 1) | (code & 1); + code >>= 1; + } + *huff_code = rev_code as u16; + } + } + + fn start_static_block(&mut self, output: &mut OutputBufferOxide) { + memset(&mut self.code_sizes[LITLEN_TABLE][0..144], 8); + memset(&mut self.code_sizes[LITLEN_TABLE][144..256], 9); + memset(&mut self.code_sizes[LITLEN_TABLE][256..280], 7); + memset(&mut self.code_sizes[LITLEN_TABLE][280..288], 8); + + memset(&mut self.code_sizes[DIST_TABLE][..32], 5); + + self.optimize_table(LITLEN_TABLE, 288, 15, true); + self.optimize_table(DIST_TABLE, 32, 15, true); + + output.put_bits(0b01, 2) + } + + fn start_dynamic_block(&mut self, output: &mut OutputBufferOxide) -> Result<()> { + // There will always be one, and only one end of block code. + self.count[0][256] = 1; + + self.optimize_table(0, MAX_HUFF_SYMBOLS_0, 15, false); + self.optimize_table(1, MAX_HUFF_SYMBOLS_1, 15, false); + + let num_lit_codes = 286 + - &self.code_sizes[0][257..286] + .iter() + .rev() + .take_while(|&x| *x == 0) + .count(); + + let num_dist_codes = 30 + - &self.code_sizes[1][1..30] + .iter() + .rev() + .take_while(|&x| *x == 0) + .count(); + + let mut code_sizes_to_pack = [0u8; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1]; + let mut packed_code_sizes = [0u8; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1]; + + let total_code_sizes_to_pack = num_lit_codes + num_dist_codes; + + code_sizes_to_pack[..num_lit_codes].copy_from_slice(&self.code_sizes[0][..num_lit_codes]); + + code_sizes_to_pack[num_lit_codes..total_code_sizes_to_pack] + .copy_from_slice(&self.code_sizes[1][..num_dist_codes]); + + let mut rle = Rle { + z_count: 0, + repeat_count: 0, + prev_code_size: 0xFF, + }; + + memset(&mut self.count[HUFF_CODES_TABLE][..MAX_HUFF_SYMBOLS_2], 0); + + let mut packed_pos = 0; + for &code_size in &code_sizes_to_pack[..total_code_sizes_to_pack] { + if code_size == 0 { + rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?; + rle.z_count += 1; + if rle.z_count == 138 { + rle.zero_code_size(&mut packed_code_sizes, &mut packed_pos, self)?; + } + } else { + rle.zero_code_size(&mut packed_code_sizes, &mut packed_pos, self)?; + if code_size != rle.prev_code_size { + rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?; + self.count[HUFF_CODES_TABLE][code_size as usize] = + self.count[HUFF_CODES_TABLE][code_size as usize].wrapping_add(1); + write(&[code_size], &mut packed_code_sizes, &mut packed_pos)?; + } else { + rle.repeat_count += 1; + if rle.repeat_count == 6 { + rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?; + } + } + } + rle.prev_code_size = code_size; + } + + if rle.repeat_count != 0 { + rle.prev_code_size(&mut packed_code_sizes, &mut packed_pos, self)?; + } else { + rle.zero_code_size(&mut packed_code_sizes, &mut packed_pos, self)?; + } + + self.optimize_table(2, MAX_HUFF_SYMBOLS_2, 7, false); + + output.put_bits(2, 2); + + output.put_bits((num_lit_codes - 257) as u32, 5); + output.put_bits((num_dist_codes - 1) as u32, 5); + + let mut num_bit_lengths = 18 + - HUFFMAN_LENGTH_ORDER + .iter() + .rev() + .take_while(|&swizzle| self.code_sizes[HUFF_CODES_TABLE][*swizzle as usize] == 0) + .count(); + + num_bit_lengths = cmp::max(4, num_bit_lengths + 1); + output.put_bits(num_bit_lengths as u32 - 4, 4); + for &swizzle in &HUFFMAN_LENGTH_ORDER[..num_bit_lengths] { + output.put_bits( + u32::from(self.code_sizes[HUFF_CODES_TABLE][swizzle as usize]), + 3, + ); + } + + let mut packed_code_size_index = 0; + while packed_code_size_index < packed_pos { + let code = packed_code_sizes[packed_code_size_index] as usize; + packed_code_size_index += 1; + assert!(code < MAX_HUFF_SYMBOLS_2); + output.put_bits( + u32::from(self.codes[HUFF_CODES_TABLE][code]), + u32::from(self.code_sizes[HUFF_CODES_TABLE][code]), + ); + if code >= 16 { + output.put_bits( + u32::from(packed_code_sizes[packed_code_size_index]), + [2, 3, 7][code - 16], + ); + packed_code_size_index += 1; + } + } + + Ok(()) + } +} + +struct DictOxide { + /// The maximum number of checks in the hash chain, for the initial, + /// and the lazy match respectively. + pub max_probes: [u32; 2], + /// Buffer of input data. + /// Padded with 1 byte to simplify matching code in `compress_fast`. + pub b: Box<HashBuffers>, + + pub code_buf_dict_pos: usize, + pub lookahead_size: usize, + pub lookahead_pos: usize, + pub size: usize, +} + +const fn probes_from_flags(flags: u32) -> [u32; 2] { + [ + 1 + ((flags & 0xFFF) + 2) / 3, + 1 + (((flags & 0xFFF) >> 2) + 2) / 3, + ] +} + +impl DictOxide { + fn new(flags: u32) -> Self { + DictOxide { + max_probes: probes_from_flags(flags), + b: Box::default(), + code_buf_dict_pos: 0, + lookahead_size: 0, + lookahead_pos: 0, + size: 0, + } + } + + fn update_flags(&mut self, flags: u32) { + self.max_probes = probes_from_flags(flags); + } + + fn reset(&mut self) { + self.b.reset(); + self.code_buf_dict_pos = 0; + self.lookahead_size = 0; + self.lookahead_pos = 0; + self.size = 0; + } + + /// Do an unaligned read of the data at `pos` in the dictionary and treat it as if it was of + /// type T. + #[inline] + fn read_unaligned_u32(&self, pos: usize) -> u32 { + // Masking the value here helps avoid bounds checks. + let pos = pos & LZ_DICT_SIZE_MASK; + let end = pos + 4; + // Somehow this assertion makes things faster. + // TODO: as of may 2024 this does not seem to make any difference + // so consider removing. + assert!(end < LZ_DICT_FULL_SIZE); + + let bytes: [u8; 4] = self.b.dict[pos..end].try_into().unwrap(); + u32::from_le_bytes(bytes) + } + + /// Do an unaligned read of the data at `pos` in the dictionary and treat it as if it was of + /// type T. + #[inline] + fn read_unaligned_u64(&self, pos: usize) -> u64 { + // Help evade bounds/panic code check by masking the position value + // This provides a small speedup at the cost of an instruction or two instead of + // having to use unsafe. + let pos = pos & LZ_DICT_SIZE_MASK; + let bytes: [u8; 8] = self.b.dict[pos..pos + 8].try_into().unwrap(); + u64::from_le_bytes(bytes) + } + + /// Do an unaligned read of the data at `pos` in the dictionary and treat it as if it was of + /// type T. + #[inline] + fn read_as_u16(&self, pos: usize) -> u16 { + read_u16_le(&self.b.dict[..], pos) + } + + /// Try to find a match for the data at lookahead_pos in the dictionary that is + /// longer than `match_len`. + /// Returns a tuple containing (match_distance, match_length). Will be equal to the input + /// values if no better matches were found. + fn find_match( + &self, + lookahead_pos: usize, + max_dist: usize, + max_match_len: u32, + mut match_dist: u32, + mut match_len: u32, + ) -> (u32, u32) { + // Clamp the match len and max_match_len to be valid. (It should be when this is called, but + // do it for now just in case for safety reasons.) + // This should normally end up as at worst conditional moves, + // so it shouldn't slow us down much. + // TODO: Statically verify these so we don't need to do this. + let max_match_len = cmp::min(MAX_MATCH_LEN as u32, max_match_len); + match_len = cmp::max(match_len, 1); + + let pos = lookahead_pos & LZ_DICT_SIZE_MASK; + let mut probe_pos = pos; + // Number of probes into the hash chains. + let mut num_probes_left = self.max_probes[(match_len >= 32) as usize]; + + // If we already have a match of the full length don't bother searching for another one. + if max_match_len <= match_len { + return (match_dist, match_len); + } + + // Read the last byte of the current match, and the next one, used to compare matches. + let mut c01: u16 = self.read_as_u16(pos + match_len as usize - 1); + // Read the two bytes at the end position of the current match. + let s01: u16 = self.read_as_u16(pos); + + 'outer: loop { + let mut dist; + 'found: loop { + num_probes_left -= 1; + if num_probes_left == 0 { + // We have done as many probes in the hash chain as the current compression + // settings allow, so return the best match we found, if any. + return (match_dist, match_len); + } + + for _ in 0..3 { + let next_probe_pos = self.b.next[probe_pos] as usize; + + dist = (lookahead_pos - next_probe_pos) & 0xFFFF; + if next_probe_pos == 0 || dist > max_dist { + // We reached the end of the hash chain, or the next value is further away + // than the maximum allowed distance, so return the best match we found, if + // any. + return (match_dist, match_len); + } + + // Mask the position value to get the position in the hash chain of the next + // position to match against. + probe_pos = next_probe_pos & LZ_DICT_SIZE_MASK; + + if self.read_as_u16(probe_pos + match_len as usize - 1) == c01 { + break 'found; + } + } + } + + if dist == 0 { + // We've looked through the whole match range, so return the best match we + // found. + return (match_dist, match_len); + } + + // Check if the two first bytes match. + if self.read_as_u16(probe_pos) != s01 { + continue; + } + + let mut p = pos + 2; + let mut q = probe_pos + 2; + // The first two bytes matched, so check the full length of the match. + for _ in 0..32 { + let p_data: u64 = self.read_unaligned_u64(p); + let q_data: u64 = self.read_unaligned_u64(q); + // Compare of 8 bytes at a time by using unaligned loads of 64-bit integers. + let xor_data = p_data ^ q_data; + if xor_data == 0 { + p += 8; + q += 8; + } else { + // If not all of the last 8 bytes matched, check how may of them did. + let trailing = xor_data.trailing_zeros(); + + let probe_len = p - pos + (trailing as usize >> 3); + if probe_len > match_len as usize { + match_dist = dist as u32; + match_len = cmp::min(max_match_len, probe_len as u32); + if match_len == max_match_len { + // We found a match that had the maximum allowed length, + // so there is now point searching further. + return (match_dist, match_len); + } + // We found a better match, so save the last two bytes for further match + // comparisons. + c01 = self.read_as_u16(pos + match_len as usize - 1) + } + continue 'outer; + } + } + + return (dist as u32, cmp::min(max_match_len, MAX_MATCH_LEN as u32)); + } + } +} + +struct ParamsOxide { + pub flags: u32, + pub greedy_parsing: bool, + pub block_index: u32, + + pub saved_match_dist: u32, + pub saved_match_len: u32, + pub saved_lit: u8, + + pub flush: TDEFLFlush, + pub flush_ofs: u32, + pub flush_remaining: u32, + pub finished: bool, + + pub adler32: u32, + + pub src_pos: usize, + + pub out_buf_ofs: usize, + pub prev_return_status: TDEFLStatus, + + pub saved_bit_buffer: u32, + pub saved_bits_in: u32, + + pub local_buf: Box<LocalBuf>, +} + +impl ParamsOxide { + fn new(flags: u32) -> Self { + ParamsOxide { + flags, + greedy_parsing: flags & TDEFL_GREEDY_PARSING_FLAG != 0, + block_index: 0, + saved_match_dist: 0, + saved_match_len: 0, + saved_lit: 0, + flush: TDEFLFlush::None, + flush_ofs: 0, + flush_remaining: 0, + finished: false, + adler32: MZ_ADLER32_INIT, + src_pos: 0, + out_buf_ofs: 0, + prev_return_status: TDEFLStatus::Okay, + saved_bit_buffer: 0, + saved_bits_in: 0, + local_buf: Box::default(), + } + } + + fn update_flags(&mut self, flags: u32) { + self.flags = flags; + self.greedy_parsing = self.flags & TDEFL_GREEDY_PARSING_FLAG != 0; + } + + /// Reset state, saving settings. + fn reset(&mut self) { + self.block_index = 0; + self.saved_match_len = 0; + self.saved_match_dist = 0; + self.saved_lit = 0; + self.flush = TDEFLFlush::None; + self.flush_ofs = 0; + self.flush_remaining = 0; + self.finished = false; + self.adler32 = MZ_ADLER32_INIT; + self.src_pos = 0; + self.out_buf_ofs = 0; + self.prev_return_status = TDEFLStatus::Okay; + self.saved_bit_buffer = 0; + self.saved_bits_in = 0; + self.local_buf.b = [0; OUT_BUF_SIZE]; + } +} + +struct LZOxide { + pub codes: [u8; LZ_CODE_BUF_SIZE], + pub code_position: usize, + pub flag_position: usize, + + // The total number of bytes in the current block. + pub total_bytes: u32, + pub num_flags_left: u32, +} + +impl LZOxide { + const fn new() -> Self { + LZOxide { + codes: [0; LZ_CODE_BUF_SIZE], + code_position: 1, + flag_position: 0, + total_bytes: 0, + num_flags_left: 8, + } + } + + fn write_code(&mut self, val: u8) { + // Perf - go via u16 to help evade bounds check + // TODO: see if we can use u16 for flag_position in general. + self.codes[usize::from(self.code_position as u16)] = val; + self.code_position += 1; + } + + fn init_flag(&mut self) { + if self.num_flags_left == 8 { + *self.get_flag() = 0; + self.code_position -= 1; + } else { + *self.get_flag() >>= self.num_flags_left; + } + } + + fn get_flag(&mut self) -> &mut u8 { + // Perf - go via u16 to help evade bounds check + // TODO: see if we can use u16 for flag_position in general. + &mut self.codes[usize::from(self.flag_position as u16)] + } + + fn plant_flag(&mut self) { + self.flag_position = self.code_position; + self.code_position += 1; + } + + fn consume_flag(&mut self) { + self.num_flags_left -= 1; + if self.num_flags_left == 0 { + self.num_flags_left = 8; + self.plant_flag(); + } + } +} + +fn compress_lz_codes( + huff: &HuffmanOxide, + output: &mut OutputBufferOxide, + lz_code_buf: &[u8], +) -> Result<bool> { + let mut flags = 1; + let mut bb = BitBuffer { + bit_buffer: u64::from(output.bit_buffer), + bits_in: output.bits_in, + }; + + let mut i: usize = 0; + while i < lz_code_buf.len() { + if flags == 1 { + flags = u32::from(lz_code_buf[i]) | 0x100; + i += 1; + } + + // The lz code was a length code + if flags & 1 == 1 { + flags >>= 1; + + let sym; + let num_extra_bits; + + let match_len = lz_code_buf[i] as usize; + + let match_dist = read_u16_le(lz_code_buf, i + 1); + + i += 3; + + debug_assert!(huff.code_sizes[0][LEN_SYM[match_len] as usize] != 0); + bb.put_fast( + u64::from(huff.codes[0][LEN_SYM[match_len] as usize]), + u32::from(huff.code_sizes[0][LEN_SYM[match_len] as usize]), + ); + bb.put_fast( + match_len as u64 & u64::from(BITMASKS[LEN_EXTRA[match_len] as usize]), + u32::from(LEN_EXTRA[match_len]), + ); + + if match_dist < 512 { + sym = SMALL_DIST_SYM[match_dist as usize] as usize; + num_extra_bits = SMALL_DIST_EXTRA[match_dist as usize] as usize; + } else { + sym = LARGE_DIST_SYM[(match_dist >> 8) as usize] as usize; + num_extra_bits = LARGE_DIST_EXTRA[(match_dist >> 8) as usize] as usize; + } + + debug_assert!(huff.code_sizes[1][sym] != 0); + bb.put_fast( + u64::from(huff.codes[1][sym]), + u32::from(huff.code_sizes[1][sym]), + ); + bb.put_fast( + u64::from(match_dist) & u64::from(BITMASKS[num_extra_bits]), + num_extra_bits as u32, + ); + } else { + // The lz code was a literal + for _ in 0..3 { + flags >>= 1; + let lit = lz_code_buf[i]; + i += 1; + + debug_assert!(huff.code_sizes[0][lit as usize] != 0); + bb.put_fast( + u64::from(huff.codes[0][lit as usize]), + u32::from(huff.code_sizes[0][lit as usize]), + ); + + if flags & 1 == 1 || i >= lz_code_buf.len() { + break; + } + } + } + + bb.flush(output)?; + } + + output.bits_in = 0; + output.bit_buffer = 0; + while bb.bits_in != 0 { + let n = cmp::min(bb.bits_in, 16); + output.put_bits(bb.bit_buffer as u32 & BITMASKS[n as usize], n); + bb.bit_buffer >>= n; + bb.bits_in -= n; + } + + // Output the end of block symbol. + output.put_bits( + u32::from(huff.codes[0][256]), + u32::from(huff.code_sizes[0][256]), + ); + + Ok(true) +} + +fn compress_block( + huff: &mut HuffmanOxide, + output: &mut OutputBufferOxide, + lz: &LZOxide, + static_block: bool, +) -> Result<bool> { + if static_block { + huff.start_static_block(output); + } else { + huff.start_dynamic_block(output)?; + } + + compress_lz_codes(huff, output, &lz.codes[..lz.code_position]) +} + +fn flush_block( + d: &mut CompressorOxide, + callback: &mut CallbackOxide, + flush: TDEFLFlush, +) -> Result<i32> { + let mut saved_buffer; + { + let mut output = callback + .out + .new_output_buffer(&mut d.params.local_buf.b, d.params.out_buf_ofs); + output.bit_buffer = d.params.saved_bit_buffer; + output.bits_in = d.params.saved_bits_in; + + let use_raw_block = (d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0) + && (d.dict.lookahead_pos - d.dict.code_buf_dict_pos) <= d.dict.size; + + assert!(d.params.flush_remaining == 0); + d.params.flush_ofs = 0; + d.params.flush_remaining = 0; + + d.lz.init_flag(); + + // If we are at the start of the stream, write the zlib header if requested. + if d.params.flags & TDEFL_WRITE_ZLIB_HEADER != 0 && d.params.block_index == 0 { + let header = zlib::header_from_flags(d.params.flags); + output.put_bits(header[0].into(), 8); + output.put_bits(header[1].into(), 8); + } + + // Output the block header. + output.put_bits((flush == TDEFLFlush::Finish) as u32, 1); + + saved_buffer = output.save(); + + let comp_success = if !use_raw_block { + let use_static = + (d.params.flags & TDEFL_FORCE_ALL_STATIC_BLOCKS != 0) || (d.lz.total_bytes < 48); + compress_block(&mut d.huff, &mut output, &d.lz, use_static)? + } else { + false + }; + + // If we failed to compress anything and the output would take up more space than the output + // data, output a stored block instead, which has at most 5 bytes of overhead. + // We only use some simple heuristics for now. + // A stored block will have an overhead of at least 4 bytes containing the block length + // but usually more due to the length parameters having to start at a byte boundary and thus + // requiring up to 5 bytes of padding. + // As a static block will have an overhead of at most 1 bit per byte + // (as literals are either 8 or 9 bytes), a raw block will + // never take up less space if the number of input bytes are less than 32. + let expanded = (d.lz.total_bytes > 32) + && (output.inner_pos - saved_buffer.pos + 1 >= (d.lz.total_bytes as usize)) + && (d.dict.lookahead_pos - d.dict.code_buf_dict_pos <= d.dict.size); + + if use_raw_block || expanded { + output.load(saved_buffer); + + // Block header. + output.put_bits(0, 2); + + // Block length has to start on a byte boundary, s opad. + output.pad_to_bytes(); + + // Block length and ones complement of block length. + output.put_bits(d.lz.total_bytes & 0xFFFF, 16); + output.put_bits(!d.lz.total_bytes & 0xFFFF, 16); + + // Write the actual bytes. + for i in 0..d.lz.total_bytes { + let pos = (d.dict.code_buf_dict_pos + i as usize) & LZ_DICT_SIZE_MASK; + output.put_bits(u32::from(d.dict.b.dict[pos]), 8); + } + } else if !comp_success { + output.load(saved_buffer); + compress_block(&mut d.huff, &mut output, &d.lz, true)?; + } + + if flush != TDEFLFlush::None { + if flush == TDEFLFlush::Finish { + output.pad_to_bytes(); + if d.params.flags & TDEFL_WRITE_ZLIB_HEADER != 0 { + let mut adler = d.params.adler32; + for _ in 0..4 { + output.put_bits((adler >> 24) & 0xFF, 8); + adler <<= 8; + } + } + } else { + // Sync or Full flush. + // Output an empty raw block. + output.put_bits(0, 3); + output.pad_to_bytes(); + output.put_bits(0, 16); + output.put_bits(0xFFFF, 16); + } + } + + memset(&mut d.huff.count[0][..MAX_HUFF_SYMBOLS_0], 0); + memset(&mut d.huff.count[1][..MAX_HUFF_SYMBOLS_1], 0); + + d.lz.code_position = 1; + d.lz.flag_position = 0; + d.lz.num_flags_left = 8; + d.dict.code_buf_dict_pos += d.lz.total_bytes as usize; + d.lz.total_bytes = 0; + d.params.block_index += 1; + + saved_buffer = output.save(); + + d.params.saved_bit_buffer = saved_buffer.bit_buffer; + d.params.saved_bits_in = saved_buffer.bits_in; + } + + Ok(callback.flush_output(saved_buffer, &mut d.params)) +} + +fn record_literal(h: &mut HuffmanOxide, lz: &mut LZOxide, lit: u8) { + lz.total_bytes += 1; + lz.write_code(lit); + + *lz.get_flag() >>= 1; + lz.consume_flag(); + + h.count[0][lit as usize] += 1; +} + +fn record_match(h: &mut HuffmanOxide, lz: &mut LZOxide, mut match_len: u32, mut match_dist: u32) { + debug_assert!(match_len >= MIN_MATCH_LEN.into()); + debug_assert!(match_dist >= 1); + debug_assert!(match_dist as usize <= LZ_DICT_SIZE); + + lz.total_bytes += match_len; + match_dist -= 1; + match_len -= u32::from(MIN_MATCH_LEN); + lz.write_code(match_len as u8); + lz.write_code(match_dist as u8); + lz.write_code((match_dist >> 8) as u8); + + *lz.get_flag() >>= 1; + *lz.get_flag() |= 0x80; + lz.consume_flag(); + + let symbol = if match_dist < 512 { + SMALL_DIST_SYM[match_dist as usize] + } else { + LARGE_DIST_SYM[((match_dist >> 8) & 127) as usize] + } as usize; + h.count[1][symbol] += 1; + // Perf - go via u8 to help optimize out bounds check. + h.count[0][LEN_SYM[usize::from(match_len as u8)] as usize] += 1; +} + +fn compress_normal(d: &mut CompressorOxide, callback: &mut CallbackOxide) -> bool { + let mut src_pos = d.params.src_pos; + let in_buf = match callback.in_buf { + None => return true, + Some(in_buf) => in_buf, + }; + + let mut lookahead_size = d.dict.lookahead_size; + let mut lookahead_pos = d.dict.lookahead_pos; + let mut saved_lit = d.params.saved_lit; + let mut saved_match_dist = d.params.saved_match_dist; + let mut saved_match_len = d.params.saved_match_len; + + while src_pos < in_buf.len() || (d.params.flush != TDEFLFlush::None && lookahead_size != 0) { + let src_buf_left = in_buf.len() - src_pos; + let num_bytes_to_process = cmp::min(src_buf_left, MAX_MATCH_LEN - lookahead_size); + + if lookahead_size + d.dict.size >= usize::from(MIN_MATCH_LEN) - 1 + && num_bytes_to_process > 0 + { + let dictb = &mut d.dict.b; + + let mut dst_pos = (lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK; + let mut ins_pos = lookahead_pos + lookahead_size - 2; + // Start the hash value from the first two bytes + let mut hash = update_hash( + u16::from(dictb.dict[ins_pos & LZ_DICT_SIZE_MASK]), + dictb.dict[(ins_pos + 1) & LZ_DICT_SIZE_MASK], + ); + + lookahead_size += num_bytes_to_process; + + for &c in &in_buf[src_pos..src_pos + num_bytes_to_process] { + // Add byte to input buffer. + dictb.dict[dst_pos] = c; + if dst_pos < MAX_MATCH_LEN - 1 { + dictb.dict[LZ_DICT_SIZE + dst_pos] = c; + } + + // Generate hash from the current byte, + hash = update_hash(hash, c); + dictb.next[ins_pos & LZ_DICT_SIZE_MASK] = dictb.hash[hash as usize]; + // and insert it into the hash chain. + dictb.hash[hash as usize] = ins_pos as u16; + dst_pos = (dst_pos + 1) & LZ_DICT_SIZE_MASK; + ins_pos += 1; + } + src_pos += num_bytes_to_process; + } else { + let dictb = &mut d.dict.b; + for &c in &in_buf[src_pos..src_pos + num_bytes_to_process] { + let dst_pos = (lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK; + dictb.dict[dst_pos] = c; + if dst_pos < MAX_MATCH_LEN - 1 { + dictb.dict[LZ_DICT_SIZE + dst_pos] = c; + } + + lookahead_size += 1; + if lookahead_size + d.dict.size >= MIN_MATCH_LEN.into() { + let ins_pos = lookahead_pos + lookahead_size - 3; + let hash = ((u32::from(dictb.dict[ins_pos & LZ_DICT_SIZE_MASK]) + << (LZ_HASH_SHIFT * 2)) + ^ ((u32::from(dictb.dict[(ins_pos + 1) & LZ_DICT_SIZE_MASK]) + << LZ_HASH_SHIFT) + ^ u32::from(c))) + & (LZ_HASH_SIZE as u32 - 1); + + dictb.next[ins_pos & LZ_DICT_SIZE_MASK] = dictb.hash[hash as usize]; + dictb.hash[hash as usize] = ins_pos as u16; + } + } + + src_pos += num_bytes_to_process; + } + + d.dict.size = cmp::min(LZ_DICT_SIZE - lookahead_size, d.dict.size); + if d.params.flush == TDEFLFlush::None && lookahead_size < MAX_MATCH_LEN { + break; + } + + let mut len_to_move = 1; + let mut cur_match_dist = 0; + let mut cur_match_len = if saved_match_len != 0 { + saved_match_len + } else { + u32::from(MIN_MATCH_LEN) - 1 + }; + let cur_pos = lookahead_pos & LZ_DICT_SIZE_MASK; + if d.params.flags & (TDEFL_RLE_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS) != 0 { + // If TDEFL_RLE_MATCHES is set, we only look for repeating sequences of the current byte. + if d.dict.size != 0 && d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS == 0 { + let c = d.dict.b.dict[(cur_pos.wrapping_sub(1)) & LZ_DICT_SIZE_MASK]; + cur_match_len = d.dict.b.dict[cur_pos..(cur_pos + lookahead_size)] + .iter() + .take_while(|&x| *x == c) + .count() as u32; + if cur_match_len < MIN_MATCH_LEN.into() { + cur_match_len = 0 + } else { + cur_match_dist = 1 + } + } + } else { + // Try to find a match for the bytes at the current position. + let dist_len = d.dict.find_match( + lookahead_pos, + d.dict.size, + lookahead_size as u32, + cur_match_dist, + cur_match_len, + ); + cur_match_dist = dist_len.0; + cur_match_len = dist_len.1; + } + + let far_and_small = cur_match_len == MIN_MATCH_LEN.into() && cur_match_dist >= 8 * 1024; + let filter_small = d.params.flags & TDEFL_FILTER_MATCHES != 0 && cur_match_len <= 5; + if far_and_small || filter_small || cur_pos == cur_match_dist as usize { + cur_match_dist = 0; + cur_match_len = 0; + } + + if saved_match_len != 0 { + if cur_match_len > saved_match_len { + record_literal(&mut d.huff, &mut d.lz, saved_lit); + if cur_match_len >= 128 { + record_match(&mut d.huff, &mut d.lz, cur_match_len, cur_match_dist); + saved_match_len = 0; + len_to_move = cur_match_len as usize; + } else { + saved_lit = d.dict.b.dict[cur_pos]; + saved_match_dist = cur_match_dist; + saved_match_len = cur_match_len; + } + } else { + record_match(&mut d.huff, &mut d.lz, saved_match_len, saved_match_dist); + len_to_move = (saved_match_len - 1) as usize; + saved_match_len = 0; + } + } else if cur_match_dist == 0 { + record_literal( + &mut d.huff, + &mut d.lz, + d.dict.b.dict[cmp::min(cur_pos, d.dict.b.dict.len() - 1)], + ); + } else if d.params.greedy_parsing + || (d.params.flags & TDEFL_RLE_MATCHES != 0) + || cur_match_len >= 128 + { + // If we are using lazy matching, check for matches at the next byte if the current + // match was shorter than 128 bytes. + record_match(&mut d.huff, &mut d.lz, cur_match_len, cur_match_dist); + len_to_move = cur_match_len as usize; + } else { + saved_lit = d.dict.b.dict[cmp::min(cur_pos, d.dict.b.dict.len() - 1)]; + saved_match_dist = cur_match_dist; + saved_match_len = cur_match_len; + } + + lookahead_pos += len_to_move; + assert!(lookahead_size >= len_to_move); + lookahead_size -= len_to_move; + d.dict.size = cmp::min(d.dict.size + len_to_move, LZ_DICT_SIZE); + + let lz_buf_tight = d.lz.code_position > LZ_CODE_BUF_SIZE - 8; + let raw = d.params.flags & TDEFL_FORCE_ALL_RAW_BLOCKS != 0; + let fat = ((d.lz.code_position * 115) >> 7) >= d.lz.total_bytes as usize; + let fat_or_raw = (d.lz.total_bytes > 31 * 1024) && (fat || raw); + + if lz_buf_tight || fat_or_raw { + d.params.src_pos = src_pos; + // These values are used in flush_block, so we need to write them back here. + d.dict.lookahead_size = lookahead_size; + d.dict.lookahead_pos = lookahead_pos; + + let n = flush_block(d, callback, TDEFLFlush::None) + .unwrap_or(TDEFLStatus::PutBufFailed as i32); + if n != 0 { + d.params.saved_lit = saved_lit; + d.params.saved_match_dist = saved_match_dist; + d.params.saved_match_len = saved_match_len; + return n > 0; + } + } + } + + d.params.src_pos = src_pos; + d.dict.lookahead_size = lookahead_size; + d.dict.lookahead_pos = lookahead_pos; + d.params.saved_lit = saved_lit; + d.params.saved_match_dist = saved_match_dist; + d.params.saved_match_len = saved_match_len; + true +} + +const COMP_FAST_LOOKAHEAD_SIZE: usize = 4096; + +fn compress_fast(d: &mut CompressorOxide, callback: &mut CallbackOxide) -> bool { + let mut src_pos = d.params.src_pos; + let mut lookahead_size = d.dict.lookahead_size; + let mut lookahead_pos = d.dict.lookahead_pos; + + let mut cur_pos = lookahead_pos & LZ_DICT_SIZE_MASK; + let in_buf = match callback.in_buf { + None => return true, + Some(in_buf) => in_buf, + }; + + debug_assert!(d.lz.code_position < LZ_CODE_BUF_SIZE - 2); + + while src_pos < in_buf.len() || (d.params.flush != TDEFLFlush::None && lookahead_size > 0) { + let mut dst_pos = (lookahead_pos + lookahead_size) & LZ_DICT_SIZE_MASK; + let mut num_bytes_to_process = cmp::min( + in_buf.len() - src_pos, + COMP_FAST_LOOKAHEAD_SIZE - lookahead_size, + ); + lookahead_size += num_bytes_to_process; + + while num_bytes_to_process != 0 { + let n = cmp::min(LZ_DICT_SIZE - dst_pos, num_bytes_to_process); + d.dict.b.dict[dst_pos..dst_pos + n].copy_from_slice(&in_buf[src_pos..src_pos + n]); + + if dst_pos < MAX_MATCH_LEN - 1 { + let m = cmp::min(n, MAX_MATCH_LEN - 1 - dst_pos); + d.dict.b.dict[dst_pos + LZ_DICT_SIZE..dst_pos + LZ_DICT_SIZE + m] + .copy_from_slice(&in_buf[src_pos..src_pos + m]); + } + + src_pos += n; + dst_pos = (dst_pos + n) & LZ_DICT_SIZE_MASK; + num_bytes_to_process -= n; + } + + d.dict.size = cmp::min(LZ_DICT_SIZE - lookahead_size, d.dict.size); + if d.params.flush == TDEFLFlush::None && lookahead_size < COMP_FAST_LOOKAHEAD_SIZE { + break; + } + + while lookahead_size >= 4 { + let mut cur_match_len = 1; + + let first_trigram = d.dict.read_unaligned_u32(cur_pos) & 0xFF_FFFF; + + let hash = (first_trigram ^ (first_trigram >> (24 - (LZ_HASH_BITS - 8)))) + & LEVEL1_HASH_SIZE_MASK; + + let mut probe_pos = usize::from(d.dict.b.hash[hash as usize]); + d.dict.b.hash[hash as usize] = lookahead_pos as u16; + + let mut cur_match_dist = (lookahead_pos - probe_pos) as u16; + if cur_match_dist as usize <= d.dict.size { + probe_pos &= LZ_DICT_SIZE_MASK; + + let trigram = d.dict.read_unaligned_u32(probe_pos) & 0xFF_FFFF; + + if first_trigram == trigram { + // Trigram was tested, so we can start with "+ 3" displacement. + let mut p = cur_pos + 3; + let mut q = probe_pos + 3; + cur_match_len = (|| { + for _ in 0..32 { + let p_data: u64 = d.dict.read_unaligned_u64(p); + let q_data: u64 = d.dict.read_unaligned_u64(q); + let xor_data = p_data ^ q_data; + if xor_data == 0 { + p += 8; + q += 8; + } else { + let trailing = xor_data.trailing_zeros(); + return p as u32 - cur_pos as u32 + (trailing >> 3); + } + } + + if cur_match_dist == 0 { + 0 + } else { + MAX_MATCH_LEN as u32 + } + })(); + + if cur_match_len < MIN_MATCH_LEN.into() + || (cur_match_len == MIN_MATCH_LEN.into() && cur_match_dist >= 8 * 1024) + { + let lit = first_trigram as u8; + cur_match_len = 1; + d.lz.write_code(lit); + *d.lz.get_flag() >>= 1; + d.huff.count[0][lit as usize] += 1; + } else { + // Limit the match to the length of the lookahead so we don't create a match + // that ends after the end of the input data. + cur_match_len = cmp::min(cur_match_len, lookahead_size as u32); + debug_assert!(cur_match_len >= MIN_MATCH_LEN.into()); + debug_assert!(cur_match_dist >= 1); + debug_assert!(cur_match_dist as usize <= LZ_DICT_SIZE); + cur_match_dist -= 1; + + d.lz.write_code((cur_match_len - u32::from(MIN_MATCH_LEN)) as u8); + d.lz.write_code(cur_match_dist as u8); + d.lz.write_code((cur_match_dist >> 8) as u8); + + *d.lz.get_flag() >>= 1; + *d.lz.get_flag() |= 0x80; + if cur_match_dist < 512 { + d.huff.count[1][SMALL_DIST_SYM[cur_match_dist as usize] as usize] += 1; + } else { + d.huff.count[1] + [LARGE_DIST_SYM[(cur_match_dist >> 8) as usize] as usize] += 1; + } + + d.huff.count[0][LEN_SYM[(cur_match_len - u32::from(MIN_MATCH_LEN)) as usize] + as usize] += 1; + } + } else { + d.lz.write_code(first_trigram as u8); + *d.lz.get_flag() >>= 1; + d.huff.count[0][first_trigram as u8 as usize] += 1; + } + + d.lz.consume_flag(); + d.lz.total_bytes += cur_match_len; + lookahead_pos += cur_match_len as usize; + d.dict.size = cmp::min(d.dict.size + cur_match_len as usize, LZ_DICT_SIZE); + cur_pos = (cur_pos + cur_match_len as usize) & LZ_DICT_SIZE_MASK; + lookahead_size -= cur_match_len as usize; + + if d.lz.code_position > LZ_CODE_BUF_SIZE - 8 { + // These values are used in flush_block, so we need to write them back here. + d.dict.lookahead_size = lookahead_size; + d.dict.lookahead_pos = lookahead_pos; + + let n = match flush_block(d, callback, TDEFLFlush::None) { + Err(_) => { + d.params.src_pos = src_pos; + d.params.prev_return_status = TDEFLStatus::PutBufFailed; + return false; + } + Ok(status) => status, + }; + if n != 0 { + d.params.src_pos = src_pos; + return n > 0; + } + debug_assert!(d.lz.code_position < LZ_CODE_BUF_SIZE - 2); + + lookahead_size = d.dict.lookahead_size; + lookahead_pos = d.dict.lookahead_pos; + } + } + } + + while lookahead_size != 0 { + let lit = d.dict.b.dict[cur_pos]; + d.lz.total_bytes += 1; + d.lz.write_code(lit); + *d.lz.get_flag() >>= 1; + d.lz.consume_flag(); + + d.huff.count[0][lit as usize] += 1; + lookahead_pos += 1; + d.dict.size = cmp::min(d.dict.size + 1, LZ_DICT_SIZE); + cur_pos = (cur_pos + 1) & LZ_DICT_SIZE_MASK; + lookahead_size -= 1; + + if d.lz.code_position > LZ_CODE_BUF_SIZE - 8 { + // These values are used in flush_block, so we need to write them back here. + d.dict.lookahead_size = lookahead_size; + d.dict.lookahead_pos = lookahead_pos; + + let n = match flush_block(d, callback, TDEFLFlush::None) { + Err(_) => { + d.params.prev_return_status = TDEFLStatus::PutBufFailed; + d.params.src_pos = src_pos; + return false; + } + Ok(status) => status, + }; + if n != 0 { + d.params.src_pos = src_pos; + return n > 0; + } + + lookahead_size = d.dict.lookahead_size; + lookahead_pos = d.dict.lookahead_pos; + } + } + } + + d.params.src_pos = src_pos; + d.dict.lookahead_size = lookahead_size; + d.dict.lookahead_pos = lookahead_pos; + true +} + +fn flush_output_buffer(c: &mut CallbackOxide, p: &mut ParamsOxide) -> (TDEFLStatus, usize, usize) { + let mut res = (TDEFLStatus::Okay, p.src_pos, 0); + if let CallbackOut::Buf(ref mut cb) = c.out { + let n = cmp::min(cb.out_buf.len() - p.out_buf_ofs, p.flush_remaining as usize); + if n != 0 { + cb.out_buf[p.out_buf_ofs..p.out_buf_ofs + n] + .copy_from_slice(&p.local_buf.b[p.flush_ofs as usize..p.flush_ofs as usize + n]); + } + p.flush_ofs += n as u32; + p.flush_remaining -= n as u32; + p.out_buf_ofs += n; + res.2 = p.out_buf_ofs; + } + + if p.finished && p.flush_remaining == 0 { + res.0 = TDEFLStatus::Done + } + res +} + +/// Main compression function. Tries to compress as much as possible from `in_buf` and +/// puts compressed output into `out_buf`. +/// +/// The value of `flush` determines if the compressor should attempt to flush all output +/// and alternatively try to finish the stream. +/// +/// Use [`TDEFLFlush::Finish`] on the final call to signal that the stream is finishing. +/// +/// Note that this function does not keep track of whether a flush marker has been output, so +/// if called using [`TDEFLFlush::Sync`], the caller needs to ensure there is enough space in the +/// output buffer if they want to avoid repeated flush markers. +/// See #105 for details. +/// +/// # Returns +/// Returns a tuple containing the current status of the compressor, the current position +/// in the input buffer and the current position in the output buffer. +pub fn compress( + d: &mut CompressorOxide, + in_buf: &[u8], + out_buf: &mut [u8], + flush: TDEFLFlush, +) -> (TDEFLStatus, usize, usize) { + compress_inner( + d, + &mut CallbackOxide::new_callback_buf(in_buf, out_buf), + flush, + ) +} + +/// Main compression function. Callbacks output. +/// +/// # Returns +/// Returns a tuple containing the current status of the compressor, the current position +/// in the input buffer. +/// +/// The caller is responsible for ensuring the `CallbackFunc` struct will not cause undefined +/// behaviour. +pub fn compress_to_output( + d: &mut CompressorOxide, + in_buf: &[u8], + flush: TDEFLFlush, + mut callback_func: impl FnMut(&[u8]) -> bool, +) -> (TDEFLStatus, usize) { + let res = compress_inner( + d, + &mut CallbackOxide::new_callback_func( + in_buf, + CallbackFunc { + put_buf_func: &mut callback_func, + }, + ), + flush, + ); + + (res.0, res.1) +} + +fn compress_inner( + d: &mut CompressorOxide, + callback: &mut CallbackOxide, + flush: TDEFLFlush, +) -> (TDEFLStatus, usize, usize) { + d.params.out_buf_ofs = 0; + d.params.src_pos = 0; + + let prev_ok = d.params.prev_return_status == TDEFLStatus::Okay; + let flush_finish_once = d.params.flush != TDEFLFlush::Finish || flush == TDEFLFlush::Finish; + + d.params.flush = flush; + if !prev_ok || !flush_finish_once { + d.params.prev_return_status = TDEFLStatus::BadParam; + return (d.params.prev_return_status, 0, 0); + } + + if d.params.flush_remaining != 0 || d.params.finished { + let res = flush_output_buffer(callback, &mut d.params); + d.params.prev_return_status = res.0; + return res; + } + + let one_probe = d.params.flags & MAX_PROBES_MASK as u32 == 1; + let greedy = d.params.flags & TDEFL_GREEDY_PARSING_FLAG != 0; + let filter_or_rle_or_raw = d.params.flags + & (TDEFL_FILTER_MATCHES | TDEFL_FORCE_ALL_RAW_BLOCKS | TDEFL_RLE_MATCHES) + != 0; + + let compress_success = if one_probe && greedy && !filter_or_rle_or_raw { + compress_fast(d, callback) + } else { + compress_normal(d, callback) + }; + + if !compress_success { + return ( + d.params.prev_return_status, + d.params.src_pos, + d.params.out_buf_ofs, + ); + } + + if let Some(in_buf) = callback.in_buf { + if d.params.flags & (TDEFL_WRITE_ZLIB_HEADER | TDEFL_COMPUTE_ADLER32) != 0 { + d.params.adler32 = update_adler32(d.params.adler32, &in_buf[..d.params.src_pos]); + } + } + + let flush_none = d.params.flush == TDEFLFlush::None; + let in_left = callback.in_buf.map_or(0, |buf| buf.len()) - d.params.src_pos; + let remaining = in_left != 0 || d.params.flush_remaining != 0; + if !flush_none && d.dict.lookahead_size == 0 && !remaining { + let flush = d.params.flush; + match flush_block(d, callback, flush) { + Err(_) => { + d.params.prev_return_status = TDEFLStatus::PutBufFailed; + return ( + d.params.prev_return_status, + d.params.src_pos, + d.params.out_buf_ofs, + ); + } + Ok(x) if x < 0 => { + return ( + d.params.prev_return_status, + d.params.src_pos, + d.params.out_buf_ofs, + ) + } + _ => { + d.params.finished = d.params.flush == TDEFLFlush::Finish; + if d.params.flush == TDEFLFlush::Full { + memset(&mut d.dict.b.hash[..], 0); + memset(&mut d.dict.b.next[..], 0); + d.dict.size = 0; + } + } + } + } + + let res = flush_output_buffer(callback, &mut d.params); + d.params.prev_return_status = res.0; + + res +} + +/// Create a set of compression flags using parameters used by zlib and other compressors. +/// Mainly intended for use with transition from c libraries as it deals with raw integers. +/// +/// # Parameters +/// `level` determines compression level. Clamped to maximum of 10. Negative values result in +/// `CompressionLevel::DefaultLevel`. +/// `window_bits`: Above 0, wraps the stream in a zlib wrapper, 0 or negative for a raw deflate +/// stream. +/// `strategy`: Sets the strategy if this conforms to any of the values in `CompressionStrategy`. +/// +/// # Notes +/// This function may be removed or moved to the `miniz_oxide_c_api` in the future. +pub fn create_comp_flags_from_zip_params(level: i32, window_bits: i32, strategy: i32) -> u32 { + let num_probes = (if level >= 0 { + cmp::min(10, level) + } else { + CompressionLevel::DefaultLevel as i32 + }) as usize; + let greedy = if level <= 3 { + TDEFL_GREEDY_PARSING_FLAG + } else { + 0 + }; + let mut comp_flags = NUM_PROBES[num_probes] | greedy; + + if window_bits > 0 { + comp_flags |= TDEFL_WRITE_ZLIB_HEADER; + } + + if level == 0 { + comp_flags |= TDEFL_FORCE_ALL_RAW_BLOCKS; + } else if strategy == CompressionStrategy::Filtered as i32 { + comp_flags |= TDEFL_FILTER_MATCHES; + } else if strategy == CompressionStrategy::HuffmanOnly as i32 { + comp_flags &= !MAX_PROBES_MASK as u32; + } else if strategy == CompressionStrategy::Fixed as i32 { + comp_flags |= TDEFL_FORCE_ALL_STATIC_BLOCKS; + } else if strategy == CompressionStrategy::RLE as i32 { + comp_flags |= TDEFL_RLE_MATCHES; + } + + comp_flags +} + +#[cfg(test)] +mod test { + use super::{ + compress_to_output, create_comp_flags_from_zip_params, read_u16_le, write_u16_le, + CompressionStrategy, CompressorOxide, TDEFLFlush, TDEFLStatus, DEFAULT_FLAGS, + MZ_DEFAULT_WINDOW_BITS, + }; + use crate::inflate::decompress_to_vec; + use alloc::vec; + + #[test] + fn u16_to_slice() { + let mut slice = [0, 0]; + write_u16_le(2000, &mut slice, 0); + assert_eq!(slice, [208, 7]); + } + + #[test] + fn u16_from_slice() { + let slice = [208, 7]; + assert_eq!(read_u16_le(&slice, 0), 2000); + } + + #[test] + fn compress_output() { + assert_eq!( + DEFAULT_FLAGS, + create_comp_flags_from_zip_params( + 4, + MZ_DEFAULT_WINDOW_BITS, + CompressionStrategy::Default as i32 + ) + ); + + let slice = [ + 1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 6, 1, 2, 3, 1, 2, 3, 2, 3, 1, 2, 3, + ]; + let mut encoded = vec![]; + let flags = create_comp_flags_from_zip_params(6, 0, 0); + let mut d = CompressorOxide::new(flags); + let (status, in_consumed) = + compress_to_output(&mut d, &slice, TDEFLFlush::Finish, |out: &[u8]| { + encoded.extend_from_slice(out); + true + }); + + assert_eq!(status, TDEFLStatus::Done); + assert_eq!(in_consumed, slice.len()); + + let decoded = decompress_to_vec(&encoded[..]).unwrap(); + assert_eq!(&decoded[..], &slice[..]); + } + + #[test] + /// Check fast compress mode + fn compress_fast() { + let slice = [ + 1, 2, 3, 4, 1, 2, 3, 1, 2, 3, 1, 2, 6, 1, 2, 3, 1, 2, 3, 2, 3, 1, 2, 3, + ]; + let mut encoded = vec![]; + let flags = create_comp_flags_from_zip_params(1, 0, 0); + let mut d = CompressorOxide::new(flags); + let (status, in_consumed) = + compress_to_output(&mut d, &slice, TDEFLFlush::Finish, |out: &[u8]| { + encoded.extend_from_slice(out); + true + }); + + assert_eq!(status, TDEFLStatus::Done); + assert_eq!(in_consumed, slice.len()); + + // Needs to be altered if algorithm improves. + assert_eq!( + &encoded[..], + [99, 100, 98, 102, 1, 98, 48, 98, 3, 147, 204, 76, 204, 140, 76, 204, 0] + ); + + let decoded = decompress_to_vec(&encoded[..]).unwrap(); + assert_eq!(&decoded[..], &slice[..]); + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/mod.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/mod.rs new file mode 100644 index 0000000..f36f28c --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/mod.rs
@@ -0,0 +1,226 @@ +//! This module contains functionality for compression. + +use crate::alloc::vec; +use crate::alloc::vec::Vec; + +mod buffer; +pub mod core; +pub mod stream; +use self::core::*; + +/// How much processing the compressor should do to compress the data. +/// `NoCompression` and `Bestspeed` have special meanings, the other levels determine the number +/// of checks for matches in the hash chains and whether to use lazy or greedy parsing. +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum CompressionLevel { + /// Don't do any compression, only output uncompressed blocks. + NoCompression = 0, + /// Fast compression. Uses a special compression routine that is optimized for speed. + BestSpeed = 1, + /// Slow/high compression. Do a lot of checks to try to find good matches. + BestCompression = 9, + /// Even more checks, can be very slow. + UberCompression = 10, + /// Default compromise between speed and compression. + DefaultLevel = 6, + /// Use the default compression level. + DefaultCompression = -1, +} + +// Missing safe rust analogue (this and mem-to-mem are quite similar) +/* +fn tdefl_compress( + d: Option<&mut CompressorOxide>, + in_buf: *const c_void, + in_size: Option<&mut usize>, + out_buf: *mut c_void, + out_size: Option<&mut usize>, + flush: TDEFLFlush, +) -> TDEFLStatus { + let res = match d { + None => { + in_size.map(|size| *size = 0); + out_size.map(|size| *size = 0); + (TDEFLStatus::BadParam, 0, 0) + }, + Some(compressor) => { + let callback_res = CallbackOxide::new( + compressor.callback_func.clone(), + in_buf, + in_size, + out_buf, + out_size, + ); + + if let Ok(mut callback) = callback_res { + let res = compress(compressor, &mut callback, flush); + callback.update_size(Some(res.1), Some(res.2)); + res + } else { + (TDEFLStatus::BadParam, 0, 0) + } + } + }; + res.0 +}*/ + +// Missing safe rust analogue +/* +fn tdefl_init( + d: Option<&mut CompressorOxide>, + put_buf_func: PutBufFuncPtr, + put_buf_user: *mut c_void, + flags: c_int, +) -> TDEFLStatus { + if let Some(d) = d { + *d = CompressorOxide::new( + put_buf_func.map(|func| + CallbackFunc { put_buf_func: func, put_buf_user: put_buf_user } + ), + flags as u32, + ); + TDEFLStatus::Okay + } else { + TDEFLStatus::BadParam + } +}*/ + +// Missing safe rust analogue (though maybe best served by flate2 front-end instead) +/* +fn tdefl_compress_mem_to_output( + buf: *const c_void, + buf_len: usize, + put_buf_func: PutBufFuncPtr, + put_buf_user: *mut c_void, + flags: c_int, +) -> bool*/ + +// Missing safe Rust analogue +/* +fn tdefl_compress_mem_to_mem( + out_buf: *mut c_void, + out_buf_len: usize, + src_buf: *const c_void, + src_buf_len: usize, + flags: c_int, +) -> usize*/ + +/// Compress the input data to a vector, using the specified compression level (0-10). +pub fn compress_to_vec(input: &[u8], level: u8) -> Vec<u8> { + compress_to_vec_inner(input, level, 0, 0) +} + +/// Compress the input data to a vector, using the specified compression level (0-10), and with a +/// zlib wrapper. +pub fn compress_to_vec_zlib(input: &[u8], level: u8) -> Vec<u8> { + compress_to_vec_inner(input, level, 1, 0) +} + +/// Simple function to compress data to a vec. +fn compress_to_vec_inner(mut input: &[u8], level: u8, window_bits: i32, strategy: i32) -> Vec<u8> { + // The comp flags function sets the zlib flag if the window_bits parameter is > 0. + let flags = create_comp_flags_from_zip_params(level.into(), window_bits, strategy); + let mut compressor = CompressorOxide::new(flags); + let mut output = vec![0; ::core::cmp::max(input.len() / 2, 2)]; + + let mut out_pos = 0; + loop { + let (status, bytes_in, bytes_out) = compress( + &mut compressor, + input, + &mut output[out_pos..], + TDEFLFlush::Finish, + ); + out_pos += bytes_out; + + match status { + TDEFLStatus::Done => { + output.truncate(out_pos); + break; + } + TDEFLStatus::Okay if bytes_in <= input.len() => { + input = &input[bytes_in..]; + + // We need more space, so resize the vector. + if output.len().saturating_sub(out_pos) < 30 { + output.resize(output.len() * 2, 0) + } + } + // Not supposed to happen unless there is a bug. + _ => panic!("Bug! Unexpectedly failed to compress!"), + } + } + + output +} + +#[cfg(test)] +mod test { + use super::{compress_to_vec, compress_to_vec_inner, CompressionStrategy}; + use crate::inflate::decompress_to_vec; + use alloc::vec; + + /// Test deflate example. + /// + /// Check if the encoder produces the same code as the example given by Mark Adler here: + /// https://stackoverflow.com/questions/17398931/deflate-encoding-with-static-huffman-codes/17415203 + #[test] + fn compress_small() { + let test_data = b"Deflate late"; + let check = [ + 0x73, 0x49, 0x4d, 0xcb, 0x49, 0x2c, 0x49, 0x55, 0x00, 0x11, 0x00, + ]; + + let res = compress_to_vec(test_data, 1); + assert_eq!(&check[..], res.as_slice()); + + let res = compress_to_vec(test_data, 9); + assert_eq!(&check[..], res.as_slice()); + } + + #[test] + fn compress_huff_only() { + let test_data = b"Deflate late"; + + let res = compress_to_vec_inner(test_data, 1, 0, CompressionStrategy::HuffmanOnly as i32); + let d = decompress_to_vec(res.as_slice()).expect("Failed to decompress!"); + assert_eq!(test_data, d.as_slice()); + } + + /// Test that a raw block compresses fine. + #[test] + fn compress_raw() { + let text = b"Hello, zlib!"; + let encoded = { + let len = text.len(); + let notlen = !len; + let mut encoded = vec![ + 1, + len as u8, + (len >> 8) as u8, + notlen as u8, + (notlen >> 8) as u8, + ]; + encoded.extend_from_slice(&text[..]); + encoded + }; + + let res = compress_to_vec(text, 0); + assert_eq!(encoded, res.as_slice()); + } + + #[test] + fn short() { + let test_data = [10, 10, 10, 10, 10, 55]; + let c = compress_to_vec(&test_data, 9); + + let d = decompress_to_vec(c.as_slice()).expect("Failed to decompress!"); + assert_eq!(&test_data, d.as_slice()); + // Check that a static block is used here, rather than a raw block + // , so the data is actually compressed. + // (The optimal compressed length would be 5, but neither miniz nor zlib manages that either + // as neither checks matches against the byte at index 0.) + assert!(c.len() <= 6); + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/stream.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/stream.rs new file mode 100644 index 0000000..39aa82d --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/stream.rs
@@ -0,0 +1,121 @@ +//! Extra streaming compression functionality. +//! +//! As of now this is mainly intended for use to build a higher-level wrapper. +//! +//! There is no DeflateState as the needed state is contained in the compressor struct itself. + +use crate::deflate::core::{compress, CompressorOxide, TDEFLFlush, TDEFLStatus}; +use crate::{MZError, MZFlush, MZStatus, StreamResult}; + +/// Try to compress from input to output with the given [`CompressorOxide`]. +/// +/// # Errors +/// +/// Returns [`MZError::Buf`] If the size of the `output` slice is empty or no progress was made due +/// to lack of expected input data, or if called without [`MZFlush::Finish`] after the compression +/// was already finished. +/// +/// Returns [`MZError::Param`] if the compressor parameters are set wrong. +/// +/// Returns [`MZError::Stream`] when lower-level decompressor returns a +/// [`TDEFLStatus::PutBufFailed`]; may not actually be possible. +pub fn deflate( + compressor: &mut CompressorOxide, + input: &[u8], + output: &mut [u8], + flush: MZFlush, +) -> StreamResult { + if output.is_empty() { + return StreamResult::error(MZError::Buf); + } + + if compressor.prev_return_status() == TDEFLStatus::Done { + return if flush == MZFlush::Finish { + StreamResult { + bytes_written: 0, + bytes_consumed: 0, + status: Ok(MZStatus::StreamEnd), + } + } else { + StreamResult::error(MZError::Buf) + }; + } + + let mut bytes_written = 0; + let mut bytes_consumed = 0; + + let mut next_in = input; + let mut next_out = output; + + let status = loop { + let in_bytes; + let out_bytes; + let defl_status = { + let res = compress(compressor, next_in, next_out, TDEFLFlush::from(flush)); + in_bytes = res.1; + out_bytes = res.2; + res.0 + }; + + next_in = &next_in[in_bytes..]; + next_out = &mut next_out[out_bytes..]; + bytes_consumed += in_bytes; + bytes_written += out_bytes; + + // Check if we are done, or compression failed. + match defl_status { + TDEFLStatus::BadParam => break Err(MZError::Param), + // Don't think this can happen as we're not using a custom callback. + TDEFLStatus::PutBufFailed => break Err(MZError::Stream), + TDEFLStatus::Done => break Ok(MZStatus::StreamEnd), + _ => (), + }; + + // All the output space was used, so wait for more. + if next_out.is_empty() { + break Ok(MZStatus::Ok); + } + + if next_in.is_empty() && (flush != MZFlush::Finish) { + let total_changed = bytes_written > 0 || bytes_consumed > 0; + + break if (flush != MZFlush::None) || total_changed { + // We wrote or consumed something, and/or did a flush (sync/partial etc.). + Ok(MZStatus::Ok) + } else { + // No more input data, not flushing, and nothing was consumed or written, + // so couldn't make any progress. + Err(MZError::Buf) + }; + } + }; + StreamResult { + bytes_consumed, + bytes_written, + status, + } +} + +#[cfg(test)] +mod test { + use super::deflate; + use crate::deflate::CompressorOxide; + use crate::inflate::decompress_to_vec_zlib; + use crate::{MZFlush, MZStatus}; + use alloc::boxed::Box; + use alloc::vec; + + #[test] + fn test_state() { + let data = b"Hello zlib!"; + let mut compressed = vec![0; 50]; + let mut compressor = Box::<CompressorOxide>::default(); + let res = deflate(&mut compressor, data, &mut compressed, MZFlush::Finish); + let status = res.status.expect("Failed to compress!"); + let decomp = + decompress_to_vec_zlib(&compressed).expect("Failed to decompress compressed data"); + assert_eq!(status, MZStatus::StreamEnd); + assert_eq!(decomp[..], data[..]); + assert_eq!(res.bytes_consumed, data.len()); + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/core.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/core.rs new file mode 100644 index 0000000..738de236 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/core.rs
@@ -0,0 +1,2052 @@ +//! Streaming decompression functionality. + +use super::*; +use crate::shared::{update_adler32, HUFFMAN_LENGTH_ORDER}; +use ::core::cell::Cell; + +use ::core::convert::TryInto; +use ::core::{cmp, slice}; + +use self::output_buffer::OutputBuffer; + +pub const TINFL_LZ_DICT_SIZE: usize = 32_768; + +/// A struct containing huffman code lengths and the huffman code tree used by the decompressor. +struct HuffmanTable { + /// Length of the code at each index. + pub code_size: [u8; MAX_HUFF_SYMBOLS_0], + /// Fast lookup table for shorter huffman codes. + /// + /// See `HuffmanTable::fast_lookup`. + pub look_up: [i16; FAST_LOOKUP_SIZE as usize], + /// Full huffman tree. + /// + /// Positive values are edge nodes/symbols, negative values are + /// parent nodes/references to other nodes. + pub tree: [i16; MAX_HUFF_TREE_SIZE], +} + +impl HuffmanTable { + const fn new() -> HuffmanTable { + HuffmanTable { + code_size: [0; MAX_HUFF_SYMBOLS_0], + look_up: [0; FAST_LOOKUP_SIZE as usize], + tree: [0; MAX_HUFF_TREE_SIZE], + } + } + + /// Look for a symbol in the fast lookup table. + /// The symbol is stored in the lower 9 bits, the length in the next 6. + /// If the returned value is negative, the code wasn't found in the + /// fast lookup table and the full tree has to be traversed to find the code. + #[inline] + fn fast_lookup(&self, bit_buf: BitBuffer) -> i16 { + self.look_up[(bit_buf & BitBuffer::from(FAST_LOOKUP_SIZE - 1)) as usize] + } + + /// Get the symbol and the code length from the huffman tree. + #[inline] + fn tree_lookup(&self, fast_symbol: i32, bit_buf: BitBuffer, mut code_len: u32) -> (i32, u32) { + let mut symbol = fast_symbol; + // We step through the tree until we encounter a positive value, which indicates a + // symbol. + loop { + // symbol here indicates the position of the left (0) node, if the next bit is 1 + // we add 1 to the lookup position to get the right node. + let tree_index = (!symbol + ((bit_buf >> code_len) & 1) as i32) as usize; + debug_assert!(tree_index < self.tree.len()); + if tree_index >= self.tree.len() { + break; + } + symbol = i32::from(self.tree[tree_index]); + code_len += 1; + if symbol >= 0 { + break; + } + } + (symbol, code_len) + } + + #[inline] + /// Look up a symbol and code length from the bits in the provided bit buffer. + /// + /// Returns Some(symbol, length) on success, + /// None if the length is 0. + /// + /// It's possible we could avoid checking for 0 if we can guarantee a sane table. + /// TODO: Check if a smaller type for code_len helps performance. + fn lookup(&self, bit_buf: BitBuffer) -> Option<(i32, u32)> { + let symbol = self.fast_lookup(bit_buf).into(); + if symbol >= 0 { + if (symbol >> 9) as u32 != 0 { + Some((symbol, (symbol >> 9) as u32)) + } else { + // Zero-length code. + None + } + } else { + // We didn't get a symbol from the fast lookup table, so check the tree instead. + Some(self.tree_lookup(symbol, bit_buf, FAST_LOOKUP_BITS.into())) + } + } +} + +/// The number of huffman tables used. +const MAX_HUFF_TABLES: usize = 3; +/// The length of the first (literal/length) huffman table. +const MAX_HUFF_SYMBOLS_0: usize = 288; +/// The length of the second (distance) huffman table. +const MAX_HUFF_SYMBOLS_1: usize = 32; +/// The length of the last (huffman code length) huffman table. +const _MAX_HUFF_SYMBOLS_2: usize = 19; +/// The maximum length of a code that can be looked up in the fast lookup table. +const FAST_LOOKUP_BITS: u8 = 10; +/// The size of the fast lookup table. +const FAST_LOOKUP_SIZE: u32 = 1 << FAST_LOOKUP_BITS; +const MAX_HUFF_TREE_SIZE: usize = MAX_HUFF_SYMBOLS_0 * 2; +const LITLEN_TABLE: usize = 0; +const DIST_TABLE: usize = 1; +const HUFFLEN_TABLE: usize = 2; + +/// Flags to [`decompress()`] to control how inflation works. +/// +/// These define bits for a bitmask argument. +pub mod inflate_flags { + /// Should we try to parse a zlib header? + /// + /// If unset, the function will expect an RFC1951 deflate stream. If set, it will expect a + /// RFC1950 zlib wrapper around the deflate stream. + pub const TINFL_FLAG_PARSE_ZLIB_HEADER: u32 = 1; + + /// There will be more input that hasn't been given to the decompressor yet. + /// + /// This is useful when you want to decompress what you have so far, + /// even if you know there is probably more input that hasn't gotten here yet (_e.g._, over a + /// network connection). When [`decompress()`][super::decompress] reaches the end of the input + /// without finding the end of the compressed stream, it will return + /// [`TINFLStatus::NeedsMoreInput`][super::TINFLStatus::NeedsMoreInput] if this is set, + /// indicating that you should get more data before calling again. If not set, it will return + /// [`TINFLStatus::FailedCannotMakeProgress`][super::TINFLStatus::FailedCannotMakeProgress] + /// suggesting the stream is corrupt, since you claimed it was all there. + pub const TINFL_FLAG_HAS_MORE_INPUT: u32 = 2; + + /// The output buffer should not wrap around. + pub const TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF: u32 = 4; + + /// Calculate the adler32 checksum of the output data even if we're not inflating a zlib stream. + /// + /// If [`TINFL_FLAG_IGNORE_ADLER32`] is specified, it will override this. + /// + /// NOTE: Enabling/disabling this between calls to decompress will result in an incorrect + /// checksum. + pub const TINFL_FLAG_COMPUTE_ADLER32: u32 = 8; + + /// Ignore adler32 checksum even if we are inflating a zlib stream. + /// + /// Overrides [`TINFL_FLAG_COMPUTE_ADLER32`] if both are enabled. + /// + /// NOTE: This flag does not exist in miniz as it does not support this and is a + /// custom addition for miniz_oxide. + /// + /// NOTE: Should not be changed from enabled to disabled after decompression has started, + /// this will result in checksum failure (outside the unlikely event where the checksum happens + /// to match anyway). + pub const TINFL_FLAG_IGNORE_ADLER32: u32 = 64; +} + +use self::inflate_flags::*; + +const MIN_TABLE_SIZES: [u16; 3] = [257, 1, 4]; + +#[cfg(target_pointer_width = "64")] +type BitBuffer = u64; + +#[cfg(not(target_pointer_width = "64"))] +type BitBuffer = u32; + +/// Main decompression struct. +/// +pub struct DecompressorOxide { + /// Current state of the decompressor. + state: core::State, + /// Number of bits in the bit buffer. + num_bits: u32, + /// Zlib CMF + z_header0: u32, + /// Zlib FLG + z_header1: u32, + /// Adler32 checksum from the zlib header. + z_adler32: u32, + /// 1 if the current block is the last block, 0 otherwise. + finish: u32, + /// The type of the current block. + block_type: u32, + /// 1 if the adler32 value should be checked. + check_adler32: u32, + /// Last match distance. + dist: u32, + /// Variable used for match length, symbols, and a number of other things. + counter: u32, + /// Number of extra bits for the last length or distance code. + num_extra: u32, + /// Number of entries in each huffman table. + table_sizes: [u32; MAX_HUFF_TABLES], + /// Buffer of input data. + bit_buf: BitBuffer, + /// Huffman tables. + tables: [HuffmanTable; MAX_HUFF_TABLES], + /// Raw block header. + raw_header: [u8; 4], + /// Huffman length codes. + len_codes: [u8; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1 + 137], +} + +impl DecompressorOxide { + /// Create a new tinfl_decompressor with all fields set to 0. + pub fn new() -> DecompressorOxide { + DecompressorOxide::default() + } + + /// Set the current state to `Start`. + #[inline] + pub fn init(&mut self) { + // The rest of the data is reset or overwritten when used. + self.state = core::State::Start; + } + + /// Returns the adler32 checksum of the currently decompressed data. + /// Note: Will return Some(1) if decompressing zlib but ignoring adler32. + #[inline] + pub fn adler32(&self) -> Option<u32> { + if self.state != State::Start && !self.state.is_failure() && self.z_header0 != 0 { + Some(self.check_adler32) + } else { + None + } + } + + /// Returns the adler32 that was read from the zlib header if it exists. + #[inline] + pub fn adler32_header(&self) -> Option<u32> { + if self.state != State::Start && self.state != State::BadZlibHeader && self.z_header0 != 0 { + Some(self.z_adler32) + } else { + None + } + } +} + +impl Default for DecompressorOxide { + /// Create a new tinfl_decompressor with all fields set to 0. + #[inline(always)] + fn default() -> Self { + DecompressorOxide { + state: core::State::Start, + num_bits: 0, + z_header0: 0, + z_header1: 0, + z_adler32: 0, + finish: 0, + block_type: 0, + check_adler32: 0, + dist: 0, + counter: 0, + num_extra: 0, + table_sizes: [0; MAX_HUFF_TABLES], + bit_buf: 0, + // TODO:(oyvindln) Check that copies here are optimized out in release mode. + tables: [ + HuffmanTable::new(), + HuffmanTable::new(), + HuffmanTable::new(), + ], + raw_header: [0; 4], + len_codes: [0; MAX_HUFF_SYMBOLS_0 + MAX_HUFF_SYMBOLS_1 + 137], + } + } +} + +#[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[non_exhaustive] +enum State { + Start = 0, + ReadZlibCmf, + ReadZlibFlg, + ReadBlockHeader, + BlockTypeNoCompression, + RawHeader, + RawMemcpy1, + RawMemcpy2, + ReadTableSizes, + ReadHufflenTableCodeSize, + ReadLitlenDistTablesCodeSize, + ReadExtraBitsCodeSize, + DecodeLitlen, + WriteSymbol, + ReadExtraBitsLitlen, + DecodeDistance, + ReadExtraBitsDistance, + RawReadFirstByte, + RawStoreFirstByte, + WriteLenBytesToEnd, + BlockDone, + HuffDecodeOuterLoop1, + HuffDecodeOuterLoop2, + ReadAdler32, + + DoneForever, + + // Failure states. + BlockTypeUnexpected, + BadCodeSizeSum, + BadDistOrLiteralTableLength, + BadTotalSymbols, + BadZlibHeader, + DistanceOutOfBounds, + BadRawLength, + BadCodeSizeDistPrevLookup, + InvalidLitlen, + InvalidDist, + InvalidCodeLen, +} + +impl State { + const fn is_failure(self) -> bool { + matches!( + self, + BlockTypeUnexpected + | BadCodeSizeSum + | BadDistOrLiteralTableLength + | BadTotalSymbols + | BadZlibHeader + | DistanceOutOfBounds + | BadRawLength + | BadCodeSizeDistPrevLookup + | InvalidLitlen + | InvalidDist + ) + } + + #[inline] + fn begin(&mut self, new_state: State) { + *self = new_state; + } +} + +use self::State::*; + +// Not sure why miniz uses 32-bit values for these, maybe alignment/cache again? +// # Optimization +// We add a extra value at the end and make the tables 32 elements long +// so we can use a mask to avoid bounds checks. +// The invalid values are set to something high enough to avoid underflowing +// the match length. +/// Base length for each length code. +/// +/// The base is used together with the value of the extra bits to decode the actual +/// length/distance values in a match. +#[rustfmt::skip] +const LENGTH_BASE: [u16; 32] = [ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 512, 512, 512 +]; + +/// Number of extra bits for each length code. +#[rustfmt::skip] +const LENGTH_EXTRA: [u8; 32] = [ + 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, + 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 0, 0, 0 +]; + +/// Base length for each distance code. +#[rustfmt::skip] +const DIST_BASE: [u16; 32] = [ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, + 49, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, + 2049, 3073, 4097, 6145, 8193, 12_289, 16_385, 24_577, 32_768, 32_768 +]; + +/// Number of extra bits for each distance code. +#[rustfmt::skip] +const DIST_EXTRA: [u8; 32] = [ + 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, 13 +]; + +/// The mask used when indexing the base/extra arrays. +const BASE_EXTRA_MASK: usize = 32 - 1; + +/// Sets the value of all the elements of the slice to `val`. +#[inline] +fn memset<T: Copy>(slice: &mut [T], val: T) { + for x in slice { + *x = val + } +} + +/// Read an le u16 value from the slice iterator. +/// +/// # Panics +/// Panics if there are less than two bytes left. +#[inline] +fn read_u16_le(iter: &mut slice::Iter<u8>) -> u16 { + let ret = { + let two_bytes = iter.as_ref()[..2].try_into().unwrap(); + u16::from_le_bytes(two_bytes) + }; + iter.nth(1); + ret +} + +/// Read an le u32 value from the slice iterator. +/// +/// # Panics +/// Panics if there are less than four bytes left. +#[inline(always)] +#[cfg(target_pointer_width = "64")] +fn read_u32_le(iter: &mut slice::Iter<u8>) -> u32 { + let ret = { + let four_bytes: [u8; 4] = iter.as_ref()[..4].try_into().unwrap(); + u32::from_le_bytes(four_bytes) + }; + iter.nth(3); + ret +} + +/// Ensure that there is data in the bit buffer. +/// +/// On 64-bit platform, we use a 64-bit value so this will +/// result in there being at least 32 bits in the bit buffer. +/// This function assumes that there is at least 4 bytes left in the input buffer. +#[inline(always)] +#[cfg(target_pointer_width = "64")] +fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>) { + // Read four bytes into the buffer at once. + if l.num_bits < 30 { + l.bit_buf |= BitBuffer::from(read_u32_le(in_iter)) << l.num_bits; + l.num_bits += 32; + } +} + +/// Same as previous, but for non-64-bit platforms. +/// Ensures at least 16 bits are present, requires at least 2 bytes in the in buffer. +#[inline(always)] +#[cfg(not(target_pointer_width = "64"))] +fn fill_bit_buffer(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>) { + // If the buffer is 32-bit wide, read 2 bytes instead. + if l.num_bits < 15 { + l.bit_buf |= BitBuffer::from(read_u16_le(in_iter)) << l.num_bits; + l.num_bits += 16; + } +} + +/// Check that the zlib header is correct and that there is enough space in the buffer +/// for the window size specified in the header. +/// +/// See https://tools.ietf.org/html/rfc1950 +#[inline] +const fn validate_zlib_header(cmf: u32, flg: u32, flags: u32, mask: usize) -> Action { + let mut failed = + // cmf + flg should be divisible by 31. + (((cmf * 256) + flg) % 31 != 0) || + // If this flag is set, a dictionary was used for this zlib compressed data. + // This is currently not supported by miniz or miniz-oxide + ((flg & 0b0010_0000) != 0) || + // Compression method. Only 8(DEFLATE) is defined by the standard. + ((cmf & 15) != 8); + + let window_size = 1 << ((cmf >> 4) + 8); + if (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF) == 0 { + // Bail if the buffer is wrapping and the window size is larger than the buffer. + failed |= (mask + 1) < window_size; + } + + // Zlib doesn't allow window sizes above 32 * 1024. + failed |= window_size > 32_768; + + if failed { + Action::Jump(BadZlibHeader) + } else { + Action::Jump(ReadBlockHeader) + } +} + +enum Action { + None, + Jump(State), + End(TINFLStatus), +} + +/// Try to decode the next huffman code, and puts it in the counter field of the decompressor +/// if successful. +/// +/// # Returns +/// The specified action returned from `f` on success, +/// `Action::End` if there are not enough data left to decode a symbol. +fn decode_huffman_code<F>( + r: &mut DecompressorOxide, + l: &mut LocalVars, + table: usize, + flags: u32, + in_iter: &mut slice::Iter<u8>, + f: F, +) -> Action +where + F: FnOnce(&mut DecompressorOxide, &mut LocalVars, i32) -> Action, +{ + // As the huffman codes can be up to 15 bits long we need at least 15 bits + // ready in the bit buffer to start decoding the next huffman code. + if l.num_bits < 15 { + // First, make sure there is enough data in the bit buffer to decode a huffman code. + if in_iter.len() < 2 { + // If there is less than 2 bytes left in the input buffer, we try to look up + // the huffman code with what's available, and return if that doesn't succeed. + // Original explanation in miniz: + // /* TINFL_HUFF_BITBUF_FILL() is only used rarely, when the number of bytes + // * remaining in the input buffer falls below 2. */ + // /* It reads just enough bytes from the input stream that are needed to decode + // * the next Huffman code (and absolutely no more). It works by trying to fully + // * decode a */ + // /* Huffman code by using whatever bits are currently present in the bit buffer. + // * If this fails, it reads another byte, and tries again until it succeeds or + // * until the */ + // /* bit buffer contains >=15 bits (deflate's max. Huffman code size). */ + loop { + let mut temp = i32::from(r.tables[table].fast_lookup(l.bit_buf)); + + if temp >= 0 { + let code_len = (temp >> 9) as u32; + if (code_len != 0) && (l.num_bits >= code_len) { + break; + } + } else if l.num_bits > FAST_LOOKUP_BITS.into() { + let mut code_len = u32::from(FAST_LOOKUP_BITS); + loop { + temp = i32::from( + r.tables[table].tree + [(!temp + ((l.bit_buf >> code_len) & 1) as i32) as usize], + ); + code_len += 1; + if temp >= 0 || l.num_bits < code_len + 1 { + break; + } + } + if temp >= 0 { + break; + } + } + + // TODO: miniz jumps straight to here after getting here again after failing to read + // a byte. + // Doing that lets miniz avoid re-doing the lookup that that was done in the + // previous call. + let mut byte = 0; + if let a @ Action::End(_) = read_byte(in_iter, flags, |b| { + byte = b; + Action::None + }) { + return a; + }; + + // Do this outside closure for now to avoid borrowing r. + l.bit_buf |= BitBuffer::from(byte) << l.num_bits; + l.num_bits += 8; + + if l.num_bits >= 15 { + break; + } + } + } else { + // There is enough data in the input buffer, so read the next two bytes + // and add them to the bit buffer. + // Unwrapping here is fine since we just checked that there are at least two + // bytes left. + l.bit_buf |= BitBuffer::from(read_u16_le(in_iter)) << l.num_bits; + l.num_bits += 16; + } + } + + // We now have at least 15 bits in the input buffer. + let mut symbol = i32::from(r.tables[table].fast_lookup(l.bit_buf)); + let code_len; + // If the symbol was found in the fast lookup table. + if symbol >= 0 { + // Get the length value from the top bits. + // As we shift down the sign bit, converting to an unsigned value + // shouldn't overflow. + code_len = (symbol >> 9) as u32; + // Mask out the length value. + symbol &= 511; + } else { + let res = r.tables[table].tree_lookup(symbol, l.bit_buf, u32::from(FAST_LOOKUP_BITS)); + symbol = res.0; + code_len = res.1; + }; + + if code_len == 0 { + return Action::Jump(InvalidCodeLen); + } + + l.bit_buf >>= code_len; + l.num_bits -= code_len; + f(r, l, symbol) +} + +/// Try to read one byte from `in_iter` and call `f` with the read byte as an argument, +/// returning the result. +/// If reading fails, `Action::End is returned` +#[inline] +fn read_byte<F>(in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action +where + F: FnOnce(u8) -> Action, +{ + match in_iter.next() { + None => end_of_input(flags), + Some(&byte) => f(byte), + } +} + +// TODO: `l: &mut LocalVars` may be slow similar to decompress_fast (even with inline(always)) +/// Try to read `amount` number of bits from `in_iter` and call the function `f` with the bits as an +/// an argument after reading, returning the result of that function, or `Action::End` if there are +/// not enough bytes left. +#[inline] +#[allow(clippy::while_immutable_condition)] +fn read_bits<F>( + l: &mut LocalVars, + amount: u32, + in_iter: &mut slice::Iter<u8>, + flags: u32, + f: F, +) -> Action +where + F: FnOnce(&mut LocalVars, BitBuffer) -> Action, +{ + // Clippy gives a false positive warning here due to the closure. + // Read enough bytes from the input iterator to cover the number of bits we want. + while l.num_bits < amount { + let action = read_byte(in_iter, flags, |byte| { + l.bit_buf |= BitBuffer::from(byte) << l.num_bits; + l.num_bits += 8; + Action::None + }); + + // If there are not enough bytes in the input iterator, return and signal that we need more. + if !matches!(action, Action::None) { + return action; + } + } + + let bits = l.bit_buf & ((1 << amount) - 1); + l.bit_buf >>= amount; + l.num_bits -= amount; + f(l, bits) +} + +#[inline] +fn pad_to_bytes<F>(l: &mut LocalVars, in_iter: &mut slice::Iter<u8>, flags: u32, f: F) -> Action +where + F: FnOnce(&mut LocalVars) -> Action, +{ + let num_bits = l.num_bits & 7; + read_bits(l, num_bits, in_iter, flags, |l, _| f(l)) +} + +#[inline] +const fn end_of_input(flags: u32) -> Action { + Action::End(if flags & TINFL_FLAG_HAS_MORE_INPUT != 0 { + TINFLStatus::NeedsMoreInput + } else { + TINFLStatus::FailedCannotMakeProgress + }) +} + +#[inline] +fn undo_bytes(l: &mut LocalVars, max: u32) -> u32 { + let res = cmp::min(l.num_bits >> 3, max); + l.num_bits -= res << 3; + res +} + +fn start_static_table(r: &mut DecompressorOxide) { + r.table_sizes[LITLEN_TABLE] = 288; + r.table_sizes[DIST_TABLE] = 32; + memset(&mut r.tables[LITLEN_TABLE].code_size[0..144], 8); + memset(&mut r.tables[LITLEN_TABLE].code_size[144..256], 9); + memset(&mut r.tables[LITLEN_TABLE].code_size[256..280], 7); + memset(&mut r.tables[LITLEN_TABLE].code_size[280..288], 8); + memset(&mut r.tables[DIST_TABLE].code_size[0..32], 5); +} + +#[cfg(feature = "rustc-dep-of-std")] +fn reverse_bits(n: u32) -> u32 { + // Lookup is not used when building as part of std to avoid wasting space + // for lookup table in every rust binary + // as it's only used for backtraces in the cold path + // - see #152 + n.reverse_bits() +} + +#[cfg(not(feature = "rustc-dep-of-std"))] +fn reverse_bits(n: u32) -> u32 { + static REVERSED_BITS_LOOKUP: [u32; 512] = { + let mut table = [0; 512]; + + let mut i = 0; + while i < 512 { + table[i] = (i as u32).reverse_bits(); + i += 1; + } + + table + }; + + REVERSED_BITS_LOOKUP[n as usize] +} + +fn init_tree(r: &mut DecompressorOxide, l: &mut LocalVars) -> Option<Action> { + loop { + let bt = r.block_type as usize; + if bt >= r.tables.len() { + return None; + } + let table = &mut r.tables[bt]; + let table_size = r.table_sizes[bt] as usize; + if table_size > table.code_size.len() { + return None; + } + let mut total_symbols = [0u32; 16]; + let mut next_code = [0u32; 17]; + memset(&mut table.look_up[..], 0); + memset(&mut table.tree[..], 0); + + for &code_size in &table.code_size[..table_size] { + let cs = code_size as usize; + if cs >= total_symbols.len() { + return None; + } + total_symbols[cs] += 1; + } + + let mut used_symbols = 0; + let mut total = 0; + for (ts, next) in total_symbols + .iter() + .copied() + .zip(next_code.iter_mut().skip(1)) + .skip(1) + { + used_symbols += ts; + total += ts; + total <<= 1; + *next = total; + } + + if total != 65_536 && used_symbols > 1 { + return Some(Action::Jump(BadTotalSymbols)); + } + + let mut tree_next = -1; + for symbol_index in 0..table_size { + let code_size = table.code_size[symbol_index]; + if code_size == 0 || usize::from(code_size) >= next_code.len() { + continue; + } + + let cur_code = next_code[code_size as usize]; + next_code[code_size as usize] += 1; + + let n = cur_code & (u32::MAX >> (32 - code_size)); + + let mut rev_code = if n < 512 { + // Using a lookup table + // for a small speedup here, + // Seems to only really make a difference on very short + // inputs however. + // 512 seems to be around a sweet spot. + reverse_bits(n) + } else { + n.reverse_bits() + } >> (32 - code_size); + + if code_size <= FAST_LOOKUP_BITS { + let k = (i16::from(code_size) << 9) | symbol_index as i16; + while rev_code < FAST_LOOKUP_SIZE { + table.look_up[rev_code as usize] = k; + rev_code += 1 << code_size; + } + continue; + } + + let mut tree_cur = table.look_up[(rev_code & (FAST_LOOKUP_SIZE - 1)) as usize]; + if tree_cur == 0 { + table.look_up[(rev_code & (FAST_LOOKUP_SIZE - 1)) as usize] = tree_next; + tree_cur = tree_next; + tree_next -= 2; + } + + rev_code >>= FAST_LOOKUP_BITS - 1; + for _ in FAST_LOOKUP_BITS + 1..code_size { + rev_code >>= 1; + tree_cur -= (rev_code & 1) as i16; + let tree_index = (-tree_cur - 1) as usize; + if tree_index >= table.tree.len() { + return None; + } + if table.tree[tree_index] == 0 { + table.tree[tree_index] = tree_next; + tree_cur = tree_next; + tree_next -= 2; + } else { + tree_cur = table.tree[tree_index]; + } + } + + rev_code >>= 1; + tree_cur -= (rev_code & 1) as i16; + let tree_index = (-tree_cur - 1) as usize; + if tree_index >= table.tree.len() { + return None; + } + table.tree[tree_index] = symbol_index as i16; + } + + if r.block_type == 2 { + l.counter = 0; + return Some(Action::Jump(ReadLitlenDistTablesCodeSize)); + } + + if r.block_type == 0 { + break; + } + r.block_type -= 1; + } + + l.counter = 0; + Some(Action::Jump(DecodeLitlen)) +} + +// A helper macro for generating the state machine. +// +// As Rust doesn't have fallthrough on matches, we have to return to the match statement +// and jump for each state change. (Which would ideally be optimized away, but often isn't.) +macro_rules! generate_state { + ($state: ident, $state_machine: tt, $f: expr) => { + loop { + match $f { + Action::None => continue, + Action::Jump(new_state) => { + $state = new_state; + continue $state_machine; + }, + Action::End(result) => break $state_machine result, + } + } + }; +} + +#[derive(Copy, Clone)] +struct LocalVars { + pub bit_buf: BitBuffer, + pub num_bits: u32, + pub dist: u32, + pub counter: u32, + pub num_extra: u32, +} + +#[inline] +fn transfer( + out_slice: &mut [u8], + mut source_pos: usize, + mut out_pos: usize, + match_len: usize, + out_buf_size_mask: usize, +) { + // special case that comes up surprisingly often. in the case that `source_pos` + // is 1 less than `out_pos`, we can say that the entire range will be the same + // value and optimize this to be a simple `memset` + let source_diff = if source_pos > out_pos { + source_pos - out_pos + } else { + out_pos - source_pos + }; + if out_buf_size_mask == usize::MAX && source_diff == 1 && out_pos > source_pos { + let init = out_slice[out_pos - 1]; + let end = (match_len >> 2) * 4 + out_pos; + + out_slice[out_pos..end].fill(init); + out_pos = end; + source_pos = end - 1; + // if the difference between `source_pos` and `out_pos` is greater than 3, we + // can do slightly better than the naive case by copying everything at once + } else if out_buf_size_mask == usize::MAX && source_diff >= 4 && out_pos > source_pos { + for _ in 0..match_len >> 2 { + out_slice.copy_within(source_pos..=source_pos + 3, out_pos); + source_pos += 4; + out_pos += 4; + } + } else { + for _ in 0..match_len >> 2 { + out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask]; + out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask]; + out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask]; + out_slice[out_pos + 3] = out_slice[(source_pos + 3) & out_buf_size_mask]; + source_pos += 4; + out_pos += 4; + } + } + + match match_len & 3 { + 0 => (), + 1 => out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask], + 2 => { + out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask]; + out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask]; + } + 3 => { + out_slice[out_pos] = out_slice[source_pos & out_buf_size_mask]; + out_slice[out_pos + 1] = out_slice[(source_pos + 1) & out_buf_size_mask]; + out_slice[out_pos + 2] = out_slice[(source_pos + 2) & out_buf_size_mask]; + } + _ => unreachable!(), + } +} + +/// Presumes that there is at least match_len bytes in output left. +#[inline] +fn apply_match( + out_slice: &mut [u8], + out_pos: usize, + dist: usize, + match_len: usize, + out_buf_size_mask: usize, +) { + debug_assert!(out_pos.checked_add(match_len).unwrap() <= out_slice.len()); + + let source_pos = out_pos.wrapping_sub(dist) & out_buf_size_mask; + + if match_len == 3 { + let out_slice = Cell::from_mut(out_slice).as_slice_of_cells(); + if let Some(dst) = out_slice.get(out_pos..out_pos + 3) { + // Moving bounds checks before any memory mutation allows the optimizer + // combine them together. + let src = out_slice + .get(source_pos) + .zip(out_slice.get((source_pos + 1) & out_buf_size_mask)) + .zip(out_slice.get((source_pos + 2) & out_buf_size_mask)); + if let Some(((a, b), c)) = src { + // For correctness, the memory reads and writes have to be interleaved. + // Cells make it possible for read and write references to overlap. + dst[0].set(a.get()); + dst[1].set(b.get()); + dst[2].set(c.get()); + } + } + return; + } + + if cfg!(not(any(target_arch = "x86", target_arch = "x86_64"))) { + // We are not on x86 so copy manually. + transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask); + return; + } + + if source_pos >= out_pos && (source_pos - out_pos) < match_len { + transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask); + } else if match_len <= dist && source_pos + match_len < out_slice.len() { + // Destination and source segments does not intersect and source does not wrap. + if source_pos < out_pos { + let (from_slice, to_slice) = out_slice.split_at_mut(out_pos); + to_slice[..match_len].copy_from_slice(&from_slice[source_pos..source_pos + match_len]); + } else { + let (to_slice, from_slice) = out_slice.split_at_mut(source_pos); + to_slice[out_pos..out_pos + match_len].copy_from_slice(&from_slice[..match_len]); + } + } else { + transfer(out_slice, source_pos, out_pos, match_len, out_buf_size_mask); + } +} + +/// Fast inner decompression loop which is run while there is at least +/// 259 bytes left in the output buffer, and at least 6 bytes left in the input buffer +/// (The maximum one match would need + 1). +/// +/// This was inspired by a similar optimization in zlib, which uses this info to do +/// faster unchecked copies of multiple bytes at a time. +/// Currently we don't do this here, but this function does avoid having to jump through the +/// big match loop on each state change(as rust does not have fallthrough or gotos at the moment), +/// and already improves decompression speed a fair bit. +fn decompress_fast( + r: &mut DecompressorOxide, + in_iter: &mut slice::Iter<u8>, + out_buf: &mut OutputBuffer, + flags: u32, + local_vars: &mut LocalVars, + out_buf_size_mask: usize, +) -> (TINFLStatus, State) { + // Make a local copy of the most used variables, to avoid having to update and read from values + // in a random memory location and to encourage more register use. + let mut l = *local_vars; + let mut state; + + let status: TINFLStatus = 'o: loop { + state = State::DecodeLitlen; + loop { + // This function assumes that there is at least 259 bytes left in the output buffer, + // and that there is at least 14 bytes left in the input buffer. 14 input bytes: + // 15 (prev lit) + 15 (length) + 5 (length extra) + 15 (dist) + // + 29 + 32 (left in bit buf, including last 13 dist extra) = 111 bits < 14 bytes + // We need the one extra byte as we may write one length and one full match + // before checking again. + if out_buf.bytes_left() < 259 || in_iter.len() < 14 { + state = State::DecodeLitlen; + break 'o TINFLStatus::Done; + } + + fill_bit_buffer(&mut l, in_iter); + + if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) { + l.counter = symbol as u32; + l.bit_buf >>= code_len; + l.num_bits -= code_len; + + if (l.counter & 256) != 0 { + // The symbol is not a literal. + break; + } else { + // If we have a 32-bit buffer we need to read another two bytes now + // to have enough bits to keep going. + if cfg!(not(target_pointer_width = "64")) { + fill_bit_buffer(&mut l, in_iter); + } + + if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) { + l.bit_buf >>= code_len; + l.num_bits -= code_len; + // The previous symbol was a literal, so write it directly and check + // the next one. + out_buf.write_byte(l.counter as u8); + if (symbol & 256) != 0 { + l.counter = symbol as u32; + // The symbol is a length value. + break; + } else { + // The symbol is a literal, so write it directly and continue. + out_buf.write_byte(symbol as u8); + } + } else { + state.begin(InvalidCodeLen); + break 'o TINFLStatus::Failed; + } + } + } else { + state.begin(InvalidCodeLen); + break 'o TINFLStatus::Failed; + } + } + + // Mask the top bits since they may contain length info. + l.counter &= 511; + if l.counter == 256 { + // We hit the end of block symbol. + state.begin(BlockDone); + break 'o TINFLStatus::Done; + } else if l.counter > 285 { + // Invalid code. + // We already verified earlier that the code is > 256. + state.begin(InvalidLitlen); + break 'o TINFLStatus::Failed; + } else { + // The symbol was a length code. + // # Optimization + // Mask the value to avoid bounds checks + // We could use get_unchecked later if can statically verify that + // this will never go out of bounds. + l.num_extra = u32::from(LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]); + l.counter = u32::from(LENGTH_BASE[(l.counter - 257) as usize & BASE_EXTRA_MASK]); + // Length and distance codes have a number of extra bits depending on + // the base, which together with the base gives us the exact value. + + fill_bit_buffer(&mut l, in_iter); + if l.num_extra != 0 { + let extra_bits = l.bit_buf & ((1 << l.num_extra) - 1); + l.bit_buf >>= l.num_extra; + l.num_bits -= l.num_extra; + l.counter += extra_bits as u32; + } + + // We found a length code, so a distance code should follow. + + if cfg!(not(target_pointer_width = "64")) { + fill_bit_buffer(&mut l, in_iter); + } + + if let Some((mut symbol, code_len)) = r.tables[DIST_TABLE].lookup(l.bit_buf) { + symbol &= 511; + l.bit_buf >>= code_len; + l.num_bits -= code_len; + if symbol > 29 { + state.begin(InvalidDist); + break 'o TINFLStatus::Failed; + } + + l.num_extra = u32::from(DIST_EXTRA[symbol as usize]); + l.dist = u32::from(DIST_BASE[symbol as usize]); + } else { + state.begin(InvalidCodeLen); + break 'o TINFLStatus::Failed; + } + + if l.num_extra != 0 { + fill_bit_buffer(&mut l, in_iter); + let extra_bits = l.bit_buf & ((1 << l.num_extra) - 1); + l.bit_buf >>= l.num_extra; + l.num_bits -= l.num_extra; + l.dist += extra_bits as u32; + } + + let position = out_buf.position(); + if l.dist as usize > out_buf.position() + && (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0) + { + // We encountered a distance that refers a position before + // the start of the decoded data, so we can't continue. + state.begin(DistanceOutOfBounds); + break TINFLStatus::Failed; + } + + apply_match( + out_buf.get_mut(), + position, + l.dist as usize, + l.counter as usize, + out_buf_size_mask, + ); + + out_buf.set_position(position + l.counter as usize); + } + }; + + *local_vars = l; + (status, state) +} + +/// Main decompression function. Keeps decompressing data from `in_buf` until the `in_buf` is +/// empty, `out` is full, the end of the deflate stream is hit, or there is an error in the +/// deflate stream. +/// +/// # Arguments +/// +/// `r` is a [`DecompressorOxide`] struct with the state of this stream. +/// +/// `in_buf` is a reference to the compressed data that is to be decompressed. The decompressor will +/// start at the first byte of this buffer. +/// +/// `out` is a reference to the buffer that will store the decompressed data, and that +/// stores previously decompressed data if any. +/// +/// * The offset given by `out_pos` indicates where in the output buffer slice writing should start. +/// * If [`TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF`] is not set, the output buffer is used in a +/// wrapping manner, and it's size is required to be a power of 2. +/// * The decompression function normally needs access to 32KiB of the previously decompressed data +///(or to the beginning of the decompressed data if less than 32KiB has been decompressed.) +/// - If this data is not available, decompression may fail. +/// - Some deflate compressors allow specifying a window size which limits match distances to +/// less than this, or alternatively an RLE mode where matches will only refer to the previous byte +/// and thus allows a smaller output buffer. The window size can be specified in the zlib +/// header structure, however, the header data should not be relied on to be correct. +/// +/// `flags` indicates settings and status to the decompression function. +/// * The [`TINFL_FLAG_HAS_MORE_INPUT`] has to be specified if more compressed data is to be provided +/// in a subsequent call to this function. +/// * See the the [`inflate_flags`] module for details on other flags. +/// +/// # Returns +/// +/// Returns a tuple containing the status of the compressor, the number of input bytes read, and the +/// number of bytes output to `out`. +/// +/// This function shouldn't panic pending any bugs. +pub fn decompress( + r: &mut DecompressorOxide, + in_buf: &[u8], + out: &mut [u8], + out_pos: usize, + flags: u32, +) -> (TINFLStatus, usize, usize) { + let out_buf_size_mask = if flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0 { + usize::max_value() + } else { + // In the case of zero len, any attempt to write would produce HasMoreOutput, + // so to gracefully process the case of there really being no output, + // set the mask to all zeros. + out.len().saturating_sub(1) + }; + + // Ensure the output buffer's size is a power of 2, unless the output buffer + // is large enough to hold the entire output file (in which case it doesn't + // matter). + // Also make sure that the output buffer position is not past the end of the output buffer. + if (out_buf_size_mask.wrapping_add(1) & out_buf_size_mask) != 0 || out_pos > out.len() { + return (TINFLStatus::BadParam, 0, 0); + } + + let mut in_iter = in_buf.iter(); + + let mut state = r.state; + + let mut out_buf = OutputBuffer::from_slice_and_pos(out, out_pos); + + // Make a local copy of the important variables here so we can work with them on the stack. + let mut l = LocalVars { + bit_buf: r.bit_buf, + num_bits: r.num_bits, + dist: r.dist, + counter: r.counter, + num_extra: r.num_extra, + }; + + let mut status = 'state_machine: loop { + match state { + Start => generate_state!(state, 'state_machine, { + l.bit_buf = 0; + l.num_bits = 0; + l.dist = 0; + l.counter = 0; + l.num_extra = 0; + r.z_header0 = 0; + r.z_header1 = 0; + r.z_adler32 = 1; + r.check_adler32 = 1; + if flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0 { + Action::Jump(State::ReadZlibCmf) + } else { + Action::Jump(State::ReadBlockHeader) + } + }), + + ReadZlibCmf => generate_state!(state, 'state_machine, { + read_byte(&mut in_iter, flags, |cmf| { + r.z_header0 = u32::from(cmf); + Action::Jump(State::ReadZlibFlg) + }) + }), + + ReadZlibFlg => generate_state!(state, 'state_machine, { + read_byte(&mut in_iter, flags, |flg| { + r.z_header1 = u32::from(flg); + validate_zlib_header(r.z_header0, r.z_header1, flags, out_buf_size_mask) + }) + }), + + // Read the block header and jump to the relevant section depending on the block type. + ReadBlockHeader => generate_state!(state, 'state_machine, { + read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| { + r.finish = (bits & 1) as u32; + r.block_type = (bits >> 1) as u32 & 3; + match r.block_type { + 0 => Action::Jump(BlockTypeNoCompression), + 1 => { + start_static_table(r); + init_tree(r, l).unwrap_or(Action::End(TINFLStatus::Failed)) + }, + 2 => { + l.counter = 0; + Action::Jump(ReadTableSizes) + }, + 3 => Action::Jump(BlockTypeUnexpected), + _ => unreachable!() + } + }) + }), + + // Raw/Stored/uncompressed block. + BlockTypeNoCompression => generate_state!(state, 'state_machine, { + pad_to_bytes(&mut l, &mut in_iter, flags, |l| { + l.counter = 0; + Action::Jump(RawHeader) + }) + }), + + // Check that the raw block header is correct. + RawHeader => generate_state!(state, 'state_machine, { + if l.counter < 4 { + // Read block length and block length check. + if l.num_bits != 0 { + read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| { + r.raw_header[l.counter as usize] = bits as u8; + l.counter += 1; + Action::None + }) + } else { + read_byte(&mut in_iter, flags, |byte| { + r.raw_header[l.counter as usize] = byte; + l.counter += 1; + Action::None + }) + } + } else { + // Check if the length value of a raw block is correct. + // The 2 first (2-byte) words in a raw header are the length and the + // ones complement of the length. + let length = u16::from(r.raw_header[0]) | (u16::from(r.raw_header[1]) << 8); + let check = u16::from(r.raw_header[2]) | (u16::from(r.raw_header[3]) << 8); + let valid = length == !check; + l.counter = length.into(); + + if !valid { + Action::Jump(BadRawLength) + } else if l.counter == 0 { + // Empty raw block. Sometimes used for synchronization. + Action::Jump(BlockDone) + } else if l.num_bits != 0 { + // There is some data in the bit buffer, so we need to write that first. + Action::Jump(RawReadFirstByte) + } else { + // The bit buffer is empty, so memcpy the rest of the uncompressed data from + // the block. + Action::Jump(RawMemcpy1) + } + } + }), + + // Read the byte from the bit buffer. + RawReadFirstByte => generate_state!(state, 'state_machine, { + read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| { + l.dist = bits as u32; + Action::Jump(RawStoreFirstByte) + }) + }), + + // Write the byte we just read to the output buffer. + RawStoreFirstByte => generate_state!(state, 'state_machine, { + if out_buf.bytes_left() == 0 { + Action::End(TINFLStatus::HasMoreOutput) + } else { + out_buf.write_byte(l.dist as u8); + l.counter -= 1; + if l.counter == 0 || l.num_bits == 0 { + Action::Jump(RawMemcpy1) + } else { + // There is still some data left in the bit buffer that needs to be output. + // TODO: Changed this to jump to `RawReadfirstbyte` rather than + // `RawStoreFirstByte` as that seemed to be the correct path, but this + // needs testing. + Action::Jump(RawReadFirstByte) + } + } + }), + + RawMemcpy1 => generate_state!(state, 'state_machine, { + if l.counter == 0 { + Action::Jump(BlockDone) + } else if out_buf.bytes_left() == 0 { + Action::End(TINFLStatus::HasMoreOutput) + } else { + Action::Jump(RawMemcpy2) + } + }), + + RawMemcpy2 => generate_state!(state, 'state_machine, { + if in_iter.len() > 0 { + // Copy as many raw bytes as possible from the input to the output using memcpy. + // Raw block lengths are limited to 64 * 1024, so casting through usize and u32 + // is not an issue. + let space_left = out_buf.bytes_left(); + let bytes_to_copy = cmp::min(cmp::min( + space_left, + in_iter.len()), + l.counter as usize + ); + + out_buf.write_slice(&in_iter.as_slice()[..bytes_to_copy]); + + in_iter.nth(bytes_to_copy - 1); + l.counter -= bytes_to_copy as u32; + Action::Jump(RawMemcpy1) + } else { + end_of_input(flags) + } + }), + + // Read how many huffman codes/symbols are used for each table. + ReadTableSizes => generate_state!(state, 'state_machine, { + if l.counter < 3 { + let num_bits = [5, 5, 4][l.counter as usize]; + read_bits(&mut l, num_bits, &mut in_iter, flags, |l, bits| { + r.table_sizes[l.counter as usize] = + bits as u32 + u32::from(MIN_TABLE_SIZES[l.counter as usize]); + l.counter += 1; + Action::None + }) + } else { + memset(&mut r.tables[HUFFLEN_TABLE].code_size[..], 0); + l.counter = 0; + // Check that the litlen and distance are within spec. + // litlen table should be <=286 acc to the RFC and + // additionally zlib rejects dist table sizes larger than 30. + // NOTE this the final sizes after adding back predefined values, not + // raw value in the data. + // See miniz_oxide issue #130 and https://github.com/madler/zlib/issues/82. + if r.table_sizes[LITLEN_TABLE] <= 286 && r.table_sizes[DIST_TABLE] <= 30 { + Action::Jump(ReadHufflenTableCodeSize) + } + else { + Action::Jump(BadDistOrLiteralTableLength) + } + } + }), + + // Read the 3-bit lengths of the huffman codes describing the huffman code lengths used + // to decode the lengths of the main tables. + ReadHufflenTableCodeSize => generate_state!(state, 'state_machine, { + if l.counter < r.table_sizes[HUFFLEN_TABLE] { + read_bits(&mut l, 3, &mut in_iter, flags, |l, bits| { + // These lengths are not stored in a normal ascending order, but rather one + // specified by the deflate specification intended to put the most used + // values at the front as trailing zero lengths do not have to be stored. + r.tables[HUFFLEN_TABLE] + .code_size[HUFFMAN_LENGTH_ORDER[l.counter as usize] as usize] = + bits as u8; + l.counter += 1; + Action::None + }) + } else { + r.table_sizes[HUFFLEN_TABLE] = 19; + init_tree(r, &mut l).unwrap_or(Action::End(TINFLStatus::Failed)) + } + }), + + ReadLitlenDistTablesCodeSize => generate_state!(state, 'state_machine, { + if l.counter < r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] { + decode_huffman_code( + r, &mut l, HUFFLEN_TABLE, + flags, &mut in_iter, |r, l, symbol| { + l.dist = symbol as u32; + if l.dist < 16 { + r.len_codes[l.counter as usize] = l.dist as u8; + l.counter += 1; + Action::None + } else if l.dist == 16 && l.counter == 0 { + Action::Jump(BadCodeSizeDistPrevLookup) + } else { + l.num_extra = [2, 3, 7][l.dist as usize - 16]; + Action::Jump(ReadExtraBitsCodeSize) + } + } + ) + } else if l.counter != r.table_sizes[LITLEN_TABLE] + r.table_sizes[DIST_TABLE] { + Action::Jump(BadCodeSizeSum) + } else { + r.tables[LITLEN_TABLE].code_size[..r.table_sizes[LITLEN_TABLE] as usize] + .copy_from_slice(&r.len_codes[..r.table_sizes[LITLEN_TABLE] as usize]); + + let dist_table_start = r.table_sizes[LITLEN_TABLE] as usize; + let dist_table_end = (r.table_sizes[LITLEN_TABLE] + + r.table_sizes[DIST_TABLE]) as usize; + r.tables[DIST_TABLE].code_size[..r.table_sizes[DIST_TABLE] as usize] + .copy_from_slice(&r.len_codes[dist_table_start..dist_table_end]); + + r.block_type -= 1; + init_tree(r, &mut l).unwrap_or(Action::End(TINFLStatus::Failed)) + } + }), + + ReadExtraBitsCodeSize => generate_state!(state, 'state_machine, { + let num_extra = l.num_extra; + read_bits(&mut l, num_extra, &mut in_iter, flags, |l, mut extra_bits| { + // Mask to avoid a bounds check. + extra_bits += [3, 3, 11][(l.dist as usize - 16) & 3]; + let val = if l.dist == 16 { + r.len_codes[l.counter as usize - 1] + } else { + 0 + }; + + memset( + &mut r.len_codes[ + l.counter as usize..l.counter as usize + extra_bits as usize + ], + val, + ); + l.counter += extra_bits as u32; + Action::Jump(ReadLitlenDistTablesCodeSize) + }) + }), + + DecodeLitlen => generate_state!(state, 'state_machine, { + if in_iter.len() < 4 || out_buf.bytes_left() < 2 { + // See if we can decode a literal with the data we have left. + // Jumps to next state (WriteSymbol) if successful. + decode_huffman_code( + r, + &mut l, + LITLEN_TABLE, + flags, + &mut in_iter, + |_r, l, symbol| { + l.counter = symbol as u32; + Action::Jump(WriteSymbol) + }, + ) + } else if + // If there is enough space, use the fast inner decompression + // function. + out_buf.bytes_left() >= 259 && + in_iter.len() >= 14 + { + let (status, new_state) = decompress_fast( + r, + &mut in_iter, + &mut out_buf, + flags, + &mut l, + out_buf_size_mask, + ); + + state = new_state; + if status == TINFLStatus::Done { + Action::Jump(new_state) + } else { + Action::End(status) + } + } else { + fill_bit_buffer(&mut l, &mut in_iter); + + if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) { + + l.counter = symbol as u32; + l.bit_buf >>= code_len; + l.num_bits -= code_len; + + if (l.counter & 256) != 0 { + // The symbol is not a literal. + Action::Jump(HuffDecodeOuterLoop1) + } else { + // If we have a 32-bit buffer we need to read another two bytes now + // to have enough bits to keep going. + if cfg!(not(target_pointer_width = "64")) { + fill_bit_buffer(&mut l, &mut in_iter); + } + + if let Some((symbol, code_len)) = r.tables[LITLEN_TABLE].lookup(l.bit_buf) { + + l.bit_buf >>= code_len; + l.num_bits -= code_len; + // The previous symbol was a literal, so write it directly and check + // the next one. + out_buf.write_byte(l.counter as u8); + if (symbol & 256) != 0 { + l.counter = symbol as u32; + // The symbol is a length value. + Action::Jump(HuffDecodeOuterLoop1) + } else { + // The symbol is a literal, so write it directly and continue. + out_buf.write_byte(symbol as u8); + Action::None + } + } else { + Action::Jump(InvalidCodeLen) + } + } + } else { + Action::Jump(InvalidCodeLen) + } + } + }), + + WriteSymbol => generate_state!(state, 'state_machine, { + if l.counter >= 256 { + Action::Jump(HuffDecodeOuterLoop1) + } else if out_buf.bytes_left() > 0 { + out_buf.write_byte(l.counter as u8); + Action::Jump(DecodeLitlen) + } else { + Action::End(TINFLStatus::HasMoreOutput) + } + }), + + HuffDecodeOuterLoop1 => generate_state!(state, 'state_machine, { + // Mask the top bits since they may contain length info. + l.counter &= 511; + + if l.counter + == 256 { + // We hit the end of block symbol. + Action::Jump(BlockDone) + } else if l.counter > 285 { + // Invalid code. + // We already verified earlier that the code is > 256. + Action::Jump(InvalidLitlen) + } else { + // # Optimization + // Mask the value to avoid bounds checks + // We could use get_unchecked later if can statically verify that + // this will never go out of bounds. + l.num_extra = + u32::from(LENGTH_EXTRA[(l.counter - 257) as usize & BASE_EXTRA_MASK]); + l.counter = u32::from(LENGTH_BASE[(l.counter - 257) as usize & BASE_EXTRA_MASK]); + // Length and distance codes have a number of extra bits depending on + // the base, which together with the base gives us the exact value. + if l.num_extra != 0 { + Action::Jump(ReadExtraBitsLitlen) + } else { + Action::Jump(DecodeDistance) + } + } + }), + + ReadExtraBitsLitlen => generate_state!(state, 'state_machine, { + let num_extra = l.num_extra; + read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| { + l.counter += extra_bits as u32; + Action::Jump(DecodeDistance) + }) + }), + + DecodeDistance => generate_state!(state, 'state_machine, { + // Try to read a huffman code from the input buffer and look up what + // length code the decoded symbol refers to. + decode_huffman_code(r, &mut l, DIST_TABLE, flags, &mut in_iter, |_r, l, symbol| { + if symbol > 29 { + // Invalid distance code. + return Action::Jump(InvalidDist) + } + // # Optimization + // Mask the value to avoid bounds checks + // We could use get_unchecked later if can statically verify that + // this will never go out of bounds. + l.num_extra = u32::from(DIST_EXTRA[symbol as usize & BASE_EXTRA_MASK]); + l.dist = u32::from(DIST_BASE[symbol as usize & BASE_EXTRA_MASK]); + if l.num_extra != 0 { + // ReadEXTRA_BITS_DISTACNE + Action::Jump(ReadExtraBitsDistance) + } else { + Action::Jump(HuffDecodeOuterLoop2) + } + }) + }), + + ReadExtraBitsDistance => generate_state!(state, 'state_machine, { + let num_extra = l.num_extra; + read_bits(&mut l, num_extra, &mut in_iter, flags, |l, extra_bits| { + l.dist += extra_bits as u32; + Action::Jump(HuffDecodeOuterLoop2) + }) + }), + + HuffDecodeOuterLoop2 => generate_state!(state, 'state_machine, { + if l.dist as usize > out_buf.position() && + (flags & TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF != 0) + { + // We encountered a distance that refers a position before + // the start of the decoded data, so we can't continue. + Action::Jump(DistanceOutOfBounds) + } else { + let out_pos = out_buf.position(); + let source_pos = out_buf.position() + .wrapping_sub(l.dist as usize) & out_buf_size_mask; + + let out_len = out_buf.get_ref().len(); + let match_end_pos = out_buf.position() + l.counter as usize; + + if match_end_pos > out_len || + // miniz doesn't do this check here. Not sure how it makes sure + // that this case doesn't happen. + (source_pos >= out_pos && (source_pos - out_pos) < l.counter as usize) + { + // Not enough space for all of the data in the output buffer, + // so copy what we have space for. + if l.counter == 0 { + Action::Jump(DecodeLitlen) + } else { + Action::Jump(WriteLenBytesToEnd) + } + } else { + apply_match( + out_buf.get_mut(), + out_pos, + l.dist as usize, + l.counter as usize, + out_buf_size_mask + ); + out_buf.set_position(out_pos + l.counter as usize); + Action::Jump(DecodeLitlen) + } + } + }), + + WriteLenBytesToEnd => generate_state!(state, 'state_machine, { + if out_buf.bytes_left() > 0 { + let out_pos = out_buf.position(); + let source_pos = out_buf.position() + .wrapping_sub(l.dist as usize) & out_buf_size_mask; + + + let len = cmp::min(out_buf.bytes_left(), l.counter as usize); + + transfer(out_buf.get_mut(), source_pos, out_pos, len, out_buf_size_mask); + + out_buf.set_position(out_pos + len); + l.counter -= len as u32; + if l.counter == 0 { + Action::Jump(DecodeLitlen) + } else { + Action::None + } + } else { + Action::End(TINFLStatus::HasMoreOutput) + } + }), + + BlockDone => generate_state!(state, 'state_machine, { + // End once we've read the last block. + if r.finish != 0 { + pad_to_bytes(&mut l, &mut in_iter, flags, |_| Action::None); + + let in_consumed = in_buf.len() - in_iter.len(); + let undo = undo_bytes(&mut l, in_consumed as u32) as usize; + in_iter = in_buf[in_consumed - undo..].iter(); + + l.bit_buf &= ((1 as BitBuffer) << l.num_bits) - 1; + debug_assert_eq!(l.num_bits, 0); + + if flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0 { + l.counter = 0; + Action::Jump(ReadAdler32) + } else { + Action::Jump(DoneForever) + } + } else { + Action::Jump(ReadBlockHeader) + } + }), + + ReadAdler32 => generate_state!(state, 'state_machine, { + if l.counter < 4 { + if l.num_bits != 0 { + read_bits(&mut l, 8, &mut in_iter, flags, |l, bits| { + r.z_adler32 <<= 8; + r.z_adler32 |= bits as u32; + l.counter += 1; + Action::None + }) + } else { + read_byte(&mut in_iter, flags, |byte| { + r.z_adler32 <<= 8; + r.z_adler32 |= u32::from(byte); + l.counter += 1; + Action::None + }) + } + } else { + Action::Jump(DoneForever) + } + }), + + // We are done. + DoneForever => break TINFLStatus::Done, + + // Anything else indicates failure. + // BadZlibHeader | BadRawLength | BadDistOrLiteralTableLength | BlockTypeUnexpected | + // DistanceOutOfBounds | + // BadTotalSymbols | BadCodeSizeDistPrevLookup | BadCodeSizeSum | InvalidLitlen | + // InvalidDist | InvalidCodeLen + _ => break TINFLStatus::Failed, + }; + }; + + let in_undo = if status != TINFLStatus::NeedsMoreInput + && status != TINFLStatus::FailedCannotMakeProgress + { + undo_bytes(&mut l, (in_buf.len() - in_iter.len()) as u32) as usize + } else { + 0 + }; + + // Make sure HasMoreOutput overrides NeedsMoreInput if the output buffer is full. + // (Unless the missing input is the adler32 value in which case we don't need to write anything.) + // TODO: May want to see if we can do this in a better way. + if status == TINFLStatus::NeedsMoreInput + && out_buf.bytes_left() == 0 + && state != State::ReadAdler32 + { + status = TINFLStatus::HasMoreOutput + } + + r.state = state; + r.bit_buf = l.bit_buf; + r.num_bits = l.num_bits; + r.dist = l.dist; + r.counter = l.counter; + r.num_extra = l.num_extra; + + r.bit_buf &= ((1 as BitBuffer) << r.num_bits) - 1; + + // If this is a zlib stream, and update the adler32 checksum with the decompressed bytes if + // requested. + let need_adler = if (flags & TINFL_FLAG_IGNORE_ADLER32) == 0 { + flags & (TINFL_FLAG_PARSE_ZLIB_HEADER | TINFL_FLAG_COMPUTE_ADLER32) != 0 + } else { + // If TINFL_FLAG_IGNORE_ADLER32 is enabled, ignore the checksum. + false + }; + if need_adler && status as i32 >= 0 { + let out_buf_pos = out_buf.position(); + r.check_adler32 = update_adler32(r.check_adler32, &out_buf.get_ref()[out_pos..out_buf_pos]); + + // disabled so that random input from fuzzer would not be rejected early, + // before it has a chance to reach interesting parts of code + if !cfg!(fuzzing) { + // Once we are done, check if the checksum matches with the one provided in the zlib header. + if status == TINFLStatus::Done + && flags & TINFL_FLAG_PARSE_ZLIB_HEADER != 0 + && r.check_adler32 != r.z_adler32 + { + status = TINFLStatus::Adler32Mismatch; + } + } + } + + ( + status, + in_buf.len() - in_iter.len() - in_undo, + out_buf.position() - out_pos, + ) +} + +#[cfg(test)] +mod test { + use super::*; + + //TODO: Fix these. + + fn tinfl_decompress_oxide<'i>( + r: &mut DecompressorOxide, + input_buffer: &'i [u8], + output_buffer: &mut [u8], + flags: u32, + ) -> (TINFLStatus, &'i [u8], usize) { + let (status, in_pos, out_pos) = decompress(r, input_buffer, output_buffer, 0, flags); + (status, &input_buffer[in_pos..], out_pos) + } + + #[test] + fn decompress_zlib() { + let encoded = [ + 120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19, + ]; + let flags = TINFL_FLAG_COMPUTE_ADLER32 | TINFL_FLAG_PARSE_ZLIB_HEADER; + + let mut b = DecompressorOxide::new(); + const LEN: usize = 32; + let mut b_buf = [0; LEN]; + + // This should fail with the out buffer being to small. + let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], &mut b_buf, flags); + + assert_eq!(b_status.0, TINFLStatus::Failed); + + let flags = flags | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + + b = DecompressorOxide::new(); + + // With TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF set this should no longer fail. + let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], &mut b_buf, flags); + + assert_eq!(b_buf[..b_status.2], b"Hello, zlib!"[..]); + assert_eq!(b_status.0, TINFLStatus::Done); + } + + #[cfg(feature = "with-alloc")] + #[test] + fn raw_block() { + const LEN: usize = 64; + + let text = b"Hello, zlib!"; + let encoded = { + let len = text.len(); + let notlen = !len; + let mut encoded = vec![ + 1, + len as u8, + (len >> 8) as u8, + notlen as u8, + (notlen >> 8) as u8, + ]; + encoded.extend_from_slice(&text[..]); + encoded + }; + + //let flags = TINFL_FLAG_COMPUTE_ADLER32 | TINFL_FLAG_PARSE_ZLIB_HEADER | + let flags = TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + + let mut b = DecompressorOxide::new(); + + let mut b_buf = [0; LEN]; + + let b_status = tinfl_decompress_oxide(&mut b, &encoded[..], &mut b_buf, flags); + assert_eq!(b_buf[..b_status.2], text[..]); + assert_eq!(b_status.0, TINFLStatus::Done); + } + + fn masked_lookup(table: &HuffmanTable, bit_buf: BitBuffer) -> (i32, u32) { + let ret = table.lookup(bit_buf).unwrap(); + (ret.0 & 511, ret.1) + } + + #[test] + fn fixed_table_lookup() { + let mut d = DecompressorOxide::new(); + d.block_type = 1; + start_static_table(&mut d); + let mut l = LocalVars { + bit_buf: d.bit_buf, + num_bits: d.num_bits, + dist: d.dist, + counter: d.counter, + num_extra: d.num_extra, + }; + init_tree(&mut d, &mut l).unwrap(); + let llt = &d.tables[LITLEN_TABLE]; + let dt = &d.tables[DIST_TABLE]; + assert_eq!(masked_lookup(llt, 0b00001100), (0, 8)); + assert_eq!(masked_lookup(llt, 0b00011110), (72, 8)); + assert_eq!(masked_lookup(llt, 0b01011110), (74, 8)); + assert_eq!(masked_lookup(llt, 0b11111101), (143, 8)); + assert_eq!(masked_lookup(llt, 0b000010011), (144, 9)); + assert_eq!(masked_lookup(llt, 0b111111111), (255, 9)); + assert_eq!(masked_lookup(llt, 0b00000000), (256, 7)); + assert_eq!(masked_lookup(llt, 0b1110100), (279, 7)); + assert_eq!(masked_lookup(llt, 0b00000011), (280, 8)); + assert_eq!(masked_lookup(llt, 0b11100011), (287, 8)); + + assert_eq!(masked_lookup(dt, 0), (0, 5)); + assert_eq!(masked_lookup(dt, 20), (5, 5)); + } + + // Only run this test with alloc enabled as it uses a larger buffer. + #[cfg(feature = "with-alloc")] + fn check_result(input: &[u8], expected_status: TINFLStatus, expected_state: State, zlib: bool) { + let mut r = DecompressorOxide::default(); + let mut output_buf = vec![0; 1024 * 32]; + let flags = if zlib { + inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER + } else { + 0 + } | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF + | TINFL_FLAG_HAS_MORE_INPUT; + let (d_status, _in_bytes, _out_bytes) = + decompress(&mut r, input, &mut output_buf, 0, flags); + assert_eq!(expected_status, d_status); + assert_eq!(expected_state, r.state); + } + + #[cfg(feature = "with-alloc")] + #[test] + fn bogus_input() { + use self::check_result as cr; + const F: TINFLStatus = TINFLStatus::Failed; + const OK: TINFLStatus = TINFLStatus::Done; + // Bad CM. + cr(&[0x77, 0x85], F, State::BadZlibHeader, true); + // Bad window size (but check is correct). + cr(&[0x88, 0x98], F, State::BadZlibHeader, true); + // Bad check bits. + cr(&[0x78, 0x98], F, State::BadZlibHeader, true); + + // Too many code lengths. (From inflate library issues) + cr( + b"M\xff\xffM*\xad\xad\xad\xad\xad\xad\xad\xcd\xcd\xcdM", + F, + State::BadDistOrLiteralTableLength, + false, + ); + + // Bad CLEN (also from inflate library issues) + cr( + b"\xdd\xff\xff*M\x94ffffffffff", + F, + State::BadDistOrLiteralTableLength, + false, + ); + + // Port of inflate coverage tests from zlib-ng + // https://github.com/Dead2/zlib-ng/blob/develop/test/infcover.c + let c = |a, b, c| cr(a, b, c, false); + + // Invalid uncompressed/raw block length. + c(&[0, 0, 0, 0, 0], F, State::BadRawLength); + // Ok empty uncompressed block. + c(&[3, 0], OK, State::DoneForever); + // Invalid block type. + c(&[6], F, State::BlockTypeUnexpected); + // Ok uncompressed block. + c(&[1, 1, 0, 0xfe, 0xff, 0], OK, State::DoneForever); + // Too many litlens, we handle this later than zlib, so this test won't + // give the same result. + // c(&[0xfc, 0, 0], F, State::BadTotalSymbols); + // Invalid set of code lengths - TODO Check if this is the correct error for this. + c(&[4, 0, 0xfe, 0xff], F, State::BadTotalSymbols); + // Invalid repeat in list of code lengths. + // (Try to repeat a non-existent code.) + c(&[4, 0, 0x24, 0x49, 0], F, State::BadCodeSizeDistPrevLookup); + // Missing end of block code (should we have a separate error for this?) - fails on further input + // c(&[4, 0, 0x24, 0xe9, 0xff, 0x6d], F, State::BadTotalSymbols); + // Invalid set of literals/lengths + c( + &[ + 4, 0x80, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x71, 0xff, 0xff, 0x93, 0x11, 0, + ], + F, + State::BadTotalSymbols, + ); + // Invalid set of distances _ needsmoreinput + // c(&[4, 0x80, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x0f, 0xb4, 0xff, 0xff, 0xc3, 0x84], F, State::BadTotalSymbols); + // Invalid distance code + c(&[2, 0x7e, 0xff, 0xff], F, State::InvalidDist); + + // Distance refers to position before the start + c( + &[0x0c, 0xc0, 0x81, 0, 0, 0, 0, 0, 0x90, 0xff, 0x6b, 0x4, 0], + F, + State::DistanceOutOfBounds, + ); + + // Trailer + // Bad gzip trailer checksum GZip header not handled by miniz_oxide + //cr(&[0x1f, 0x8b, 0x08 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x03, 0, 0, 0, 0, 0x01], F, State::BadCRC, false) + // Bad gzip trailer length + //cr(&[0x1f, 0x8b, 0x08 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0x03, 0, 0, 0, 0, 0, 0, 0, 0, 0x01], F, State::BadCRC, false) + } + + #[test] + fn empty_output_buffer_non_wrapping() { + let encoded = [ + 120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19, + ]; + let flags = TINFL_FLAG_COMPUTE_ADLER32 + | TINFL_FLAG_PARSE_ZLIB_HEADER + | TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + let mut r = DecompressorOxide::new(); + let mut output_buf: [u8; 0] = []; + // Check that we handle an empty buffer properly and not panicking. + // https://github.com/Frommi/miniz_oxide/issues/23 + let res = decompress(&mut r, &encoded, &mut output_buf, 0, flags); + assert_eq!(res, (TINFLStatus::HasMoreOutput, 4, 0)); + } + + #[test] + fn empty_output_buffer_wrapping() { + let encoded = [ + 0x73, 0x49, 0x4d, 0xcb, 0x49, 0x2c, 0x49, 0x55, 0x00, 0x11, 0x00, + ]; + let flags = TINFL_FLAG_COMPUTE_ADLER32; + let mut r = DecompressorOxide::new(); + let mut output_buf: [u8; 0] = []; + // Check that we handle an empty buffer properly and not panicking. + // https://github.com/Frommi/miniz_oxide/issues/23 + let res = decompress(&mut r, &encoded, &mut output_buf, 0, flags); + assert_eq!(res, (TINFLStatus::HasMoreOutput, 2, 0)); + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/mod.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/mod.rs new file mode 100644 index 0000000..3f787e7 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/mod.rs
@@ -0,0 +1,343 @@ +//! This module contains functionality for decompression. + +#[cfg(feature = "with-alloc")] +use crate::alloc::{boxed::Box, vec, vec::Vec}; +use ::core::usize; +#[cfg(all(feature = "std", feature = "with-alloc"))] +use std::error::Error; + +pub mod core; +mod output_buffer; +pub mod stream; +use self::core::*; + +const TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS: i32 = -4; +const TINFL_STATUS_BAD_PARAM: i32 = -3; +const TINFL_STATUS_ADLER32_MISMATCH: i32 = -2; +const TINFL_STATUS_FAILED: i32 = -1; +const TINFL_STATUS_DONE: i32 = 0; +const TINFL_STATUS_NEEDS_MORE_INPUT: i32 = 1; +const TINFL_STATUS_HAS_MORE_OUTPUT: i32 = 2; + +/// Return status codes. +#[repr(i8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum TINFLStatus { + /// More input data was expected, but the caller indicated that there was no more data, so the + /// input stream is likely truncated. + /// + /// This can't happen if you have provided the + /// [`TINFL_FLAG_HAS_MORE_INPUT`][core::inflate_flags::TINFL_FLAG_HAS_MORE_INPUT] flag to the + /// decompression. By setting that flag, you indicate more input exists but is not provided, + /// and so reaching the end of the input data without finding the end of the compressed stream + /// would instead return a [`NeedsMoreInput`][Self::NeedsMoreInput] status. + FailedCannotMakeProgress = TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS as i8, + + /// The output buffer is an invalid size; consider the `flags` parameter. + BadParam = TINFL_STATUS_BAD_PARAM as i8, + + /// The decompression went fine, but the adler32 checksum did not match the one + /// provided in the header. + Adler32Mismatch = TINFL_STATUS_ADLER32_MISMATCH as i8, + + /// Failed to decompress due to invalid data. + Failed = TINFL_STATUS_FAILED as i8, + + /// Finished decompression without issues. + /// + /// This indicates the end of the compressed stream has been reached. + Done = TINFL_STATUS_DONE as i8, + + /// The decompressor needs more input data to continue decompressing. + /// + /// This occurs when there's no more consumable input, but the end of the stream hasn't been + /// reached, and you have supplied the + /// [`TINFL_FLAG_HAS_MORE_INPUT`][core::inflate_flags::TINFL_FLAG_HAS_MORE_INPUT] flag to the + /// decompressor. Had you not supplied that flag (which would mean you were asserting that you + /// believed all the data was available) you would have gotten a + /// [`FailedCannotMakeProcess`][Self::FailedCannotMakeProgress] instead. + NeedsMoreInput = TINFL_STATUS_NEEDS_MORE_INPUT as i8, + + /// There is still pending data that didn't fit in the output buffer. + HasMoreOutput = TINFL_STATUS_HAS_MORE_OUTPUT as i8, +} + +impl TINFLStatus { + pub fn from_i32(value: i32) -> Option<TINFLStatus> { + use self::TINFLStatus::*; + match value { + TINFL_STATUS_FAILED_CANNOT_MAKE_PROGRESS => Some(FailedCannotMakeProgress), + TINFL_STATUS_BAD_PARAM => Some(BadParam), + TINFL_STATUS_ADLER32_MISMATCH => Some(Adler32Mismatch), + TINFL_STATUS_FAILED => Some(Failed), + TINFL_STATUS_DONE => Some(Done), + TINFL_STATUS_NEEDS_MORE_INPUT => Some(NeedsMoreInput), + TINFL_STATUS_HAS_MORE_OUTPUT => Some(HasMoreOutput), + _ => None, + } + } +} + +/// Struct return when decompress_to_vec functions fail. +#[cfg(feature = "with-alloc")] +#[derive(Debug)] +pub struct DecompressError { + /// Decompressor status on failure. See [TINFLStatus] for details. + pub status: TINFLStatus, + /// The currently decompressed data if any. + pub output: Vec<u8>, +} + +#[cfg(feature = "with-alloc")] +impl alloc::fmt::Display for DecompressError { + #[cold] + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.write_str(match self.status { + TINFLStatus::FailedCannotMakeProgress => "Truncated input stream", + TINFLStatus::BadParam => "Invalid output buffer size", + TINFLStatus::Adler32Mismatch => "Adler32 checksum mismatch", + TINFLStatus::Failed => "Invalid input data", + TINFLStatus::Done => "", // Unreachable + TINFLStatus::NeedsMoreInput => "Truncated input stream", + TINFLStatus::HasMoreOutput => "Output size exceeded the specified limit", + }) + } +} + +/// Implement Error trait only if std feature is requested as it requires std. +#[cfg(all(feature = "std", feature = "with-alloc"))] +impl Error for DecompressError {} + +#[cfg(feature = "with-alloc")] +fn decompress_error(status: TINFLStatus, output: Vec<u8>) -> Result<Vec<u8>, DecompressError> { + Err(DecompressError { status, output }) +} + +/// Decompress the deflate-encoded data in `input` to a vector. +/// +/// NOTE: This function will not bound the output, so if the output is large enough it can result in an out of memory error. +/// It is therefore suggested to not use this for anything other than test programs, use the functions with a specified limit, or +/// ideally streaming decompression via the [flate2](https://github.com/alexcrichton/flate2-rs) library instead. +/// +/// Returns a [`Result`] containing the [`Vec`] of decompressed data on success, and a [struct][DecompressError] containing the status and so far decompressed data if any on failure. +#[inline] +#[cfg(feature = "with-alloc")] +pub fn decompress_to_vec(input: &[u8]) -> Result<Vec<u8>, DecompressError> { + decompress_to_vec_inner(input, 0, usize::max_value()) +} + +/// Decompress the deflate-encoded data (with a zlib wrapper) in `input` to a vector. +/// +/// NOTE: This function will not bound the output, so if the output is large enough it can result in an out of memory error. +/// It is therefore suggested to not use this for anything other than test programs, use the functions with a specified limit, or +/// ideally streaming decompression via the [flate2](https://github.com/alexcrichton/flate2-rs) library instead. +/// +/// Returns a [`Result`] containing the [`Vec`] of decompressed data on success, and a [struct][DecompressError] containing the status and so far decompressed data if any on failure. +#[inline] +#[cfg(feature = "with-alloc")] +pub fn decompress_to_vec_zlib(input: &[u8]) -> Result<Vec<u8>, DecompressError> { + decompress_to_vec_inner( + input, + inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER, + usize::max_value(), + ) +} + +/// Decompress the deflate-encoded data in `input` to a vector. +/// +/// The vector is grown to at most `max_size` bytes; if the data does not fit in that size, +/// the error [struct][DecompressError] will contain the status [`TINFLStatus::HasMoreOutput`] and the data that was decompressed on failure. +/// +/// As this function tries to decompress everything in one go, it's not ideal for general use outside of tests or where the output size is expected to be small. +/// It is suggested to use streaming decompression via the [flate2](https://github.com/alexcrichton/flate2-rs) library instead. +/// +/// Returns a [`Result`] containing the [`Vec`] of decompressed data on success, and a [struct][DecompressError] on failure. +#[inline] +#[cfg(feature = "with-alloc")] +pub fn decompress_to_vec_with_limit( + input: &[u8], + max_size: usize, +) -> Result<Vec<u8>, DecompressError> { + decompress_to_vec_inner(input, 0, max_size) +} + +/// Decompress the deflate-encoded data (with a zlib wrapper) in `input` to a vector. +/// The vector is grown to at most `max_size` bytes; if the data does not fit in that size, +/// the error [struct][DecompressError] will contain the status [`TINFLStatus::HasMoreOutput`] and the data that was decompressed on failure. +/// +/// As this function tries to decompress everything in one go, it's not ideal for general use outside of tests or where the output size is expected to be small. +/// It is suggested to use streaming decompression via the [flate2](https://github.com/alexcrichton/flate2-rs) library instead. +/// +/// Returns a [`Result`] containing the [`Vec`] of decompressed data on success, and a [struct][DecompressError] on failure. +#[inline] +#[cfg(feature = "with-alloc")] +pub fn decompress_to_vec_zlib_with_limit( + input: &[u8], + max_size: usize, +) -> Result<Vec<u8>, DecompressError> { + decompress_to_vec_inner(input, inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER, max_size) +} + +/// Backend of various to-[`Vec`] decompressions. +/// +/// Returns [`Vec`] of decompressed data on success and the [error struct][DecompressError] with details on failure. +#[cfg(feature = "with-alloc")] +fn decompress_to_vec_inner( + mut input: &[u8], + flags: u32, + max_output_size: usize, +) -> Result<Vec<u8>, DecompressError> { + let flags = flags | inflate_flags::TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + let mut ret: Vec<u8> = vec![0; input.len().saturating_mul(2).min(max_output_size)]; + + let mut decomp = Box::<DecompressorOxide>::default(); + + let mut out_pos = 0; + loop { + // Wrap the whole output slice so we know we have enough of the + // decompressed data for matches. + let (status, in_consumed, out_consumed) = + decompress(&mut decomp, input, &mut ret, out_pos, flags); + out_pos += out_consumed; + + match status { + TINFLStatus::Done => { + ret.truncate(out_pos); + return Ok(ret); + } + + TINFLStatus::HasMoreOutput => { + // in_consumed is not expected to be out of bounds, + // but the check eliminates a panicking code path + if in_consumed > input.len() { + return decompress_error(TINFLStatus::HasMoreOutput, ret); + } + input = &input[in_consumed..]; + + // if the buffer has already reached the size limit, return an error + if ret.len() >= max_output_size { + return decompress_error(TINFLStatus::HasMoreOutput, ret); + } + // calculate the new length, capped at `max_output_size` + let new_len = ret.len().saturating_mul(2).min(max_output_size); + ret.resize(new_len, 0); + } + + _ => return decompress_error(status, ret), + } + } +} + +/// Decompress one or more source slices from an iterator into the output slice. +/// +/// * On success, returns the number of bytes that were written. +/// * On failure, returns the failure status code. +/// +/// This will fail if the output buffer is not large enough, but in that case +/// the output buffer will still contain the partial decompression. +/// +/// * `out` the output buffer. +/// * `it` the iterator of input slices. +/// * `zlib_header` if the first slice out of the iterator is expected to have a +/// Zlib header. Otherwise the slices are assumed to be the deflate data only. +/// * `ignore_adler32` if the adler32 checksum should be calculated or not. +pub fn decompress_slice_iter_to_slice<'out, 'inp>( + out: &'out mut [u8], + it: impl Iterator<Item = &'inp [u8]>, + zlib_header: bool, + ignore_adler32: bool, +) -> Result<usize, TINFLStatus> { + use self::core::inflate_flags::*; + + let mut it = it.peekable(); + let r = &mut DecompressorOxide::new(); + let mut out_pos = 0; + while let Some(in_buf) = it.next() { + let has_more = it.peek().is_some(); + let flags = { + let mut f = TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + if zlib_header { + f |= TINFL_FLAG_PARSE_ZLIB_HEADER; + } + if ignore_adler32 { + f |= TINFL_FLAG_IGNORE_ADLER32; + } + if has_more { + f |= TINFL_FLAG_HAS_MORE_INPUT; + } + f + }; + let (status, _input_read, bytes_written) = decompress(r, in_buf, out, out_pos, flags); + out_pos += bytes_written; + match status { + TINFLStatus::NeedsMoreInput => continue, + TINFLStatus::Done => return Ok(out_pos), + e => return Err(e), + } + } + // If we ran out of source slices without getting a `Done` from the + // decompression we can call it a failure. + Err(TINFLStatus::FailedCannotMakeProgress) +} + +#[cfg(all(test, feature = "with-alloc"))] +mod test { + use super::{ + decompress_slice_iter_to_slice, decompress_to_vec_zlib, decompress_to_vec_zlib_with_limit, + DecompressError, TINFLStatus, + }; + const ENCODED: [u8; 20] = [ + 120, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, 19, + ]; + + #[test] + fn decompress_vec() { + let res = decompress_to_vec_zlib(&ENCODED[..]).unwrap(); + assert_eq!(res.as_slice(), &b"Hello, zlib!"[..]); + } + + #[test] + fn decompress_vec_with_high_limit() { + let res = decompress_to_vec_zlib_with_limit(&ENCODED[..], 100_000).unwrap(); + assert_eq!(res.as_slice(), &b"Hello, zlib!"[..]); + } + + #[test] + fn fail_to_decompress_with_limit() { + let res = decompress_to_vec_zlib_with_limit(&ENCODED[..], 8); + match res { + Err(DecompressError { + status: TINFLStatus::HasMoreOutput, + .. + }) => (), // expected result + _ => panic!("Decompression output size limit was not enforced"), + } + } + + #[test] + fn test_decompress_slice_iter_to_slice() { + // one slice + let mut out = [0_u8; 12_usize]; + let r = + decompress_slice_iter_to_slice(&mut out, Some(&ENCODED[..]).into_iter(), true, false); + assert_eq!(r, Ok(12)); + assert_eq!(&out[..12], &b"Hello, zlib!"[..]); + + // some chunks at a time + for chunk_size in 1..13 { + // Note: because of https://github.com/Frommi/miniz_oxide/issues/110 our + // out buffer needs to have +1 byte available when the chunk size cuts + // the adler32 data off from the last actual data. + let mut out = [0_u8; 12_usize + 1]; + let r = + decompress_slice_iter_to_slice(&mut out, ENCODED.chunks(chunk_size), true, false); + assert_eq!(r, Ok(12)); + assert_eq!(&out[..12], &b"Hello, zlib!"[..]); + } + + // output buffer too small + let mut out = [0_u8; 3_usize]; + let r = decompress_slice_iter_to_slice(&mut out, ENCODED.chunks(7), true, false); + assert!(r.is_err()); + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/output_buffer.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/output_buffer.rs new file mode 100644 index 0000000..5218a807 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/output_buffer.rs
@@ -0,0 +1,60 @@ +/// A wrapper for the output slice used when decompressing. +/// +/// Using this rather than `Cursor` lets us implement the writing methods directly on +/// the buffer and lets us use a usize rather than u64 for the position which helps with +/// performance on 32-bit systems. +pub struct OutputBuffer<'a> { + slice: &'a mut [u8], + position: usize, +} + +impl<'a> OutputBuffer<'a> { + #[inline] + pub fn from_slice_and_pos(slice: &'a mut [u8], position: usize) -> OutputBuffer<'a> { + OutputBuffer { slice, position } + } + + #[inline] + pub const fn position(&self) -> usize { + self.position + } + + #[inline] + pub fn set_position(&mut self, position: usize) { + self.position = position; + } + + /// Write a byte to the current position and increment + /// + /// Assumes that there is space. + #[inline] + pub fn write_byte(&mut self, byte: u8) { + self.slice[self.position] = byte; + self.position += 1; + } + + /// Write a slice to the current position and increment + /// + /// Assumes that there is space. + #[inline] + pub fn write_slice(&mut self, data: &[u8]) { + let len = data.len(); + self.slice[self.position..self.position + len].copy_from_slice(data); + self.position += data.len(); + } + + #[inline] + pub const fn bytes_left(&self) -> usize { + self.slice.len() - self.position + } + + #[inline] + pub const fn get_ref(&self) -> &[u8] { + self.slice + } + + #[inline] + pub fn get_mut(&mut self) -> &mut [u8] { + self.slice + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/stream.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/stream.rs new file mode 100644 index 0000000..5463ab0f --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/stream.rs
@@ -0,0 +1,423 @@ +//! Extra streaming decompression functionality. +//! +//! As of now this is mainly intended for use to build a higher-level wrapper. +#[cfg(feature = "with-alloc")] +use crate::alloc::boxed::Box; +use core::{cmp, mem}; + +use crate::inflate::core::{decompress, inflate_flags, DecompressorOxide, TINFL_LZ_DICT_SIZE}; +use crate::inflate::TINFLStatus; +use crate::{DataFormat, MZError, MZFlush, MZResult, MZStatus, StreamResult}; + +/// Tag that determines reset policy of [InflateState](struct.InflateState.html) +pub trait ResetPolicy { + /// Performs reset + fn reset(&self, state: &mut InflateState); +} + +/// Resets state, without performing expensive ops (e.g. zeroing buffer) +/// +/// Note that not zeroing buffer can lead to security issues when dealing with untrusted input. +pub struct MinReset; + +impl ResetPolicy for MinReset { + fn reset(&self, state: &mut InflateState) { + state.decompressor().init(); + state.dict_ofs = 0; + state.dict_avail = 0; + state.first_call = true; + state.has_flushed = false; + state.last_status = TINFLStatus::NeedsMoreInput; + } +} + +/// Resets state and zero memory, continuing to use the same data format. +pub struct ZeroReset; + +impl ResetPolicy for ZeroReset { + #[inline] + fn reset(&self, state: &mut InflateState) { + MinReset.reset(state); + state.dict = [0; TINFL_LZ_DICT_SIZE]; + } +} + +/// Full reset of the state, including zeroing memory. +/// +/// Requires to provide new data format. +pub struct FullReset(pub DataFormat); + +impl ResetPolicy for FullReset { + #[inline] + fn reset(&self, state: &mut InflateState) { + ZeroReset.reset(state); + state.data_format = self.0; + } +} + +/// A struct that compbines a decompressor with extra data for streaming decompression. +/// +pub struct InflateState { + /// Inner decompressor struct + decomp: DecompressorOxide, + + /// Buffer of input bytes for matches. + /// TODO: Could probably do this a bit cleaner with some + /// Cursor-like class. + /// We may also look into whether we need to keep a buffer here, or just one in the + /// decompressor struct. + dict: [u8; TINFL_LZ_DICT_SIZE], + /// Where in the buffer are we currently at? + dict_ofs: usize, + /// How many bytes of data to be flushed is there currently in the buffer? + dict_avail: usize, + + first_call: bool, + has_flushed: bool, + + /// Whether the input data is wrapped in a zlib header and checksum. + /// TODO: This should be stored in the decompressor. + data_format: DataFormat, + last_status: TINFLStatus, +} + +impl Default for InflateState { + fn default() -> Self { + InflateState { + decomp: DecompressorOxide::default(), + dict: [0; TINFL_LZ_DICT_SIZE], + dict_ofs: 0, + dict_avail: 0, + first_call: true, + has_flushed: false, + data_format: DataFormat::Raw, + last_status: TINFLStatus::NeedsMoreInput, + } + } +} +impl InflateState { + /// Create a new state. + /// + /// Note that this struct is quite large due to internal buffers, and as such storing it on + /// the stack is not recommended. + /// + /// # Parameters + /// `data_format`: Determines whether the compressed data is assumed to wrapped with zlib + /// metadata. + pub fn new(data_format: DataFormat) -> InflateState { + InflateState { + data_format, + ..Default::default() + } + } + + /// Create a new state on the heap. + /// + /// # Parameters + /// `data_format`: Determines whether the compressed data is assumed to wrapped with zlib + /// metadata. + #[cfg(feature = "with-alloc")] + pub fn new_boxed(data_format: DataFormat) -> Box<InflateState> { + let mut b: Box<InflateState> = Box::default(); + b.data_format = data_format; + b + } + + /// Access the innner decompressor. + pub fn decompressor(&mut self) -> &mut DecompressorOxide { + &mut self.decomp + } + + /// Return the status of the last call to `inflate` with this `InflateState`. + pub const fn last_status(&self) -> TINFLStatus { + self.last_status + } + + /// Create a new state using miniz/zlib style window bits parameter. + /// + /// The decompressor does not support different window sizes. As such, + /// any positive (>0) value will set the zlib header flag, while a negative one + /// will not. + #[cfg(feature = "with-alloc")] + pub fn new_boxed_with_window_bits(window_bits: i32) -> Box<InflateState> { + let mut b: Box<InflateState> = Box::default(); + b.data_format = DataFormat::from_window_bits(window_bits); + b + } + + #[inline] + /// Reset the decompressor without re-allocating memory, using the given + /// data format. + pub fn reset(&mut self, data_format: DataFormat) { + self.reset_as(FullReset(data_format)); + } + + #[inline] + /// Resets the state according to specified policy. + pub fn reset_as<T: ResetPolicy>(&mut self, policy: T) { + policy.reset(self) + } +} + +/// Try to decompress from `input` to `output` with the given [`InflateState`] +/// +/// # `flush` +/// +/// Generally, the various [`MZFlush`] flags have meaning only on the compression side. They can be +/// supplied here, but the only one that has any semantic meaning is [`MZFlush::Finish`], which is a +/// signal that the stream is expected to finish, and failing to do so is an error. It isn't +/// necessary to specify it when the stream ends; you'll still get returned a +/// [`MZStatus::StreamEnd`] anyway. Other values either have no effect or cause errors. It's +/// likely that you'll almost always just want to use [`MZFlush::None`]. +/// +/// # Errors +/// +/// Returns [`MZError::Buf`] if the size of the `output` slice is empty or no progress was made due +/// to lack of expected input data, or if called with [`MZFlush::Finish`] and input wasn't all +/// consumed. +/// +/// Returns [`MZError::Data`] if this or a a previous call failed with an error return from +/// [`TINFLStatus`]; probably indicates corrupted data. +/// +/// Returns [`MZError::Stream`] when called with [`MZFlush::Full`] (meaningless on +/// decompression), or when called without [`MZFlush::Finish`] after an earlier call with +/// [`MZFlush::Finish`] has been made. +pub fn inflate( + state: &mut InflateState, + input: &[u8], + output: &mut [u8], + flush: MZFlush, +) -> StreamResult { + let mut bytes_consumed = 0; + let mut bytes_written = 0; + let mut next_in = input; + let mut next_out = output; + + if flush == MZFlush::Full { + return StreamResult::error(MZError::Stream); + } + + let mut decomp_flags = if state.data_format == DataFormat::Zlib { + inflate_flags::TINFL_FLAG_COMPUTE_ADLER32 + } else { + inflate_flags::TINFL_FLAG_IGNORE_ADLER32 + }; + + if (state.data_format == DataFormat::Zlib) + | (state.data_format == DataFormat::ZLibIgnoreChecksum) + { + decomp_flags |= inflate_flags::TINFL_FLAG_PARSE_ZLIB_HEADER; + } + + let first_call = state.first_call; + state.first_call = false; + if state.last_status == TINFLStatus::FailedCannotMakeProgress { + return StreamResult::error(MZError::Buf); + } + if (state.last_status as i32) < 0 { + return StreamResult::error(MZError::Data); + } + + if state.has_flushed && (flush != MZFlush::Finish) { + return StreamResult::error(MZError::Stream); + } + state.has_flushed |= flush == MZFlush::Finish; + + if (flush == MZFlush::Finish) && first_call { + decomp_flags |= inflate_flags::TINFL_FLAG_USING_NON_WRAPPING_OUTPUT_BUF; + + let status = decompress(&mut state.decomp, next_in, next_out, 0, decomp_flags); + let in_bytes = status.1; + let out_bytes = status.2; + let status = status.0; + + state.last_status = status; + + bytes_consumed += in_bytes; + bytes_written += out_bytes; + + let ret_status = { + if status == TINFLStatus::FailedCannotMakeProgress { + Err(MZError::Buf) + } else if (status as i32) < 0 { + Err(MZError::Data) + } else if status != TINFLStatus::Done { + state.last_status = TINFLStatus::Failed; + Err(MZError::Buf) + } else { + Ok(MZStatus::StreamEnd) + } + }; + return StreamResult { + bytes_consumed, + bytes_written, + status: ret_status, + }; + } + + if flush != MZFlush::Finish { + decomp_flags |= inflate_flags::TINFL_FLAG_HAS_MORE_INPUT; + } + + if state.dict_avail != 0 { + bytes_written += push_dict_out(state, &mut next_out); + return StreamResult { + bytes_consumed, + bytes_written, + status: Ok( + if (state.last_status == TINFLStatus::Done) && (state.dict_avail == 0) { + MZStatus::StreamEnd + } else { + MZStatus::Ok + }, + ), + }; + } + + let status = inflate_loop( + state, + &mut next_in, + &mut next_out, + &mut bytes_consumed, + &mut bytes_written, + decomp_flags, + flush, + ); + StreamResult { + bytes_consumed, + bytes_written, + status, + } +} + +fn inflate_loop( + state: &mut InflateState, + next_in: &mut &[u8], + next_out: &mut &mut [u8], + total_in: &mut usize, + total_out: &mut usize, + decomp_flags: u32, + flush: MZFlush, +) -> MZResult { + let orig_in_len = next_in.len(); + loop { + let status = decompress( + &mut state.decomp, + next_in, + &mut state.dict, + state.dict_ofs, + decomp_flags, + ); + + let in_bytes = status.1; + let out_bytes = status.2; + let status = status.0; + + state.last_status = status; + + *next_in = &next_in[in_bytes..]; + *total_in += in_bytes; + + state.dict_avail = out_bytes; + *total_out += push_dict_out(state, next_out); + + // The stream was corrupted, and decompression failed. + if (status as i32) < 0 { + return Err(MZError::Data); + } + + // The decompressor has flushed all it's data and is waiting for more input, but + // there was no more input provided. + if (status == TINFLStatus::NeedsMoreInput) && orig_in_len == 0 { + return Err(MZError::Buf); + } + + if flush == MZFlush::Finish { + if status == TINFLStatus::Done { + // There is not enough space in the output buffer to flush the remaining + // decompressed data in the internal buffer. + return if state.dict_avail != 0 { + Err(MZError::Buf) + } else { + Ok(MZStatus::StreamEnd) + }; + // No more space in the output buffer, but we're not done. + } else if next_out.is_empty() { + return Err(MZError::Buf); + } + } else { + // We're not expected to finish, so it's fine if we can't flush everything yet. + let empty_buf = next_in.is_empty() || next_out.is_empty(); + if (status == TINFLStatus::Done) || empty_buf || (state.dict_avail != 0) { + return if (status == TINFLStatus::Done) && (state.dict_avail == 0) { + // No more data left, we're done. + Ok(MZStatus::StreamEnd) + } else { + // Ok for now, still waiting for more input data or output space. + Ok(MZStatus::Ok) + }; + } + } + } +} + +fn push_dict_out(state: &mut InflateState, next_out: &mut &mut [u8]) -> usize { + let n = cmp::min(state.dict_avail, next_out.len()); + (next_out[..n]).copy_from_slice(&state.dict[state.dict_ofs..state.dict_ofs + n]); + *next_out = &mut mem::take(next_out)[n..]; + state.dict_avail -= n; + state.dict_ofs = (state.dict_ofs + (n)) & (TINFL_LZ_DICT_SIZE - 1); + n +} + +#[cfg(all(test, feature = "with-alloc"))] +mod test { + use super::{inflate, InflateState}; + use crate::{DataFormat, MZFlush, MZStatus}; + use alloc::vec; + + #[test] + fn test_state() { + let encoded = [ + 120u8, 156, 243, 72, 205, 201, 201, 215, 81, 168, 202, 201, 76, 82, 4, 0, 27, 101, 4, + 19, + ]; + let mut out = vec![0; 50]; + let mut state = InflateState::new_boxed(DataFormat::Zlib); + let res = inflate(&mut state, &encoded, &mut out, MZFlush::Finish); + let status = res.status.expect("Failed to decompress!"); + assert_eq!(status, MZStatus::StreamEnd); + assert_eq!(out[..res.bytes_written as usize], b"Hello, zlib!"[..]); + assert_eq!(res.bytes_consumed, encoded.len()); + + state.reset_as(super::ZeroReset); + out.iter_mut().map(|x| *x = 0).count(); + let res = inflate(&mut state, &encoded, &mut out, MZFlush::Finish); + let status = res.status.expect("Failed to decompress!"); + assert_eq!(status, MZStatus::StreamEnd); + assert_eq!(out[..res.bytes_written as usize], b"Hello, zlib!"[..]); + assert_eq!(res.bytes_consumed, encoded.len()); + + state.reset_as(super::MinReset); + out.iter_mut().map(|x| *x = 0).count(); + let res = inflate(&mut state, &encoded, &mut out, MZFlush::Finish); + let status = res.status.expect("Failed to decompress!"); + assert_eq!(status, MZStatus::StreamEnd); + assert_eq!(out[..res.bytes_written as usize], b"Hello, zlib!"[..]); + assert_eq!(res.bytes_consumed, encoded.len()); + assert_eq!(state.decompressor().adler32(), Some(459605011)); + + // Test state when not computing adler. + state = InflateState::new_boxed(DataFormat::ZLibIgnoreChecksum); + out.iter_mut().map(|x| *x = 0).count(); + let res = inflate(&mut state, &encoded, &mut out, MZFlush::Finish); + let status = res.status.expect("Failed to decompress!"); + assert_eq!(status, MZStatus::StreamEnd); + assert_eq!(out[..res.bytes_written as usize], b"Hello, zlib!"[..]); + assert_eq!(res.bytes_consumed, encoded.len()); + // Not computed, so should be Some(1) + assert_eq!(state.decompressor().adler32(), Some(1)); + // Should still have the checksum read from the header file. + assert_eq!(state.decompressor().adler32_header(), Some(459605011)) + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/lib.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/lib.rs new file mode 100644 index 0000000..6cd4ed3 --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/lib.rs
@@ -0,0 +1,211 @@ +//! A pure rust replacement for the [miniz](https://github.com/richgel999/miniz) +//! DEFLATE/zlib encoder/decoder. +//! Used a rust back-end for the +//! [flate2](https://github.com/alexcrichton/flate2-rs) crate. +//! +#![cfg_attr( + feature = "with-alloc", + doc = r##" +# Usage +## Simple compression/decompression: +``` rust + +use miniz_oxide::inflate::decompress_to_vec; +use miniz_oxide::deflate::compress_to_vec; + +fn roundtrip(data: &[u8]) { + let compressed = compress_to_vec(data, 6); + let decompressed = decompress_to_vec(compressed.as_slice()).expect("Failed to decompress!"); +# let _ = decompressed; +} + +# roundtrip(b"Test_data test data lalalal blabla"); +"## +)] +#![forbid(unsafe_code)] +#![cfg_attr(not(feature = "std"), no_std)] + +#[cfg(feature = "with-alloc")] +extern crate alloc; + +#[cfg(feature = "with-alloc")] +pub mod deflate; +pub mod inflate; +mod shared; + +pub use crate::shared::update_adler32 as mz_adler32_oxide; +pub use crate::shared::{MZ_ADLER32_INIT, MZ_DEFAULT_WINDOW_BITS}; + +/// A list of flush types. +/// +/// See <http://www.bolet.org/~pornin/deflate-flush.html> for more in-depth info. +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum MZFlush { + /// Don't force any flushing. + /// Used when more input data is expected. + None = 0, + /// Zlib partial flush. + /// Currently treated as [`Sync`]. + Partial = 1, + /// Finish compressing the currently buffered data, and output an empty raw block. + /// Has no use in decompression. + Sync = 2, + /// Same as [`Sync`], but resets the compression dictionary so that further compressed + /// data does not depend on data compressed before the flush. + /// + /// Has no use in decompression, and is an error to supply in that case. + Full = 3, + /// Attempt to flush the remaining data and end the stream. + Finish = 4, + /// Not implemented. + Block = 5, +} + +impl MZFlush { + /// Create an MZFlush value from an integer value. + /// + /// Returns `MZError::Param` on invalid values. + pub fn new(flush: i32) -> Result<Self, MZError> { + match flush { + 0 => Ok(MZFlush::None), + 1 | 2 => Ok(MZFlush::Sync), + 3 => Ok(MZFlush::Full), + 4 => Ok(MZFlush::Finish), + _ => Err(MZError::Param), + } + } +} + +/// A list of miniz successful status codes. +/// +/// These are emitted as the [`Ok`] side of a [`MZResult`] in the [`StreamResult`] returned from +/// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`]. +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum MZStatus { + /// Operation succeeded. + /// + /// Some data was decompressed or compressed; see the byte counters in the [`StreamResult`] for + /// details. + Ok = 0, + + /// Operation succeeded and end of deflate stream was found. + /// + /// X-ref [`TINFLStatus::Done`][inflate::TINFLStatus::Done] or + /// [`TDEFLStatus::Done`][deflate::core::TDEFLStatus::Done] for `inflate` or `deflate` + /// respectively. + StreamEnd = 1, + + /// Unused + NeedDict = 2, +} + +/// A list of miniz failed status codes. +/// +/// These are emitted as the [`Err`] side of a [`MZResult`] in the [`StreamResult`] returned from +/// [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`]. +#[repr(i32)] +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum MZError { + /// Unused + ErrNo = -1, + + /// General stream error. + /// + /// See [`inflate::stream::inflate()`] docs for details of how it can occur there. + /// + /// See [`deflate::stream::deflate()`] docs for how it can in principle occur there, though it's + /// believed impossible in practice. + Stream = -2, + + /// Error in inflation; see [`inflate::stream::inflate()`] for details. + /// + /// Not returned from [`deflate::stream::deflate()`]. + Data = -3, + + /// Unused + Mem = -4, + + /// Buffer-related error. + /// + /// See the docs of [`deflate::stream::deflate()`] or [`inflate::stream::inflate()`] for details + /// of when it would trigger in the one you're using. + Buf = -5, + + /// Unused + Version = -6, + + /// Bad parameters. + /// + /// This can be returned from [`deflate::stream::deflate()`] in the case of bad parameters. See + /// [`TDEFLStatus::BadParam`][deflate::core::TDEFLStatus::BadParam]. + Param = -10_000, +} + +/// How compressed data is wrapped. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum DataFormat { + /// Wrapped using the [zlib](http://www.zlib.org/rfc-zlib.html) format. + Zlib, + /// Zlib wrapped but ignore and don't compute the adler32 checksum. + /// Currently only used for inflate, behaves the same as Zlib for compression. + ZLibIgnoreChecksum, + /// Raw DEFLATE. + Raw, +} + +impl DataFormat { + pub fn from_window_bits(window_bits: i32) -> DataFormat { + if window_bits > 0 { + DataFormat::Zlib + } else { + DataFormat::Raw + } + } + + pub fn to_window_bits(self) -> i32 { + match self { + DataFormat::Zlib | DataFormat::ZLibIgnoreChecksum => shared::MZ_DEFAULT_WINDOW_BITS, + DataFormat::Raw => -shared::MZ_DEFAULT_WINDOW_BITS, + } + } +} + +/// `Result` alias for all miniz status codes both successful and failed. +pub type MZResult = Result<MZStatus, MZError>; + +/// A structure containing the result of a call to the inflate or deflate streaming functions. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub struct StreamResult { + /// The number of bytes consumed from the input slice. + pub bytes_consumed: usize, + /// The number of bytes written to the output slice. + pub bytes_written: usize, + /// The return status of the call. + pub status: MZResult, +} + +impl StreamResult { + #[inline] + pub const fn error(error: MZError) -> StreamResult { + StreamResult { + bytes_consumed: 0, + bytes_written: 0, + status: Err(error), + } + } +} + +impl core::convert::From<StreamResult> for MZResult { + fn from(res: StreamResult) -> Self { + res.status + } +} + +impl core::convert::From<&StreamResult> for MZResult { + fn from(res: &StreamResult) -> Self { + res.status + } +}
diff --git a/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/shared.rs b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/shared.rs new file mode 100644 index 0000000..9b8ac1a --- /dev/null +++ b/third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/shared.rs
@@ -0,0 +1,25 @@ +#[doc(hidden)] +pub const MZ_ADLER32_INIT: u32 = 1; + +#[doc(hidden)] +pub const MZ_DEFAULT_WINDOW_BITS: i32 = 15; + +pub const HUFFMAN_LENGTH_ORDER: [u8; 19] = [ + 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15, +]; + +#[doc(hidden)] +#[cfg(not(feature = "simd"))] +pub fn update_adler32(adler: u32, data: &[u8]) -> u32 { + let mut hash = adler2::Adler32::from_checksum(adler); + hash.write_slice(data); + hash.checksum() +} + +#[doc(hidden)] +#[cfg(feature = "simd")] +pub fn update_adler32(adler: u32, data: &[u8]) -> u32 { + let mut hash = simd_adler32::Adler32::from_checksum(adler); + hash.write(data); + hash.finish() +}
diff --git a/third_party/rust/flate2/v1/BUILD.gn b/third_party/rust/flate2/v1/BUILD.gn index c00ab33..ef21eeb 100644 --- a/third_party/rust/flate2/v1/BUILD.gn +++ b/third_party/rust/flate2/v1/BUILD.gn
@@ -13,34 +13,34 @@ epoch = "1" crate_type = "rlib" crate_root = - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/lib.rs" + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/lib.rs" sources = [ - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/bufreader.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/crc.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/bufread.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/mod.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/read.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/deflate/write.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/c.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/mod.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/ffi/rust.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/bufread.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/mod.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/read.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/gz/write.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/lib.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/mem.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zio.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/bufread.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/mod.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/read.rs", - "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/src/zlib/write.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/bufreader.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/crc.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/bufread.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/mod.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/read.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/deflate/write.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/c.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/mod.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/ffi/rust.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/bufread.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/mod.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/read.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/gz/write.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/lib.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/mem.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zio.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/bufread.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/mod.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/read.rs", + "//third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/src/zlib/write.rs", ] inputs = [] build_native_rust_unit_tests = false edition = "2018" - cargo_pkg_version = "1.0.31" + cargo_pkg_version = "1.0.33" cargo_pkg_authors = "Alex Crichton <alex@alexcrichton.com>, Josh Triplett <josh@joshtriplett.org>" cargo_pkg_name = "flate2" cargo_pkg_description = "DEFLATE compression and decompression exposed as Read/BufRead/Write streams. Supports miniz_oxide and multiple zlib implementations. Supports zlib, gzip, and raw deflate streams." @@ -52,7 +52,7 @@ proc_macro_configs += [ "//build/config/compiler:no_chromium_code" ] deps = [ "//third_party/rust/crc32fast/v1:lib", - "//third_party/rust/miniz_oxide/v0_7:lib", + "//third_party/rust/miniz_oxide/v0_8:lib", ] features = [ "any_impl",
diff --git a/third_party/rust/flate2/v1/README.chromium b/third_party/rust/flate2/v1/README.chromium index 1642c6a..bbc195d 100644 --- a/third_party/rust/flate2/v1/README.chromium +++ b/third_party/rust/flate2/v1/README.chromium
@@ -4,9 +4,9 @@ Supports miniz_oxide and multiple zlib implementations. Supports zlib, gzip, and raw deflate streams. -Version: 1.0.31 +Version: 1.0.33 Security Critical: yes Shipped: yes License: Apache 2.0 -License File: //third_party/rust/chromium_crates_io/vendor/flate2-1.0.31/LICENSE-APACHE -Revision: 93c81772305a102f1ec846bd12713dd7bf1e3f04 +License File: //third_party/rust/chromium_crates_io/vendor/flate2-1.0.33/LICENSE-APACHE +Revision: 50852c6138789b255d5b2dfea2abb1a1dda99e99
diff --git a/third_party/rust/miniz_oxide/v0_8/BUILD.gn b/third_party/rust/miniz_oxide/v0_8/BUILD.gn new file mode 100644 index 0000000..08acefa --- /dev/null +++ b/third_party/rust/miniz_oxide/v0_8/BUILD.gn
@@ -0,0 +1,49 @@ +# 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. + +# @generated from third_party/rust/chromium_crates_io/BUILD.gn.hbs by +# tools/crates/gnrt. +# Do not edit! + +import("//build/rust/cargo_crate.gni") + +cargo_crate("lib") { + crate_name = "miniz_oxide" + epoch = "0.8" + crate_type = "rlib" + crate_root = "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/lib.rs" + sources = [ + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/buffer.rs", + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/core.rs", + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/mod.rs", + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/deflate/stream.rs", + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/core.rs", + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/mod.rs", + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/output_buffer.rs", + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/inflate/stream.rs", + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/lib.rs", + "//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/src/shared.rs", + ] + inputs = [] + + build_native_rust_unit_tests = false + edition = "2021" + cargo_pkg_version = "0.8.0" + cargo_pkg_authors = "Frommi <daniil.liferenko@gmail.com>, oyvindln <oyvindln@users.noreply.github.com>" + cargo_pkg_name = "miniz_oxide" + cargo_pkg_description = "DEFLATE compression and decompression library rewritten in Rust based on miniz" + library_configs -= [ "//build/config/compiler:chromium_code" ] + library_configs += [ "//build/config/compiler:no_chromium_code" ] + executable_configs -= [ "//build/config/compiler:chromium_code" ] + executable_configs += [ "//build/config/compiler:no_chromium_code" ] + proc_macro_configs -= [ "//build/config/compiler:chromium_code" ] + proc_macro_configs += [ "//build/config/compiler:no_chromium_code" ] + deps = [ "//third_party/rust/adler2/v2:lib" ] + features = [ "with-alloc" ] + + # Only for usage from third-party crates. Add the crate to + # //third_party/rust/chromium_crates_io/Cargo.toml to use + # it from first-party code. + visibility = [ "//third_party/rust/*" ] +}
diff --git a/third_party/rust/miniz_oxide/v0_8/README.chromium b/third_party/rust/miniz_oxide/v0_8/README.chromium new file mode 100644 index 0000000..2e3ce620 --- /dev/null +++ b/third_party/rust/miniz_oxide/v0_8/README.chromium
@@ -0,0 +1,9 @@ +Name: miniz_oxide +URL: https://crates.io/crates/miniz_oxide +Description: DEFLATE compression and decompression library rewritten in Rust based on miniz +Version: 0.8.0 +Security Critical: yes +Shipped: yes +License: Apache 2.0 +License File: //third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE,//third_party/rust/chromium_crates_io/vendor/miniz_oxide-0.8.0/LICENSE-APACHE.md +Revision: 58cf901875b2a5b3c9eeb844bd534f6cee54f847
diff --git a/third_party/skia b/third_party/skia index cd3d3da..f1b130c 160000 --- a/third_party/skia +++ b/third_party/skia
@@ -1 +1 @@ -Subproject commit cd3d3daafe559192288d12cde5722034b935df7f +Subproject commit f1b130c74c5327c8d4919d74fd4efc80890c77e8
diff --git a/third_party/vulkan-deps b/third_party/vulkan-deps index 23ed8d7..3564f95 160000 --- a/third_party/vulkan-deps +++ b/third_party/vulkan-deps
@@ -1 +1 @@ -Subproject commit 23ed8d76c58a57c4f14b0aba6197d5631a844f00 +Subproject commit 3564f95cf10c7febe85d145baf229a3f91ef7447
diff --git a/third_party/vulkan-validation-layers/src b/third_party/vulkan-validation-layers/src index 13c0c4d..b87d71c 160000 --- a/third_party/vulkan-validation-layers/src +++ b/third_party/vulkan-validation-layers/src
@@ -1 +1 @@ -Subproject commit 13c0c4dc619d165b05061702a3c8eb604d21efa4 +Subproject commit b87d71c2177c08e5ad43c15d1fb8b3f60926c023
diff --git a/tools/cast3p/runtime.version b/tools/cast3p/runtime.version index e7dd467..5ce6c08 100644 --- a/tools/cast3p/runtime.version +++ b/tools/cast3p/runtime.version
@@ -1 +1 @@ -431650 +432990
diff --git a/tools/mb/mb.py b/tools/mb/mb.py index 516de39..23b188c 100755 --- a/tools/mb/mb.py +++ b/tools/mb/mb.py
@@ -82,8 +82,9 @@ self.chromium_src_dir = CHROMIUM_SRC_DIR self.default_config = os.path.join(self.chromium_src_dir, 'tools', 'mb', 'mb_config.pyl') - self.default_isolate_map = os.path.join(self.chromium_src_dir, 'testing', - 'buildbot', 'gn_isolate_map.pyl') + self.default_isolate_map = os.path.join(self.chromium_src_dir, 'infra', + 'config', 'generated', 'testing', + 'gn_isolate_map.pyl') self.executable = sys.executable self.platform = sys.platform self.sep = os.sep @@ -1524,8 +1525,7 @@ else: labels.append(isolate_map[target]['label']) else: - err += ('target "%s" not found in ' - '//testing/buildbot/gn_isolate_map.pyl\n' % target) + err += f'target "{target}" not found in gn_isolate_map.pyl\n' return err, labels
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index 4e48ad5..9f66f54 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -15856,6 +15856,7 @@ <int value="-1981692093" label="SafeBrowsingPasswordProtectionForSignedInUsers:enabled"/> <int value="-1980328793" label="trace-upload-url"/> + <int value="-1978938699" label="PwaNavigationCapturing:disabled"/> <int value="-1978625006" label="PcieBillboardNotification:disabled"/> <int value="-1978116081" label="SeaPen:disabled"/> <int value="-1978003156" label="EnableExtensibleEnterpriseSSO:disabled"/> @@ -16607,6 +16608,7 @@ <int value="-1655535052" label="enable-pointer-events"/> <int value="-1655495554" label="NtpCalendarModule:disabled"/> <int value="-1655281250" label="DefaultCalculatorWebApp:enabled"/> + <int value="-1654902085" label="PwaNavigationCapturing:enabled"/> <int value="-1654476091" label="cast-streaming-force-enable-hardware-vp8"/> <int value="-1654344175" label="disable-extension-info-dialog"/> <int value="-1653991213" label="CrossOriginIsolated:disabled"/> @@ -19719,7 +19721,6 @@ <int value="-360453785" label="LeftToRightUrls:disabled"/> <int value="-360038744" label="invert-viewport-scroll-order"/> <int value="-359886807" label="AppPreloadService:disabled"/> - <int value="-359878424" label="AntiFingerprintingSetting:disabled"/> <int value="-359452972" label="ProjectorV2:enabled"/> <int value="-359331504" label="InputDeviceSettingsSplit:enabled"/> <int value="-357464687" label="SharingPreferVapid:enabled"/> @@ -21301,7 +21302,6 @@ <int value="299792415" label="OmniboxSuggestionTransparencyOptions:enabled"/> <int value="300095239" label="FCMInvalidations:enabled"/> <int value="300870732" label="ShelfDimming:disabled"/> - <int value="301196825" label="AntiFingerprintingSetting:enabled"/> <int value="301513718" label="PrivacySandboxSettings4:enabled"/> <int value="301536977" label="DetailedLanguageSettings:enabled"/> <int value="301630312" label="ForcedColors:disabled"/> @@ -22659,7 +22659,6 @@ <int value="864024033" label="IsolatePrerendersMustProbeOrigin:enabled"/> <int value="865096806" label="CrosMall:disabled"/> <int value="865952257" label="CrOSLateBootBluetoothTelephony:disabled"/> - <int value="866313743" label="FingerprintingProtectionSetting:enabled"/> <int value="866536801" label="PDFViewerUpdate:disabled"/> <int value="867061581" label="AllowWindowDragUsingSystemDragDrop:enabled"/> <int value="867512869" label="mark-non-secure-as"/> @@ -22739,7 +22738,6 @@ <int value="900560795" label="HttpsFirstModeV2ForTypicallySecureUsers:disabled"/> <int value="900614020" label="ContentSuggestionsShowSummary:disabled"/> - <int value="900642009" label="FingerprintingProtectionSetting:disabled"/> <int value="902209599" label="ShelfHotseat:enabled"/> <int value="902442795" label="time-before-discard-in-minutes"/> <int value="902649149" label="ArcGhostWindowNewStyle:enabled"/>
diff --git a/tools/metrics/histograms/metadata/ash/enums.xml b/tools/metrics/histograms/metadata/ash/enums.xml index 5cfa03e..c89e627 100644 --- a/tools/metrics/histograms/metadata/ash/enums.xml +++ b/tools/metrics/histograms/metadata/ash/enums.xml
@@ -218,6 +218,7 @@ <enum name="AuthInputType"> <int value="0" label="Password"/> <int value="1" label="PIN"/> + <int value="2" label="Fingerprint"/> </enum> <enum name="AuthMethod">
diff --git a/tools/metrics/histograms/metadata/ash/histograms.xml b/tools/metrics/histograms/metadata/ash/histograms.xml index 4ca0b54..e7fa1be 100644 --- a/tools/metrics/histograms/metadata/ash/histograms.xml +++ b/tools/metrics/histograms/metadata/ash/histograms.xml
@@ -801,6 +801,16 @@ </summary> </histogram> +<histogram name="Ash.Auth.ActiveSessionAuthFingerprintAttempt" units="attempts" + expires_after="2025-08-02"> + <owner>iscsi@google.com</owner> + <owner>cros-lurs@google.com</owner> + <summary> + The number of fingerprint attempts while the active session auth dialog was + opened. Recorded when the active session auth dialog closes. + </summary> +</histogram> + <histogram name="Ash.Auth.ActiveSessionAuthOpenDuration" units="ms" expires_after="2025-08-02"> <owner>iscsi@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/bluetooth/enums.xml b/tools/metrics/histograms/metadata/bluetooth/enums.xml index 4ecbc126..7a867b1f 100644 --- a/tools/metrics/histograms/metadata/bluetooth/enums.xml +++ b/tools/metrics/histograms/metadata/bluetooth/enums.xml
@@ -71,6 +71,8 @@ <int value="19" label="JNI environment error"/> <int value="20" label="JNI thread attach error"/> <int value="21" label="Wakelock error"/> + <int value="22" label="Unexpected state"/> + <int value="23" label="Socket error"/> </enum> <enum name="BluetoothConnectToServiceError"> @@ -100,6 +102,8 @@ <int value="16" label="JNI environment error"/> <int value="17" label="JNI thread attach error"/> <int value="18" label="Wakelock error"/> + <int value="19" label="Unexpected state"/> + <int value="20" label="Socket error"/> </enum> <enum name="BluetoothDeviceConnectToServiceFailureReason"> @@ -1456,6 +1460,8 @@ <int value="18" label="JNI environment error"/> <int value="19" label="JNI thread attach error"/> <int value="20" label="Wakelock error"/> + <int value="21" label="Unexpected state"/> + <int value="22" label="Socket error"/> </enum> <enum name="WebBluetoothGATTOperationOutcome">
diff --git a/tools/metrics/histograms/metadata/nearby/enums.xml b/tools/metrics/histograms/metadata/nearby/enums.xml index 3bda8c49..8e54d221 100644 --- a/tools/metrics/histograms/metadata/nearby/enums.xml +++ b/tools/metrics/histograms/metadata/nearby/enums.xml
@@ -62,6 +62,8 @@ <int value="18" label="JNI Environment"/> <int value="19" label="JNI Thread Attach"/> <int value="20" label="Wakelock"/> + <int value="21" label="Unexpected State"/> + <int value="22" label="Socket Error"/> </enum> <enum name="NearbyConnectionsGattResult">
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml index b0ce923..c82fb5b 100644 --- a/tools/metrics/histograms/metadata/net/histograms.xml +++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -751,16 +751,6 @@ </summary> </histogram> -<histogram name="Net.CertVerifier.PathBuilderIterationCount" units="units" - expires_after="2024-09-01"> - <owner>mattm@chromium.org</owner> - <owner>rsleevi@chromium.org</owner> - <summary> - When using the builtin cert verifier, records the number of iterations taken - during path building for each attempted verification. - </summary> -</histogram> - <histogram name="Net.CertVerifier_First_Job_Latency" units="ms" expires_after="never"> <!-- expires-never: core cert verifier metric; monitored by Chirps -->
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 86d92c4c..086d8125 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -6145,6 +6145,17 @@ </summary> </histogram> +<histogram name="MPArch.ChildProcessLaunchActivelyInParallel" units="threads" + expires_after="2025-09-01"> + <owner>ajgo@chromium.org</owner> + <owner>src/sandbox/policy/win/OWNERS</owner> + <summary> + The number of process creation threads that are actively spawning sub + processes. Recorded at the start of each process launch. Only recorded on + Windows and when parallel process launching is enabled. + </summary> +</histogram> + <histogram name="MPArch.ChildProcessLauncher.{Event}" units="ms" expires_after="2025-01-05"> <owner>ajgo@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/page/enums.xml b/tools/metrics/histograms/metadata/page/enums.xml index 64fdd01..ace289b6 100644 --- a/tools/metrics/histograms/metadata/page/enums.xml +++ b/tools/metrics/histograms/metadata/page/enums.xml
@@ -122,16 +122,6 @@ tracking a relevant committed load"/> </enum> -<enum name="LargestContentfulPaintImageLoadStartLessThanDocumentTtfbCauses"> - <int value="0" label="Unknown"/> - <int value="1" label="Image is loaded from memory cache"/> - <int value="2" - label="Image is preloaded after receiving a 103 (Early Hints) response"/> - <int value="3" - label="Image is loaded from memory and preloaded after receiving a 103 - (Early Hints) response"/> -</enum> - <enum name="LcppPredictResult"> <int value="0" label="Success">Prediction is success.</int> <int value="1" label="Failure: No hit">
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml index 16a83bb..95ae59e7f 100644 --- a/tools/metrics/histograms/metadata/page/histograms.xml +++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -842,7 +842,7 @@ <histogram name="PageLoad.Clients.FencedFrames.InteractiveTiming.FirstInputDelay4" - units="ms" expires_after="2025-02-23"> + units="ms" expires_after="2025-10-08"> <owner>lbrady@google.com</owner> <owner>shivanisha@chromium.org</owner> <owner>dom@chromium.org</owner> @@ -870,7 +870,7 @@ <histogram name="PageLoad.Clients.FencedFrames.LayoutInstability.CumulativeShiftScore.MainFrame" - units="scorex10" expires_after="2024-10-08"> + units="scorex10" expires_after="2025-10-08"> <owner>lbrady@google.com</owner> <owner>shivanisha@chromium.org</owner> <owner>dom@chromium.org</owner> @@ -896,7 +896,7 @@ <histogram name="PageLoad.Clients.FencedFrames.PaintTiming.NavigationToFirstImagePaint" - units="ms" expires_after="2024-10-08"> + units="ms" expires_after="2025-10-08"> <owner>lbrady@google.com</owner> <owner>shivanisha@chromium.org</owner> <owner>dom@chromium.org</owner> @@ -3803,59 +3803,6 @@ </token> </histogram> -<histogram - name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint.ImageLCPLessThanLoadEnd" - enum="Boolean" expires_after="2024-12-30"> - <owner>haoliuk@chromium.org</owner> - <owner>speed-metrics-dev@chromium.org</owner> - <summary> - Records the count of cases where an LCP image candidate has an LCP less than - its LoadEnd. This is counted once per LCP candidate in the - PageLoadTracker::OnTimingChanged() method when the LCP candiate changes. - </summary> -</histogram> - -<histogram - name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint.ImageLoadEndLessThanLoadStart" - enum="Boolean" expires_after="2024-08-24"> - <owner>haoliuk@chromium.org</owner> - <owner>speed-metrics-dev@chromium.org</owner> - <summary> - Records the count of cases where an LCP image candidate has a LoadEnd less - than its LoadStart. This is counted once per LCP candidate in the - PageLoadTracker::OnTimingChanged() method when the LCP candiate changes. - </summary> -</histogram> - -<histogram - name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint.ImageLoadStartLessThanDocumentTTFB" - enum="Boolean" expires_after="2024-12-30"> - <owner>haoliuk@chromium.org</owner> - <owner>speed-metrics-dev@chromium.org</owner> - <summary> - Records the count of cases where an LCP image candidate has a LoadStart less - than the document TTFB. This is counted once per LCP candidate in the - PageLoadTracker::OnTimingChanged() method when the LCP candiate changes. - </summary> -</histogram> - -<histogram - name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint.ImageLoadStartLessThanDocumentTtfbCauses" - enum="LargestContentfulPaintImageLoadStartLessThanDocumentTtfbCauses" - expires_after="2024-12-30"> - <owner>haoliuk@chromium.org</owner> - <owner>speed-metrics-dev@chromium.org</owner> - <summary> - Records the count of 'causes' of LCP image load timings being less than - document Time-To-First-Byte(TTFB) to diagnose crbug.com/1431906. This is - recorded at most once per image, only when the image's load start was - recorded as being before its associated document's TTFB. Recorded in the - page load tracker when the LCP candidate changes. Unexplained instances are - recorded in the 'Unknown' bucket, and these are expected to diminish over - time as additional causes are uncovered. - </summary> -</histogram> - <histogram name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint2" units="ms" expires_after="2025-01-05"> <owner>iclelland@chromium.org</owner>
diff --git a/tools/metrics/ukm/ukm.xml b/tools/metrics/ukm/ukm.xml index 4f46a24..9ad3c69b9b 100644 --- a/tools/metrics/ukm/ukm.xml +++ b/tools/metrics/ukm/ukm.xml
@@ -8136,6 +8136,31 @@ </metric> </event> +<event name="FamilyLinkUser.ReauthenticationInterstitial"> + <owner>chrome-kids-eng@google.com</owner> + <summary> + These metrics are logged when an unauthenticated Family Link user tries to + navigate to YouTube in the main frame, prompting a re-authentication + interstitial. + </summary> + <metric name="InterstitialShown" enum="BooleanHit"> + <summary> + Recorded when the re-authentication interstitial is displayed. + </summary> + </metric> + <metric name="ReauthenticationCompleted" enum="BooleanHit"> + <summary> + Recorded when users successfully re-authenticates and can continue + navigation, and vice-versa for failed reauthentication. + </summary> + </metric> + <metric name="ReauthenticationStarted" enum="BooleanHit"> + <summary> + Recorded when users initiate re-authentication from the interstitial. + </summary> + </metric> +</event> + <event name="FastCheckout.FormStatus"> <owner>bwolfgang@google.com</owner> <owner>jkeitel@google.com</owner>
diff --git a/tools/perf/benchmark.csv b/tools/perf/benchmark.csv index 438ae098..6a16828 100644 --- a/tools/perf/benchmark.csv +++ b/tools/perf/benchmark.csv
@@ -79,6 +79,7 @@ system_health.memory_desktop,"pasko@chromium.org, lizeb@chromium.org",,https://bit.ly/system-health-benchmarks,"2016,2018,2019,2020,2021,accessibility,emerging_market,health_check,images,infinite_scroll,international,javascript_heavy,keyboard_input,scroll,wasm,webgl" system_health.memory_mobile,"pasko@chromium.org, lizeb@chromium.org",,https://bit.ly/system-health-benchmarks,"2016,2018,2019,2020,2021,2023,emerging_market,health_check,images,infinite_scroll,international,javascript_heavy" system_health.webview_startup,"oksamyt@chromium.org, torne@chromium.org",Mobile>WebView>Perf,,2016 +tint_benchmark,"jrprice@google.com, dsinclair@chromium.org",Dawn>Tint,https://dawn.googlesource.com/dawn/+/HEAD/docs/tint/benchmark.md, tracing_perftests,"eseckler@chromium.org, khokhlov@chromium.org, kraskevich@chromium.org",Speed>Tracing,, v8.browsing_desktop,"cbruni@chromium.org, vahl@chromium.org, almuthanna@chromium.org",Blink>JavaScript,https://bit.ly/system-health-v8-benchmarks,"2016,2018,2019,2020,2021,health_check,images,infinite_scroll,international,javascript_heavy,keyboard_input,wasm,webgl" v8.browsing_desktop-future,"cbruni@chromium.org, almuthanna@chromium.org",Blink>JavaScript,https://bit.ly/system-health-v8-benchmarks,"2016,2018,2019,2020,2021,health_check,images,infinite_scroll,international,javascript_heavy,keyboard_input,wasm,webgl"
diff --git a/tools/perf/core/bot_platforms.py b/tools/perf/core/bot_platforms.py index e2b8ed7..965a3c2 100644 --- a/tools/perf/core/bot_platforms.py +++ b/tools/perf/core/bot_platforms.py
@@ -335,6 +335,10 @@ estimated_runtime=estimated_runtime) +def _tint_benchmark(estimated_runtime=180): + return ExecutableConfig('tint_benchmark', estimated_runtime=estimated_runtime) + + def _load_library_perf_tests(estimated_runtime=3): return ExecutableConfig('load_library_perf_tests', estimated_runtime=estimated_runtime) @@ -483,6 +487,7 @@ # TODO(crbug.com/40562709): Add views_perftests. _base_perftests(200), _load_library_perf_tests(), + _tint_benchmark(), _tracing_perftests(5), ]) _MAC_HIGH_END_BENCHMARK_CONFIGS = PerfSuite(OFFICIAL_BENCHMARK_CONFIGS).Remove([ @@ -492,6 +497,7 @@ _MAC_HIGH_END_EXECUTABLE_CONFIGS = frozenset([ _base_perftests(300), # _dawn_perf_tests(330), # b/332611618 + _tint_benchmark(), _views_perftests(), ]) _MAC_LOW_END_BENCHMARK_CONFIGS = PerfSuite(OFFICIAL_BENCHMARK_CONFIGS).Remove([ @@ -535,6 +541,7 @@ _MAC_M1_MINI_2020_EXECUTABLE_CONFIGS = frozenset([ _base_perftests(300), _dawn_perf_tests(330), + _tint_benchmark(), _views_perftests(), ]) _MAC_M2_PRO_BENCHMARK_CONFIGS = PerfSuite(OFFICIAL_BENCHMARK_CONFIGS).Remove([ @@ -581,6 +588,7 @@ _base_perftests(200), _components_perftests(125), _dawn_perf_tests(600), + _tint_benchmark(), _views_perftests(), ]) _ANDROID_GO_BENCHMARK_CONFIGS = PerfSuite([ @@ -626,6 +634,7 @@ ]) _ANDROID_PIXEL6_EXECUTABLE_CONFIGS = frozenset([ _components_perftests(60), + _tint_benchmark(), ]) _ANDROID_PIXEL6_PGO_EXECUTABLE_CONFIGS = frozenset([ _components_perftests(60),
diff --git a/tools/perf/core/perf_data_generator.py b/tools/perf/core/perf_data_generator.py index 2200d0c..d1628ab8 100755 --- a/tools/perf/core/perf_data_generator.py +++ b/tools/perf/core/perf_data_generator.py
@@ -1432,6 +1432,10 @@ 'enga@chromium.org', 'Dawn', 'https://dawn.googlesource.com/dawn/+/HEAD/src/tests/perf_tests/README.md' ), + 'tint_benchmark': + BenchmarkMetadata( + 'jrprice@google.com, dsinclair@chromium.org', 'Dawn>Tint', + 'https://dawn.googlesource.com/dawn/+/HEAD/docs/tint/benchmark.md'), } RESOURCE_SIZES_METADATA = BenchmarkMetadata(
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json index 3ce2679..7e3446f3 100644 --- a/tools/perf/core/perfetto_binary_roller/binary_deps.json +++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -5,8 +5,8 @@ "full_remote_path": "perfetto-luci-artifacts/v47.0/linux-arm64/trace_processor_shell" }, "win": { - "hash": "f42f63bec70a482cd64a6ba166c5dee5e5b5b00a", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/b43c9c0bcffd352177f4e03d47723c120ba88426/trace_processor_shell.exe" + "hash": "aa8b2c17872a01e529cb3afbeab858ec670dced1", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/win/77d945596576841ab4cd882de842c8a0d0905cd6/trace_processor_shell.exe" }, "linux_arm": { "hash": "b5e5fcaf0e8ae5af509255c50c116d2ad6308221", @@ -21,8 +21,8 @@ "full_remote_path": "perfetto-luci-artifacts/v47.0/mac-arm64/trace_processor_shell" }, "linux": { - "hash": "93b2e3971a842c53c3803e860825be038a6308e2", - "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/b43c9c0bcffd352177f4e03d47723c120ba88426/trace_processor_shell" + "hash": "7777c995f6a1cdb48cf51eb69ab314a080081e88", + "full_remote_path": "chromium-telemetry/perfetto_binaries/trace_processor_shell/linux/55f3db55b84b33f926f6996d7baca9b7eb35230e/trace_processor_shell" } }, "power_profile.sql": {
diff --git a/tools/perf/core/shard_maps/android-pixel6-perf_map.json b/tools/perf/core/shard_maps/android-pixel6-perf_map.json index ff97f10..8514dc7 100644 --- a/tools/perf/core/shard_maps/android-pixel6-perf_map.json +++ b/tools/perf/core/shard_maps/android-pixel6-perf_map.json
@@ -35,6 +35,10 @@ "blink_perf.dom": { "abridged": false }, + "blink_perf.events": { + "end": 1, + "abridged": false + }, "jetstream2": { "abridged": false }, @@ -50,13 +54,14 @@ "2": { "benchmarks": { "blink_perf.events": { + "begin": 1, "abridged": false }, "blink_perf.image_decoder": { "abridged": false }, "blink_perf.layout": { - "end": 72, + "end": 76, "abridged": false }, "jetstream2": { @@ -74,7 +79,7 @@ "3": { "benchmarks": { "blink_perf.layout": { - "begin": 72, + "begin": 76, "abridged": false }, "blink_perf.owp_storage": { @@ -160,7 +165,7 @@ "benchmarks": { "rendering.mobile": { "begin": 2, - "end": 78, + "end": 79, "abridged": false } } @@ -168,8 +173,8 @@ "6": { "benchmarks": { "rendering.mobile": { - "begin": 78, - "end": 157, + "begin": 79, + "end": 158, "abridged": false } } @@ -177,8 +182,8 @@ "7": { "benchmarks": { "rendering.mobile": { - "begin": 157, - "end": 242, + "begin": 158, + "end": 243, "abridged": false } } @@ -186,8 +191,8 @@ "8": { "benchmarks": { "rendering.mobile": { - "begin": 242, - "end": 333, + "begin": 243, + "end": 334, "abridged": false } } @@ -195,8 +200,8 @@ "9": { "benchmarks": { "rendering.mobile": { - "begin": 333, - "end": 413, + "begin": 334, + "end": 415, "abridged": false } } @@ -204,7 +209,7 @@ "10": { "benchmarks": { "rendering.mobile": { - "begin": 413, + "begin": 415, "abridged": false }, "rendering.mobile.notracing": { @@ -233,7 +238,7 @@ "abridged": false }, "system_health.common_mobile": { - "end": 52, + "end": 55, "abridged": false } }, @@ -247,11 +252,11 @@ "11": { "benchmarks": { "system_health.common_mobile": { - "begin": 52, + "begin": 55, "abridged": false }, "system_health.memory_mobile": { - "end": 22, + "end": 23, "abridged": false } } @@ -259,8 +264,8 @@ "12": { "benchmarks": { "system_health.memory_mobile": { - "begin": 22, - "end": 49, + "begin": 23, + "end": 50, "abridged": false } } @@ -268,7 +273,7 @@ "13": { "benchmarks": { "system_health.memory_mobile": { - "begin": 49, + "begin": 50, "abridged": false }, "system_health.scroll_jank_mobile": { @@ -281,6 +286,11 @@ "end": 5, "abridged": false } + }, + "executables": { + "tint_benchmark": { + "path": "tint_benchmark" + } } }, "14": { @@ -301,25 +311,25 @@ } }, "extra_infos": { - "num_stories": 1149, - "predicted_min_shard_time": 3613.0, - "predicted_min_shard_index": 11, + "num_stories": 1150, + "predicted_min_shard_time": 3668.0, + "predicted_min_shard_index": 3, "predicted_max_shard_time": 4118.0, "predicted_max_shard_index": 14, "shard #0": 3708.0, - "shard #1": 3683.0, - "shard #2": 3695.0, - "shard #3": 3713.0, + "shard #1": 3719.0, + "shard #2": 3704.0, + "shard #3": 3668.0, "shard #4": 3703.0, - "shard #5": 3685.0, - "shard #6": 3704.0, - "shard #7": 3730.0, - "shard #8": 3686.0, - "shard #9": 3690.0, - "shard #10": 3697.0, - "shard #11": 3613.0, - "shard #12": 3753.0, - "shard #13": 3691.0, + "shard #5": 3734.0, + "shard #6": 3701.0, + "shard #7": 3725.0, + "shard #8": 3697.0, + "shard #9": 3731.0, + "shard #10": 3735.0, + "shard #11": 3671.0, + "shard #12": 3699.0, + "shard #13": 3736.0, "shard #14": 4118.0 } }
diff --git a/tools/perf/core/shard_maps/linux-perf-calibration_map.json b/tools/perf/core/shard_maps/linux-perf-calibration_map.json index 48db708..0820da6 100644 --- a/tools/perf/core/shard_maps/linux-perf-calibration_map.json +++ b/tools/perf/core/shard_maps/linux-perf-calibration_map.json
@@ -41,7 +41,7 @@ "abridged": false }, "blink_perf.bindings": { - "end": 32, + "end": 30, "abridged": false }, "jetstream2": { @@ -61,11 +61,11 @@ "abridged": false }, "blink_perf.bindings": { - "begin": 32, + "begin": 30, "abridged": false }, "blink_perf.css": { - "end": 21, + "end": 17, "abridged": false }, "jetstream2": { @@ -85,8 +85,8 @@ "abridged": false }, "blink_perf.css": { - "begin": 21, - "end": 61, + "begin": 17, + "end": 57, "abridged": false }, "jetstream2": { @@ -106,17 +106,14 @@ "abridged": false }, "blink_perf.css": { - "begin": 61, + "begin": 57, "abridged": false }, "blink_perf.dom": { "abridged": false }, "blink_perf.events": { - "abridged": false - }, - "blink_perf.image_decoder": { - "end": 1, + "end": 2, "abridged": false }, "jetstream2": { @@ -135,12 +132,15 @@ "blink_perf.shadow_dom": { "abridged": false }, + "blink_perf.events": { + "begin": 2, + "abridged": false + }, "blink_perf.image_decoder": { - "begin": 1, "abridged": false }, "blink_perf.layout": { - "end": 31, + "end": 26, "abridged": false }, "jetstream2": { @@ -160,8 +160,8 @@ "abridged": false }, "blink_perf.layout": { - "begin": 31, - "end": 71, + "begin": 26, + "end": 66, "abridged": false }, "jetstream2": { @@ -181,8 +181,8 @@ "abridged": false }, "blink_perf.layout": { - "begin": 71, - "end": 111, + "begin": 66, + "end": 106, "abridged": false }, "jetstream2": { @@ -202,7 +202,7 @@ "abridged": false }, "blink_perf.layout": { - "begin": 111, + "begin": 106, "abridged": false }, "blink_perf.owp_storage": { @@ -212,7 +212,7 @@ "abridged": false }, "blink_perf.parser": { - "end": 10, + "end": 5, "abridged": false }, "jetstream2": { @@ -232,11 +232,11 @@ "abridged": false }, "blink_perf.parser": { - "begin": 10, + "begin": 5, "abridged": false }, "blink_perf.svg": { - "end": 19, + "end": 15, "abridged": false }, "jetstream2": { @@ -256,7 +256,7 @@ "abridged": false }, "blink_perf.svg": { - "begin": 19, + "begin": 15, "abridged": false }, "blink_perf.webaudio": { @@ -272,7 +272,7 @@ "abridged": false }, "desktop_ui": { - "end": 8, + "end": 4, "abridged": false }, "speedometer2": { @@ -289,7 +289,7 @@ "abridged": false }, "desktop_ui": { - "begin": 8, + "begin": 4, "abridged": false }, "dummy_benchmark.noisy_benchmark_1": { @@ -302,7 +302,7 @@ "abridged": false }, "media.desktop": { - "end": 18, + "end": 17, "abridged": false }, "speedometer2": { @@ -324,7 +324,7 @@ "abridged": false }, "media.desktop": { - "begin": 18, + "begin": 17, "abridged": false }, "memory.desktop": { @@ -334,7 +334,10 @@ "abridged": false }, "power.desktop": { - "end": 7, + "abridged": false + }, + "rasterize_and_record_micro.top_25": { + "end": 8, "abridged": false }, "speedometer2": { @@ -350,15 +353,12 @@ "blink_perf.shadow_dom": { "abridged": false }, - "power.desktop": { - "begin": 7, - "abridged": false - }, "rasterize_and_record_micro.top_25": { + "begin": 8, "abridged": false }, "rendering.desktop": { - "end": 8, + "end": 25, "abridged": false }, "speedometer2": { @@ -375,8 +375,8 @@ "abridged": false }, "rendering.desktop": { - "begin": 8, - "end": 49, + "begin": 25, + "end": 66, "abridged": false }, "speedometer2": { @@ -393,8 +393,8 @@ "abridged": false }, "rendering.desktop": { - "begin": 49, - "end": 90, + "begin": 66, + "end": 108, "abridged": false }, "speedometer2": { @@ -411,8 +411,8 @@ "abridged": false }, "rendering.desktop": { - "begin": 90, - "end": 131, + "begin": 108, + "end": 149, "abridged": false }, "speedometer2": { @@ -429,8 +429,8 @@ "abridged": false }, "rendering.desktop": { - "begin": 131, - "end": 172, + "begin": 149, + "end": 191, "abridged": false }, "speedometer2": { @@ -447,8 +447,8 @@ "abridged": false }, "rendering.desktop": { - "begin": 172, - "end": 212, + "begin": 191, + "end": 232, "abridged": false }, "speedometer2": { @@ -465,8 +465,8 @@ "abridged": false }, "rendering.desktop": { - "begin": 212, - "end": 253, + "begin": 232, + "end": 274, "abridged": false }, "speedometer2": { @@ -483,8 +483,8 @@ "abridged": false }, "rendering.desktop": { - "begin": 253, - "end": 293, + "begin": 274, + "end": 315, "abridged": false }, "speedometer2": { @@ -501,25 +501,7 @@ "abridged": false }, "rendering.desktop": { - "begin": 293, - "end": 334, - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer3": { - "abridged": false - } - } - }, - "22": { - "benchmarks": { - "blink_perf.shadow_dom": { - "abridged": false - }, - "rendering.desktop": { - "begin": 334, + "begin": 315, "abridged": false }, "rendering.desktop.notracing": { @@ -544,7 +526,25 @@ "abridged": false }, "system_health.common_desktop": { - "end": 31, + "end": 3, + "abridged": false + } + } + }, + "22": { + "benchmarks": { + "blink_perf.shadow_dom": { + "abridged": false + }, + "system_health.common_desktop": { + "begin": 3, + "end": 44, + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer3": { "abridged": false } } @@ -555,8 +555,11 @@ "abridged": false }, "system_health.common_desktop": { - "begin": 31, - "end": 72, + "begin": 44, + "abridged": false + }, + "system_health.memory_desktop": { + "end": 7, "abridged": false }, "speedometer2": { @@ -572,12 +575,9 @@ "blink_perf.shadow_dom": { "abridged": false }, - "system_health.common_desktop": { - "begin": 72, - "abridged": false - }, "system_health.memory_desktop": { - "end": 33, + "begin": 7, + "end": 48, "abridged": false }, "speedometer2": { @@ -594,8 +594,7 @@ "abridged": false }, "system_health.memory_desktop": { - "begin": 33, - "end": 74, + "begin": 48, "abridged": false }, "speedometer2": { @@ -604,6 +603,11 @@ "speedometer3": { "abridged": false } + }, + "executables": { + "tint_benchmark": { + "path": "tint_benchmark" + } } }, "26": { @@ -611,15 +615,11 @@ "blink_perf.shadow_dom": { "abridged": false }, - "system_health.memory_desktop": { - "begin": 74, - "abridged": false - }, "v8.browsing_desktop": { "abridged": false }, "v8.browsing_desktop-future": { - "end": 6, + "end": 8, "abridged": false }, "speedometer2": { @@ -641,7 +641,7 @@ "abridged": false }, "v8.browsing_desktop-future": { - "begin": 6, + "begin": 8, "abridged": false }, "wasmpspdfkit": { @@ -659,11 +659,11 @@ } }, "extra_infos": { - "num_stories": 2256, - "predicted_min_shard_time": 810, - "predicted_min_shard_index": 18, - "predicted_max_shard_time": 820.0, - "predicted_max_shard_index": 0, + "num_stories": 2269, + "predicted_min_shard_time": 785.0, + "predicted_min_shard_index": 26, + "predicted_max_shard_time": 900, + "predicted_max_shard_index": 25, "shard #0": 820.0, "shard #1": 820, "shard #2": 820, @@ -675,22 +675,22 @@ "shard #8": 820, "shard #9": 820, "shard #10": 820, - "shard #11": 813.0, - "shard #12": 815.0, - "shard #13": 820, + "shard #11": 823.0, + "shard #12": 820, + "shard #13": 830, "shard #14": 820, - "shard #15": 820, + "shard #15": 830, "shard #16": 820, - "shard #17": 820, - "shard #18": 810, - "shard #19": 820, - "shard #20": 810, - "shard #21": 820, - "shard #22": 810, - "shard #23": 820, - "shard #24": 810, - "shard #25": 820, - "shard #26": 815.0, - "shard #27": 820 + "shard #17": 830, + "shard #18": 820, + "shard #19": 830, + "shard #20": 820, + "shard #21": 830, + "shard #22": 820, + "shard #23": 830, + "shard #24": 820, + "shard #25": 900, + "shard #26": 785.0, + "shard #27": 800 } }
diff --git a/tools/perf/core/shard_maps/linux-perf-rel_map.json b/tools/perf/core/shard_maps/linux-perf-rel_map.json index 32eadff8..302d815 100644 --- a/tools/perf/core/shard_maps/linux-perf-rel_map.json +++ b/tools/perf/core/shard_maps/linux-perf-rel_map.json
@@ -2,7 +2,7 @@ "0": { "benchmarks": { "system_health.common_desktop": { - "end": 34, + "end": 44, "abridged": false } }, @@ -22,11 +22,14 @@ "1": { "benchmarks": { "system_health.common_desktop": { - "begin": 34, + "begin": 44, "abridged": false } }, "executables": { + "tint_benchmark": { + "path": "tint_benchmark" + }, "tracing_perftests": { "path": "tracing_perftests" } @@ -34,11 +37,11 @@ }, "extra_infos": { "num_stories": 83, - "predicted_min_shard_time": 1172.0, + "predicted_min_shard_time": 1164.0, "predicted_min_shard_index": 0, - "predicted_max_shard_time": 1186.0, + "predicted_max_shard_time": 1178.0, "predicted_max_shard_index": 1, - "shard #0": 1172.0, - "shard #1": 1186.0 + "shard #0": 1164.0, + "shard #1": 1178.0 } }
diff --git a/tools/perf/core/shard_maps/linux-perf_map.json b/tools/perf/core/shard_maps/linux-perf_map.json index 7d852fb6..a8d7629 100644 --- a/tools/perf/core/shard_maps/linux-perf_map.json +++ b/tools/perf/core/shard_maps/linux-perf_map.json
@@ -80,7 +80,7 @@ "abridged": false }, "blink_perf.bindings": { - "end": 14, + "end": 13, "abridged": false }, "jetstream2": { @@ -142,11 +142,11 @@ "2": { "benchmarks": { "blink_perf.bindings": { - "begin": 14, + "begin": 13, "abridged": false }, "blink_perf.css": { - "end": 49, + "end": 44, "abridged": false }, "jetstream2": { @@ -208,14 +208,11 @@ "3": { "benchmarks": { "blink_perf.css": { - "begin": 49, + "begin": 44, "abridged": false }, "blink_perf.dom": { - "abridged": false - }, - "blink_perf.events": { - "end": 3, + "end": 13, "abridged": false }, "jetstream2": { @@ -276,15 +273,18 @@ }, "4": { "benchmarks": { + "blink_perf.dom": { + "begin": 13, + "abridged": false + }, "blink_perf.events": { - "begin": 3, "abridged": false }, "blink_perf.image_decoder": { "abridged": false }, "blink_perf.layout": { - "end": 67, + "end": 45, "abridged": false }, "jetstream2": { @@ -346,7 +346,7 @@ "5": { "benchmarks": { "blink_perf.layout": { - "begin": 67, + "begin": 45, "abridged": false }, "blink_perf.owp_storage": { @@ -356,10 +356,7 @@ "abridged": false }, "blink_perf.parser": { - "abridged": false - }, - "blink_perf.shadow_dom": { - "end": 7, + "end": 12, "abridged": false }, "system_health.common_desktop": { @@ -414,8 +411,11 @@ }, "6": { "benchmarks": { + "blink_perf.parser": { + "begin": 12, + "abridged": false + }, "blink_perf.shadow_dom": { - "begin": 7, "abridged": false }, "blink_perf.svg": { @@ -428,13 +428,7 @@ "abridged": false }, "blink_perf.webgl": { - "abridged": false - }, - "blink_perf.webgl_fast_call": { - "abridged": false - }, - "desktop_ui": { - "end": 5, + "end": 2, "abridged": false }, "system_health.common_desktop": { @@ -489,8 +483,14 @@ }, "7": { "benchmarks": { + "blink_perf.webgl": { + "begin": 2, + "abridged": false + }, + "blink_perf.webgl_fast_call": { + "abridged": false + }, "desktop_ui": { - "begin": 5, "abridged": false }, "dummy_benchmark.noisy_benchmark_1": { @@ -499,6 +499,58 @@ "dummy_benchmark.stable_benchmark_1": { "abridged": false }, + "system_health.common_desktop": { + "sections": [ + { + "begin": 64, + "end": 65 + }, + { + "begin": 73, + "end": 74 + }, + { + "begin": 77, + "end": 78 + } + ], + "abridged": false + }, + "speedometer": { + "abridged": false + }, + "speedometer2-minorms": { + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer2-predictable": { + "abridged": false + }, + "speedometer3": { + "abridged": false + }, + "speedometer3-minorms": { + "abridged": false + }, + "speedometer3-predictable": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3.0": { + "display_name": "speedometer3.crossbench", + "arguments": [] + }, + "jetstream_2.2": { + "display_name": "jetstream2.crossbench", + "arguments": [] + } + } + }, + "8": { + "benchmarks": { "jetstream2": { "abridged": false }, @@ -506,7 +558,7 @@ "abridged": false }, "media.desktop": { - "end": 4, + "end": 14, "abridged": false }, "system_health.common_desktop": { @@ -564,71 +616,14 @@ } } }, - "8": { - "benchmarks": { - "media.desktop": { - "begin": 4, - "abridged": false - }, - "memory.desktop": { - "end": 1, - "abridged": false - }, - "system_health.common_desktop": { - "sections": [ - { - "begin": 64, - "end": 65 - }, - { - "begin": 73, - "end": 74 - }, - { - "begin": 77, - "end": 78 - } - ], - "abridged": false - }, - "speedometer": { - "abridged": false - }, - "speedometer2-minorms": { - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer2-predictable": { - "abridged": false - }, - "speedometer3": { - "abridged": false - }, - "speedometer3-minorms": { - "abridged": false - }, - "speedometer3-predictable": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "jetstream_2.2": { - "display_name": "jetstream2.crossbench", - "arguments": [] - } - } - }, "9": { "benchmarks": { + "media.desktop": { + "begin": 14, + "abridged": false + }, "memory.desktop": { - "begin": 1, - "end": 6, + "end": 4, "abridged": false }, "system_health.common_desktop": { @@ -684,7 +679,52 @@ "10": { "benchmarks": { "memory.desktop": { - "begin": 6, + "begin": 4, + "abridged": false + }, + "speedometer": { + "abridged": false + }, + "speedometer2-minorms": { + "abridged": false + }, + "speedometer2": { + "abridged": false + }, + "speedometer2-predictable": { + "abridged": false + }, + "speedometer3": { + "abridged": false + }, + "speedometer3-minorms": { + "abridged": false + }, + "speedometer3-predictable": { + "abridged": false + } + }, + "crossbench": { + "speedometer_3.0": { + "display_name": "speedometer3.crossbench", + "arguments": [] + }, + "jetstream_2.2": { + "display_name": "jetstream2.crossbench", + "arguments": [] + } + } + }, + "11": { + "benchmarks": { + "octane": { + "abridged": false + }, + "octane-minorms": { + "abridged": false + }, + "power.desktop": { + "end": 12, "abridged": false }, "speedometer": { @@ -724,62 +764,17 @@ } } }, - "11": { + "12": { "benchmarks": { - "octane": { - "abridged": false - }, - "octane-minorms": { - "abridged": false - }, "power.desktop": { + "begin": 12, "abridged": false }, "rasterize_and_record_micro.top_25": { "abridged": false }, "rendering.desktop": { - "end": 4, - "abridged": false - }, - "speedometer": { - "abridged": false - }, - "speedometer2-minorms": { - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer2-predictable": { - "abridged": false - }, - "speedometer3": { - "abridged": false - }, - "speedometer3-minorms": { - "abridged": false - }, - "speedometer3-predictable": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - }, - "jetstream_2.2": { - "display_name": "jetstream2.crossbench", - "arguments": [] - } - } - }, - "12": { - "benchmarks": { - "rendering.desktop": { - "begin": 4, - "end": 49, + "end": 30, "abridged": false }, "speedometer": { @@ -818,8 +813,8 @@ "13": { "benchmarks": { "rendering.desktop": { - "begin": 49, - "end": 97, + "begin": 30, + "end": 77, "abridged": false }, "speedometer": { @@ -858,8 +853,8 @@ "14": { "benchmarks": { "rendering.desktop": { - "begin": 97, - "end": 150, + "begin": 77, + "end": 129, "abridged": false }, "speedometer": { @@ -898,8 +893,8 @@ "15": { "benchmarks": { "rendering.desktop": { - "begin": 150, - "end": 191, + "begin": 129, + "end": 174, "abridged": false }, "speedometer": { @@ -938,8 +933,8 @@ "16": { "benchmarks": { "rendering.desktop": { - "begin": 191, - "end": 240, + "begin": 174, + "end": 216, "abridged": false }, "speedometer": { @@ -978,8 +973,8 @@ "17": { "benchmarks": { "rendering.desktop": { - "begin": 240, - "end": 275, + "begin": 216, + "end": 261, "abridged": false }, "speedometer": { @@ -1018,8 +1013,8 @@ "18": { "benchmarks": { "rendering.desktop": { - "begin": 275, - "end": 313, + "begin": 261, + "end": 295, "abridged": false }, "speedometer": { @@ -1058,10 +1053,8 @@ "19": { "benchmarks": { "rendering.desktop": { - "begin": 313, - "abridged": false - }, - "rendering.desktop.notracing": { + "begin": 295, + "end": 339, "abridged": false }, "speedometer": { @@ -1099,6 +1092,13 @@ }, "20": { "benchmarks": { + "rendering.desktop": { + "begin": 339, + "abridged": false + }, + "rendering.desktop.notracing": { + "abridged": false + }, "speedometer": { "abridged": false }, @@ -1130,7 +1130,7 @@ "abridged": false }, "system_health.common_desktop": { - "end": 52, + "end": 25, "abridged": false } } @@ -1138,11 +1138,11 @@ "21": { "benchmarks": { "system_health.common_desktop": { - "begin": 52, + "begin": 25, "abridged": false }, "system_health.memory_desktop": { - "end": 17, + "end": 10, "abridged": false } } @@ -1150,8 +1150,8 @@ "22": { "benchmarks": { "system_health.memory_desktop": { - "begin": 17, - "end": 38, + "begin": 10, + "end": 37, "abridged": false } } @@ -1159,8 +1159,8 @@ "23": { "benchmarks": { "system_health.memory_desktop": { - "begin": 38, - "end": 65, + "begin": 37, + "end": 66, "abridged": false } } @@ -1168,15 +1168,18 @@ "24": { "benchmarks": { "system_health.memory_desktop": { - "begin": 65, + "begin": 66, "abridged": false }, "v8.browsing_desktop": { - "end": 3, + "end": 7, "abridged": false } }, "executables": { + "tint_benchmark": { + "path": "tint_benchmark" + }, "tracing_perftests": { "path": "tracing_perftests" } @@ -1185,7 +1188,7 @@ "25": { "benchmarks": { "v8.browsing_desktop": { - "begin": 3, + "begin": 7, "abridged": false }, "v8.browsing_desktop-future": { @@ -1200,36 +1203,36 @@ } }, "extra_infos": { - "num_stories": 1370, - "predicted_min_shard_time": 1353.0, - "predicted_min_shard_index": 23, - "predicted_max_shard_time": 2255.0, + "num_stories": 1368, + "predicted_min_shard_time": 1440.0, + "predicted_min_shard_index": 10, + "predicted_max_shard_time": 2093.0, "predicted_max_shard_index": 25, - "shard #0": 1459.0, - "shard #1": 1506.0, - "shard #2": 1504.0, - "shard #3": 1511.0, - "shard #4": 1507.0, - "shard #5": 1506.0, - "shard #6": 1473.0, - "shard #7": 1508.0, - "shard #8": 1525.0, - "shard #9": 1560.0, - "shard #10": 1576.0, - "shard #11": 1490.0, - "shard #12": 1502.0, - "shard #13": 1500.0, - "shard #14": 1501.0, - "shard #15": 1500.0, - "shard #16": 1491.0, - "shard #17": 1494.0, - "shard #18": 1501.0, - "shard #19": 1535.0, - "shard #20": 1483.0, - "shard #21": 1485.0, - "shard #22": 1470.0, - "shard #23": 1353.0, - "shard #24": 1551.0, - "shard #25": 2255.0 + "shard #0": 1480.0, + "shard #1": 1503.0, + "shard #2": 1502.0, + "shard #3": 1494.0, + "shard #4": 1499.0, + "shard #5": 1496.0, + "shard #6": 1501.0, + "shard #7": 1454.0, + "shard #8": 1500.0, + "shard #9": 1445.0, + "shard #10": 1440.0, + "shard #11": 1510.0, + "shard #12": 1506.0, + "shard #13": 1510.0, + "shard #14": 1517.0, + "shard #15": 1514.0, + "shard #16": 1502.0, + "shard #17": 1514.0, + "shard #18": 1515.0, + "shard #19": 1502.0, + "shard #20": 1515.0, + "shard #21": 1532.0, + "shard #22": 1515.0, + "shard #23": 1620.0, + "shard #24": 1441.0, + "shard #25": 2093.0 } }
diff --git a/tools/perf/core/shard_maps/linux-r350-perf_map.json b/tools/perf/core/shard_maps/linux-r350-perf_map.json index 4d047bb37..1b60b20 100644 --- a/tools/perf/core/shard_maps/linux-r350-perf_map.json +++ b/tools/perf/core/shard_maps/linux-r350-perf_map.json
@@ -5,7 +5,7 @@ "abridged": false }, "blink_perf.accessibility": { - "end": 15, + "end": 16, "abridged": false } }, @@ -22,11 +22,11 @@ "1": { "benchmarks": { "blink_perf.accessibility": { - "begin": 15, + "begin": 16, "abridged": false }, "blink_perf.bindings": { - "end": 32, + "end": 34, "abridged": false } } @@ -34,11 +34,11 @@ "2": { "benchmarks": { "blink_perf.bindings": { - "begin": 32, + "begin": 34, "abridged": false }, "blink_perf.css": { - "end": 20, + "end": 23, "abridged": false } } @@ -46,8 +46,8 @@ "3": { "benchmarks": { "blink_perf.css": { - "begin": 20, - "end": 61, + "begin": 23, + "end": 65, "abridged": false } } @@ -55,7 +55,7 @@ "4": { "benchmarks": { "blink_perf.css": { - "begin": 61, + "begin": 65, "abridged": false }, "blink_perf.dom": { @@ -65,7 +65,7 @@ "abridged": false }, "blink_perf.image_decoder": { - "end": 1, + "end": 6, "abridged": false } } @@ -73,11 +73,11 @@ "5": { "benchmarks": { "blink_perf.image_decoder": { - "begin": 1, + "begin": 6, "abridged": false }, "blink_perf.layout": { - "end": 32, + "end": 38, "abridged": false } } @@ -85,8 +85,8 @@ "6": { "benchmarks": { "blink_perf.layout": { - "begin": 32, - "end": 73, + "begin": 38, + "end": 80, "abridged": false } } @@ -94,26 +94,26 @@ "7": { "benchmarks": { "blink_perf.layout": { - "begin": 73, - "end": 114, - "abridged": false - } - } - }, - "8": { - "benchmarks": { - "blink_perf.layout": { - "begin": 114, + "begin": 80, "abridged": false }, "blink_perf.owp_storage": { "abridged": false }, "blink_perf.paint": { + "end": 1, + "abridged": false + } + } + }, + "8": { + "benchmarks": { + "blink_perf.paint": { + "begin": 1, "abridged": false }, "blink_perf.parser": { - "end": 14, + "end": 23, "abridged": false } } @@ -121,11 +121,11 @@ "9": { "benchmarks": { "blink_perf.parser": { - "begin": 14, + "begin": 23, "abridged": false }, "blink_perf.shadow_dom": { - "end": 24, + "end": 35, "abridged": false } } @@ -133,25 +133,25 @@ "10": { "benchmarks": { "blink_perf.shadow_dom": { - "begin": 24, + "begin": 35, "abridged": false }, "blink_perf.svg": { "abridged": false }, "blink_perf.webaudio": { - "end": 2, + "abridged": false + }, + "blink_perf.webcodecs": { + "end": 5, "abridged": false } } }, "11": { "benchmarks": { - "blink_perf.webaudio": { - "begin": 2, - "abridged": false - }, "blink_perf.webcodecs": { + "begin": 5, "abridged": false }, "blink_perf.webgl": { @@ -161,15 +161,6 @@ "abridged": false }, "desktop_ui": { - "end": 15, - "abridged": false - } - } - }, - "12": { - "benchmarks": { - "desktop_ui": { - "begin": 15, "abridged": false }, "dummy_benchmark.noisy_benchmark_1": { @@ -180,12 +171,16 @@ }, "jetstream2": { "abridged": false - }, + } + } + }, + "12": { + "benchmarks": { "jetstream2-minorms": { "abridged": false }, "media.desktop": { - "end": 7, + "end": 22, "abridged": false } }, @@ -204,12 +199,18 @@ "13": { "benchmarks": { "media.desktop": { - "begin": 7, + "begin": 22, "abridged": false }, "memory.desktop": { "abridged": false } + }, + "crossbench": { + "motionmark_1.3": { + "display_name": "motionmark1.3.crossbench", + "arguments": [] + } } }, "14": { @@ -221,28 +222,22 @@ "abridged": false }, "power.desktop": { - "end": 4, "abridged": false - } - }, - "crossbench": { - "motionmark_1.3": { - "display_name": "motionmark1.3.crossbench", - "arguments": [] + }, + "rasterize_and_record_micro.top_25": { + "end": 24, + "abridged": false } } }, "15": { "benchmarks": { - "power.desktop": { - "begin": 4, - "abridged": false - }, "rasterize_and_record_micro.top_25": { + "begin": 24, "abridged": false }, "rendering.desktop": { - "end": 6, + "end": 40, "abridged": false } } @@ -250,8 +245,8 @@ "16": { "benchmarks": { "rendering.desktop": { - "begin": 6, - "end": 48, + "begin": 40, + "end": 81, "abridged": false } } @@ -259,8 +254,8 @@ "17": { "benchmarks": { "rendering.desktop": { - "begin": 48, - "end": 91, + "begin": 81, + "end": 122, "abridged": false } } @@ -268,8 +263,8 @@ "18": { "benchmarks": { "rendering.desktop": { - "begin": 91, - "end": 133, + "begin": 122, + "end": 163, "abridged": false } } @@ -277,8 +272,8 @@ "19": { "benchmarks": { "rendering.desktop": { - "begin": 133, - "end": 176, + "begin": 163, + "end": 204, "abridged": false } } @@ -286,8 +281,8 @@ "20": { "benchmarks": { "rendering.desktop": { - "begin": 176, - "end": 218, + "begin": 204, + "end": 245, "abridged": false } } @@ -295,8 +290,8 @@ "21": { "benchmarks": { "rendering.desktop": { - "begin": 218, - "end": 261, + "begin": 245, + "end": 287, "abridged": false } } @@ -304,8 +299,8 @@ "22": { "benchmarks": { "rendering.desktop": { - "begin": 261, - "end": 303, + "begin": 287, + "end": 328, "abridged": false } } @@ -313,16 +308,7 @@ "23": { "benchmarks": { "rendering.desktop": { - "begin": 303, - "end": 346, - "abridged": false - } - } - }, - "24": { - "benchmarks": { - "rendering.desktop": { - "begin": 346, + "begin": 328, "abridged": false }, "rendering.desktop.notracing": { @@ -359,7 +345,7 @@ "abridged": false }, "system_health.common_desktop": { - "end": 22, + "end": 4, "abridged": false } }, @@ -370,23 +356,32 @@ } } }, + "24": { + "benchmarks": { + "system_health.common_desktop": { + "begin": 4, + "end": 45, + "abridged": false + } + } + }, "25": { "benchmarks": { "system_health.common_desktop": { - "begin": 22, - "end": 65, + "begin": 45, + "abridged": false + }, + "system_health.memory_desktop": { + "end": 8, "abridged": false } } }, "26": { "benchmarks": { - "system_health.common_desktop": { - "begin": 65, - "abridged": false - }, "system_health.memory_desktop": { - "end": 28, + "begin": 8, + "end": 49, "abridged": false } } @@ -394,23 +389,23 @@ "27": { "benchmarks": { "system_health.memory_desktop": { - "begin": 28, - "end": 71, + "begin": 49, "abridged": false } + }, + "executables": { + "tint_benchmark": { + "path": "tint_benchmark" + } } }, "28": { "benchmarks": { - "system_health.memory_desktop": { - "begin": 71, - "abridged": false - }, "v8.browsing_desktop": { "abridged": false }, "v8.browsing_desktop-future": { - "end": 5, + "end": 9, "abridged": false } }, @@ -423,7 +418,7 @@ "29": { "benchmarks": { "v8.browsing_desktop-future": { - "begin": 5, + "begin": 9, "abridged": false }, "wasmpspdfkit": { @@ -435,40 +430,40 @@ } }, "extra_infos": { - "num_stories": 1164, - "predicted_min_shard_time": 270, - "predicted_min_shard_index": 13, - "predicted_max_shard_time": 430, - "predicted_max_shard_index": 17, - "shard #0": 410.0, - "shard #1": 410, - "shard #2": 410, - "shard #3": 410, - "shard #4": 410, - "shard #5": 410, - "shard #6": 410, - "shard #7": 410, - "shard #8": 410, - "shard #9": 410, - "shard #10": 410, - "shard #11": 410, + "num_stories": 1162, + "predicted_min_shard_time": 380, + "predicted_min_shard_index": 29, + "predicted_max_shard_time": 480, + "predicted_max_shard_index": 13, + "shard #0": 420.0, + "shard #1": 420, + "shard #2": 420, + "shard #3": 420, + "shard #4": 420, + "shard #5": 420, + "shard #6": 420, + "shard #7": 420, + "shard #8": 420, + "shard #9": 420, + "shard #10": 420, + "shard #11": 420, "shard #12": 413.0, - "shard #13": 270, - "shard #14": 420, - "shard #15": 420, - "shard #16": 420, - "shard #17": 430, - "shard #18": 420, - "shard #19": 430, - "shard #20": 420, - "shard #21": 430, - "shard #22": 420, - "shard #23": 430, - "shard #24": 420, - "shard #25": 430, - "shard #26": 420, - "shard #27": 430, - "shard #28": 425.0, - "shard #29": 420 + "shard #13": 480, + "shard #14": 410, + "shard #15": 410, + "shard #16": 410, + "shard #17": 410, + "shard #18": 410, + "shard #19": 410, + "shard #20": 410, + "shard #21": 420, + "shard #22": 410, + "shard #23": 420, + "shard #24": 410, + "shard #25": 420, + "shard #26": 410, + "shard #27": 480, + "shard #28": 385.0, + "shard #29": 380 } }
diff --git a/tools/perf/core/shard_maps/mac-laptop_high_end-perf_map.json b/tools/perf/core/shard_maps/mac-laptop_high_end-perf_map.json index 55ca4e4..a25decf 100644 --- a/tools/perf/core/shard_maps/mac-laptop_high_end-perf_map.json +++ b/tools/perf/core/shard_maps/mac-laptop_high_end-perf_map.json
@@ -5,7 +5,7 @@ "abridged": false }, "blink_perf.accessibility": { - "end": 8, + "end": 13, "abridged": false }, "jetstream2": { @@ -41,14 +41,14 @@ "1": { "benchmarks": { "blink_perf.accessibility": { - "begin": 8, + "begin": 13, "abridged": false }, "blink_perf.bindings": { "abridged": false }, "blink_perf.css": { - "end": 3, + "end": 49, "abridged": false }, "jetstream2": { @@ -75,11 +75,20 @@ "2": { "benchmarks": { "blink_perf.css": { - "begin": 3, + "begin": 49, "abridged": false }, "blink_perf.dom": { - "end": 11, + "abridged": false + }, + "blink_perf.events": { + "abridged": false + }, + "blink_perf.image_decoder": { + "abridged": false + }, + "blink_perf.layout": { + "end": 2, "abridged": false }, "jetstream2": { @@ -105,18 +114,15 @@ }, "3": { "benchmarks": { - "blink_perf.dom": { - "begin": 11, - "abridged": false - }, - "blink_perf.events": { - "abridged": false - }, - "blink_perf.image_decoder": { - "abridged": false - }, "blink_perf.layout": { - "end": 70, + "begin": 2, + "abridged": false + }, + "blink_perf.owp_storage": { + "abridged": false + }, + "blink_perf.parser": { + "end": 4, "abridged": false }, "jetstream2": { @@ -142,19 +148,28 @@ }, "4": { "benchmarks": { - "blink_perf.layout": { - "begin": 70, - "abridged": false - }, - "blink_perf.owp_storage": { - "abridged": false - }, "blink_perf.parser": { + "begin": 4, "abridged": false }, "blink_perf.shadow_dom": { "abridged": false }, + "blink_perf.webaudio": { + "abridged": false + }, + "blink_perf.webcodecs": { + "abridged": false + }, + "blink_perf.webgl": { + "abridged": false + }, + "blink_perf.webgl_fast_call": { + "abridged": false + }, + "blink_perf.webgpu": { + "abridged": false + }, "jetstream2": { "abridged": false }, @@ -178,21 +193,6 @@ }, "5": { "benchmarks": { - "blink_perf.webaudio": { - "abridged": false - }, - "blink_perf.webcodecs": { - "abridged": false - }, - "blink_perf.webgl": { - "abridged": false - }, - "blink_perf.webgl_fast_call": { - "abridged": false - }, - "blink_perf.webgpu": { - "abridged": false - }, "blink_perf.webgpu_fast_call": { "abridged": false }, @@ -209,7 +209,7 @@ "abridged": false }, "media.desktop": { - "end": 5, + "end": 21, "abridged": false }, "speedometer2": { @@ -229,11 +229,10 @@ "6": { "benchmarks": { "media.desktop": { - "begin": 5, + "begin": 21, "abridged": false }, "memory.desktop": { - "end": 6, "abridged": false }, "speedometer2": { @@ -252,15 +251,14 @@ }, "7": { "benchmarks": { - "memory.desktop": { - "begin": 6, - "abridged": false - }, "octane": { "abridged": false }, "power.desktop": { - "end": 9, + "abridged": false + }, + "rasterize_and_record_micro.top_25": { + "end": 19, "abridged": false }, "speedometer2": { @@ -283,15 +281,12 @@ }, "8": { "benchmarks": { - "power.desktop": { - "begin": 9, - "abridged": false - }, "rasterize_and_record_micro.top_25": { + "begin": 19, "abridged": false }, "rendering.desktop": { - "end": 28, + "end": 47, "abridged": false }, "speedometer2": { @@ -311,8 +306,8 @@ "9": { "benchmarks": { "rendering.desktop": { - "begin": 28, - "end": 84, + "begin": 47, + "end": 98, "abridged": false }, "speedometer2": { @@ -332,8 +327,8 @@ "10": { "benchmarks": { "rendering.desktop": { - "begin": 84, - "end": 139, + "begin": 98, + "end": 151, "abridged": false }, "speedometer2": { @@ -353,8 +348,8 @@ "11": { "benchmarks": { "rendering.desktop": { - "begin": 139, - "end": 184, + "begin": 151, + "end": 202, "abridged": false }, "speedometer2": { @@ -374,8 +369,8 @@ "12": { "benchmarks": { "rendering.desktop": { - "begin": 184, - "end": 236, + "begin": 202, + "end": 249, "abridged": false }, "speedometer2": { @@ -395,8 +390,8 @@ "13": { "benchmarks": { "rendering.desktop": { - "begin": 236, - "end": 279, + "begin": 249, + "end": 287, "abridged": false }, "speedometer2": { @@ -416,8 +411,8 @@ "14": { "benchmarks": { "rendering.desktop": { - "begin": 279, - "end": 329, + "begin": 287, + "end": 337, "abridged": false }, "speedometer2": { @@ -437,7 +432,7 @@ "15": { "benchmarks": { "rendering.desktop": { - "begin": 329, + "begin": 337, "abridged": false }, "rendering.desktop.notracing": { @@ -462,7 +457,7 @@ "abridged": false }, "system_health.common_desktop": { - "end": 14, + "end": 23, "abridged": false } }, @@ -476,8 +471,8 @@ "16": { "benchmarks": { "system_health.common_desktop": { - "begin": 14, - "end": 69, + "begin": 23, + "end": 72, "abridged": false }, "speedometer2": { @@ -497,11 +492,11 @@ "17": { "benchmarks": { "system_health.common_desktop": { - "begin": 69, + "begin": 72, "abridged": false }, "system_health.memory_desktop": { - "end": 13, + "end": 16, "abridged": false }, "speedometer2": { @@ -521,8 +516,8 @@ "18": { "benchmarks": { "system_health.memory_desktop": { - "begin": 13, - "end": 30, + "begin": 16, + "end": 35, "abridged": false }, "speedometer2": { @@ -542,8 +537,8 @@ "19": { "benchmarks": { "system_health.memory_desktop": { - "begin": 30, - "end": 54, + "begin": 35, + "end": 56, "abridged": false }, "speedometer2": { @@ -563,8 +558,8 @@ "20": { "benchmarks": { "system_health.memory_desktop": { - "begin": 54, - "end": 74, + "begin": 56, + "end": 75, "abridged": false } } @@ -572,13 +567,18 @@ "21": { "benchmarks": { "system_health.memory_desktop": { - "begin": 74, + "begin": 75, "abridged": false }, "v8.browsing_desktop": { "end": 23, "abridged": false } + }, + "executables": { + "tint_benchmark": { + "path": "tint_benchmark" + } } }, "22": { @@ -607,33 +607,33 @@ } }, "extra_infos": { - "num_stories": 1181, - "predicted_min_shard_time": 1182.0, - "predicted_min_shard_index": 15, - "predicted_max_shard_time": 1325.0, + "num_stories": 1180, + "predicted_min_shard_time": 1178.0, + "predicted_min_shard_index": 6, + "predicted_max_shard_time": 1423.0, "predicted_max_shard_index": 22, - "shard #0": 1193.0, - "shard #1": 1198.0, - "shard #2": 1205.0, - "shard #3": 1199.0, - "shard #4": 1196.0, - "shard #5": 1199.0, - "shard #6": 1210.0, - "shard #7": 1212.0, - "shard #8": 1189.0, - "shard #9": 1192.0, - "shard #10": 1188.0, - "shard #11": 1206.0, - "shard #12": 1204.0, - "shard #13": 1194.0, - "shard #14": 1199.0, - "shard #15": 1182.0, - "shard #16": 1186.0, - "shard #17": 1203.0, - "shard #18": 1186.0, - "shard #19": 1219.0, - "shard #20": 1197.0, - "shard #21": 1217.0, - "shard #22": 1325.0 + "shard #0": 1347.0, + "shard #1": 1344.0, + "shard #2": 1339.0, + "shard #3": 1328.0, + "shard #4": 1341.0, + "shard #5": 1348.0, + "shard #6": 1178.0, + "shard #7": 1348.0, + "shard #8": 1341.0, + "shard #9": 1340.0, + "shard #10": 1351.0, + "shard #11": 1347.0, + "shard #12": 1342.0, + "shard #13": 1342.0, + "shard #14": 1348.0, + "shard #15": 1345.0, + "shard #16": 1325.0, + "shard #17": 1381.0, + "shard #18": 1334.0, + "shard #19": 1385.0, + "shard #20": 1407.0, + "shard #21": 1359.0, + "shard #22": 1423.0 } }
diff --git a/tools/perf/core/shard_maps/mac-m1_mini_2020-perf_map.json b/tools/perf/core/shard_maps/mac-m1_mini_2020-perf_map.json index 0e3b94581..7ff9cce4 100644 --- a/tools/perf/core/shard_maps/mac-m1_mini_2020-perf_map.json +++ b/tools/perf/core/shard_maps/mac-m1_mini_2020-perf_map.json
@@ -196,7 +196,7 @@ }, "blink_perf.accessibility": { "begin": 13, - "end": 22, + "end": 23, "abridged": false }, "jetstream2": { @@ -242,14 +242,14 @@ "pageset_repeat": 2 }, "blink_perf.accessibility": { - "begin": 22, + "begin": 23, "abridged": false }, "blink_perf.bindings": { "abridged": false }, "blink_perf.css": { - "end": 52, + "end": 58, "abridged": false }, "speedometer2": { @@ -285,7 +285,7 @@ "pageset_repeat": 2 }, "blink_perf.css": { - "begin": 52, + "begin": 58, "abridged": false }, "blink_perf.dom": { @@ -298,7 +298,7 @@ "abridged": false }, "blink_perf.layout": { - "end": 12, + "end": 24, "abridged": false }, "speedometer2": { @@ -334,8 +334,11 @@ "pageset_repeat": 2 }, "blink_perf.layout": { - "begin": 12, - "end": 103, + "begin": 24, + "abridged": false + }, + "blink_perf.owp_storage": { + "end": 1, "abridged": false }, "speedometer2": { @@ -370,11 +373,8 @@ "abridged": false, "pageset_repeat": 2 }, - "blink_perf.layout": { - "begin": 103, - "abridged": false - }, "blink_perf.owp_storage": { + "begin": 1, "abridged": false }, "blink_perf.parser": { @@ -384,7 +384,10 @@ "abridged": false }, "blink_perf.webaudio": { - "end": 5, + "abridged": false + }, + "blink_perf.webcodecs": { + "end": 6, "abridged": false }, "speedometer2": { @@ -419,11 +422,8 @@ "abridged": false, "pageset_repeat": 2 }, - "blink_perf.webaudio": { - "begin": 5, - "abridged": false - }, "blink_perf.webcodecs": { + "begin": 6, "abridged": false }, "blink_perf.webgl": { @@ -439,7 +439,7 @@ "abridged": false }, "desktop_ui": { - "end": 8, + "end": 16, "abridged": false }, "speedometer2": { @@ -484,7 +484,7 @@ "pageset_repeat": 2 }, "desktop_ui": { - "begin": 8, + "begin": 16, "abridged": false }, "dummy_benchmark.noisy_benchmark_1": { @@ -500,7 +500,7 @@ "abridged": false }, "media.desktop": { - "end": 7, + "end": 10, "abridged": false }, "speedometer2": { @@ -536,8 +536,11 @@ "pageset_repeat": 2 }, "media.desktop": { - "begin": 7, - "end": 22, + "begin": 10, + "abridged": false + }, + "memory.desktop": { + "end": 1, "abridged": false }, "speedometer2": { @@ -572,12 +575,9 @@ "abridged": false, "pageset_repeat": 2 }, - "media.desktop": { - "begin": 22, - "abridged": false - }, "memory.desktop": { - "end": 6, + "begin": 1, + "end": 8, "abridged": false }, "speedometer2": { @@ -613,14 +613,14 @@ "pageset_repeat": 2 }, "memory.desktop": { - "begin": 6, + "begin": 8, "abridged": false }, "octane": { "abridged": false }, "power.desktop": { - "end": 5, + "end": 9, "abridged": false }, "speedometer2": { @@ -656,14 +656,14 @@ "pageset_repeat": 2 }, "power.desktop": { - "begin": 5, + "begin": 9, "abridged": false }, "rasterize_and_record_micro.top_25": { "abridged": false }, "rendering.desktop": { - "end": 2, + "end": 8, "abridged": false }, "speedometer2": { @@ -699,8 +699,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 2, - "end": 25, + "begin": 8, + "end": 33, "abridged": false }, "speedometer2": { @@ -736,8 +736,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 25, - "end": 52, + "begin": 33, + "end": 61, "abridged": false }, "speedometer2": { @@ -773,8 +773,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 52, - "end": 79, + "begin": 61, + "end": 88, "abridged": false }, "speedometer2": { @@ -810,8 +810,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 79, - "end": 107, + "begin": 88, + "end": 118, "abridged": false }, "speedometer2": { @@ -847,8 +847,8 @@ "pageset_repeat": 2 }, "rendering.desktop": { - "begin": 107, - "end": 135, + "begin": 118, + "end": 143, "abridged": false }, "speedometer2": { @@ -880,8 +880,8 @@ "20": { "benchmarks": { "rendering.desktop": { - "begin": 135, - "end": 206, + "begin": 143, + "end": 210, "abridged": false }, "speedometer2": { @@ -903,8 +903,8 @@ "21": { "benchmarks": { "rendering.desktop": { - "begin": 206, - "end": 272, + "begin": 210, + "end": 278, "abridged": false }, "speedometer2": { @@ -926,7 +926,7 @@ "22": { "benchmarks": { "rendering.desktop": { - "begin": 272, + "begin": 278, "abridged": false }, "speedometer": { @@ -949,20 +949,6 @@ "abridged": false, "pageset_repeat": 6 }, - "speedometer3-minorms": { - "abridged": false - } - } - }, - "23": { - "benchmarks": { - "speedometer2-minorms": { - "abridged": false - }, - "speedometer3": { - "abridged": false, - "pageset_repeat": 6 - }, "speedometer3-future": { "abridged": false }, @@ -970,23 +956,37 @@ "abridged": false }, "system_health.common_desktop": { - "end": 75, + "end": 9, + "abridged": false + } + } + }, + "23": { + "benchmarks": { + "system_health.common_desktop": { + "begin": 9, "abridged": false }, "speedometer2": { "abridged": false, "pageset_repeat": 2 + }, + "speedometer2-minorms": { + "abridged": false + }, + "speedometer3": { + "abridged": false, + "pageset_repeat": 6 + }, + "speedometer3-minorms": { + "abridged": false } } }, "24": { "benchmarks": { - "system_health.common_desktop": { - "begin": 75, - "abridged": false - }, "system_health.memory_desktop": { - "end": 24, + "end": 28, "abridged": false }, "speedometer2": { @@ -1008,8 +1008,8 @@ "25": { "benchmarks": { "system_health.memory_desktop": { - "begin": 24, - "end": 57, + "begin": 28, + "end": 62, "abridged": false }, "speedometer2": { @@ -1031,8 +1031,7 @@ "26": { "benchmarks": { "system_health.memory_desktop": { - "begin": 57, - "end": 78, + "begin": 62, "abridged": false }, "speedometer2": { @@ -1053,10 +1052,6 @@ }, "27": { "benchmarks": { - "system_health.memory_desktop": { - "begin": 78, - "abridged": false - }, "v8.browsing_desktop": { "abridged": false }, @@ -1085,6 +1080,9 @@ } }, "executables": { + "tint_benchmark": { + "path": "tint_benchmark" + }, "views_perftests": { "arguments": [ "--xvfb" @@ -1094,38 +1092,38 @@ } }, "extra_infos": { - "num_stories": 1292, - "predicted_min_shard_time": 1730.0, + "num_stories": 1296, + "predicted_min_shard_time": 1729.0, "predicted_min_shard_index": 0, - "predicted_max_shard_time": 1986.0, + "predicted_max_shard_time": 2036.0, "predicted_max_shard_index": 27, - "shard #0": 1730.0, + "shard #0": 1729.0, "shard #1": 1949.0, - "shard #2": 1876.0, + "shard #2": 1877.0, "shard #3": 1851.0, - "shard #4": 1841.0, - "shard #5": 1843.0, - "shard #6": 1843.0, - "shard #7": 1841.0, - "shard #8": 1833.0, - "shard #9": 1842.0, - "shard #10": 1813.0, - "shard #11": 1842.0, - "shard #12": 1856.0, - "shard #13": 1860.0, - "shard #14": 1833.0, - "shard #15": 1837.0, - "shard #16": 1852.0, - "shard #17": 1841.0, - "shard #18": 1847.0, - "shard #19": 1852.0, - "shard #20": 1842.0, - "shard #21": 1842.0, - "shard #22": 1832.0, - "shard #23": 1845.0, - "shard #24": 1854.0, - "shard #25": 1814.0, - "shard #26": 1853.0, - "shard #27": 1986.0 + "shard #4": 1862.0, + "shard #5": 1858.0, + "shard #6": 1860.0, + "shard #7": 1860.0, + "shard #8": 1859.0, + "shard #9": 1863.0, + "shard #10": 1869.0, + "shard #11": 1847.0, + "shard #12": 1898.0, + "shard #13": 1862.0, + "shard #14": 1862.0, + "shard #15": 1855.0, + "shard #16": 1862.0, + "shard #17": 1856.0, + "shard #18": 1862.0, + "shard #19": 1845.0, + "shard #20": 1841.0, + "shard #21": 1845.0, + "shard #22": 1862.0, + "shard #23": 1837.0, + "shard #24": 1847.0, + "shard #25": 1874.0, + "shard #26": 1820.0, + "shard #27": 2036.0 } }
diff --git a/tools/perf/core/shard_maps/win-11-perf_map.json b/tools/perf/core/shard_maps/win-11-perf_map.json index cca39f43..39060e3 100644 --- a/tools/perf/core/shard_maps/win-11-perf_map.json +++ b/tools/perf/core/shard_maps/win-11-perf_map.json
@@ -5,7 +5,7 @@ "abridged": false }, "blink_perf.accessibility": { - "end": 6, + "end": 7, "abridged": false }, "jetstream2": { @@ -41,8 +41,7 @@ "1": { "benchmarks": { "blink_perf.accessibility": { - "begin": 6, - "end": 11, + "begin": 7, "abridged": false }, "jetstream2": { @@ -68,12 +67,14 @@ }, "2": { "benchmarks": { - "blink_perf.accessibility": { - "begin": 11, + "blink_perf.bindings": { "abridged": false }, - "blink_perf.bindings": { - "end": 33, + "blink_perf.css": { + "abridged": false + }, + "blink_perf.dom": { + "end": 2, "abridged": false }, "jetstream2": { @@ -99,15 +100,18 @@ }, "3": { "benchmarks": { - "blink_perf.bindings": { - "begin": 33, - "abridged": false - }, - "blink_perf.css": { - "abridged": false - }, "blink_perf.dom": { - "end": 7, + "begin": 2, + "abridged": false + }, + "blink_perf.events": { + "abridged": false + }, + "blink_perf.image_decoder": { + "abridged": false + }, + "blink_perf.layout": { + "end": 39, "abridged": false }, "jetstream2": { @@ -133,18 +137,15 @@ }, "4": { "benchmarks": { - "blink_perf.dom": { - "begin": 7, - "abridged": false - }, - "blink_perf.events": { - "abridged": false - }, - "blink_perf.image_decoder": { - "abridged": false - }, "blink_perf.layout": { - "end": 42, + "begin": 39, + "abridged": false + }, + "blink_perf.owp_storage": { + "abridged": false + }, + "blink_perf.parser": { + "end": 21, "abridged": false }, "jetstream2": { @@ -170,41 +171,14 @@ }, "5": { "benchmarks": { - "blink_perf.layout": { - "begin": 42, - "abridged": false - }, - "blink_perf.owp_storage": { - "abridged": false - }, "blink_perf.parser": { + "begin": 21, "abridged": false }, "blink_perf.shadow_dom": { "abridged": false }, "blink_perf.webaudio": { - "end": 3, - "abridged": false - }, - "speedometer2": { - "abridged": false - }, - "speedometer3": { - "abridged": false - } - }, - "crossbench": { - "speedometer_3.0": { - "display_name": "speedometer3.crossbench", - "arguments": [] - } - } - }, - "6": { - "benchmarks": { - "blink_perf.webaudio": { - "begin": 3, "abridged": false }, "blink_perf.webcodecs": { @@ -235,7 +209,29 @@ "--xvfb" ], "path": "components_perftests" + } + }, + "crossbench": { + "speedometer_3.0": { + "display_name": "speedometer3.crossbench", + "arguments": [] + } + } + }, + "6": { + "benchmarks": { + "desktop_ui": { + "end": 16, + "abridged": false }, + "speedometer2": { + "abridged": false + }, + "speedometer3": { + "abridged": false + } + }, + "executables": { "dawn_perf_tests": { "arguments": [ "--test-launcher-jobs=1", @@ -254,6 +250,7 @@ "7": { "benchmarks": { "desktop_ui": { + "begin": 16, "abridged": false }, "dummy_benchmark.noisy_benchmark_1": { @@ -266,7 +263,7 @@ "abridged": false }, "media.desktop": { - "end": 11, + "end": 21, "abridged": false }, "speedometer2": { @@ -286,7 +283,7 @@ "8": { "benchmarks": { "media.desktop": { - "begin": 11, + "begin": 21, "abridged": false }, "memory.desktop": { @@ -317,7 +314,7 @@ "abridged": false }, "power.desktop": { - "end": 5, + "end": 7, "abridged": false }, "speedometer2": { @@ -341,7 +338,7 @@ "10": { "benchmarks": { "power.desktop": { - "begin": 5, + "begin": 7, "abridged": false }, "rasterize_and_record_micro.top_25": { @@ -356,8 +353,18 @@ "speedometer2": { "abridged": false }, + "speedometer2-future": { + "abridged": false + }, "speedometer3": { "abridged": false + }, + "speedometer3-future": { + "abridged": false + }, + "system_health.memory_desktop": { + "end": 2, + "abridged": false } }, "crossbench": { @@ -369,21 +376,16 @@ }, "11": { "benchmarks": { + "system_health.memory_desktop": { + "begin": 2, + "end": 19, + "abridged": false + }, "speedometer2": { "abridged": false }, - "speedometer2-future": { - "abridged": false - }, "speedometer3": { "abridged": false - }, - "speedometer3-future": { - "abridged": false - }, - "system_health.memory_desktop": { - "end": 15, - "abridged": false } }, "crossbench": { @@ -396,8 +398,8 @@ "12": { "benchmarks": { "system_health.memory_desktop": { - "begin": 15, - "end": 28, + "begin": 19, + "end": 34, "abridged": false }, "speedometer2": { @@ -417,7 +419,7 @@ "13": { "benchmarks": { "system_health.memory_desktop": { - "begin": 28, + "begin": 34, "end": 53, "abridged": false }, @@ -505,7 +507,7 @@ "abridged": false }, "v8.browsing_desktop": { - "end": 22, + "end": 20, "abridged": false }, "speedometer2": { @@ -515,6 +517,11 @@ "abridged": false } }, + "executables": { + "tint_benchmark": { + "path": "tint_benchmark" + } + }, "crossbench": { "speedometer_3.0": { "display_name": "speedometer3.crossbench", @@ -525,11 +532,11 @@ "18": { "benchmarks": { "v8.browsing_desktop": { - "begin": 22, + "begin": 20, "abridged": false }, "v8.browsing_desktop-future": { - "end": 17, + "end": 13, "abridged": false }, "speedometer2": { @@ -549,7 +556,7 @@ "19": { "benchmarks": { "v8.browsing_desktop-future": { - "begin": 17, + "begin": 13, "abridged": false }, "wasmpspdfkit": { @@ -581,30 +588,30 @@ } }, "extra_infos": { - "num_stories": 754, - "predicted_min_shard_time": 765.0, - "predicted_min_shard_index": 16, - "predicted_max_shard_time": 1108.0, - "predicted_max_shard_index": 6, - "shard #0": 799.0, - "shard #1": 839.0, - "shard #2": 843.0, - "shard #3": 840.0, - "shard #4": 846.0, - "shard #5": 849.0, - "shard #6": 1108.0, - "shard #7": 794.0, - "shard #8": 853.0, - "shard #9": 809.0, - "shard #10": 832.0, - "shard #11": 816.0, - "shard #12": 822.0, - "shard #13": 840.0, - "shard #14": 873.0, - "shard #15": 849.0, - "shard #16": 765.0, - "shard #17": 841.0, - "shard #18": 810.0, - "shard #19": 886.0 + "num_stories": 753, + "predicted_min_shard_time": 694.0, + "predicted_min_shard_index": 5, + "predicted_max_shard_time": 1066.0, + "predicted_max_shard_index": 14, + "shard #0": 1011.0, + "shard #1": 932.0, + "shard #2": 930.0, + "shard #3": 929.0, + "shard #4": 925.0, + "shard #5": 694.0, + "shard #6": 941.0, + "shard #7": 943.0, + "shard #8": 874.0, + "shard #9": 942.0, + "shard #10": 979.0, + "shard #11": 943.0, + "shard #12": 967.0, + "shard #13": 952.0, + "shard #14": 1066.0, + "shard #15": 904.0, + "shard #16": 832.0, + "shard #17": 957.0, + "shard #18": 944.0, + "shard #19": 1044.0 } }
diff --git a/ui/accessibility/ax_role_properties.cc b/ui/accessibility/ax_role_properties.cc index 9b0b623..4fc4c76 100644 --- a/ui/accessibility/ax_role_properties.cc +++ b/ui/accessibility/ax_role_properties.cc
@@ -824,35 +824,6 @@ } } -bool IsTableItem(ax::mojom::Role role) { - switch (role) { - case ax::mojom::Role::kListBoxOption: - case ax::mojom::Role::kListItem: - case ax::mojom::Role::kTerm: - case ax::mojom::Role::kTreeItem: - return true; - default: - return IsCellOrTableHeader(role); - } -} - -#if BUILDFLAG(IS_ANDROID) -bool IsTableLike(const ax::mojom::Role role) { - switch (role) { - case ax::mojom::Role::kGrid: - case ax::mojom::Role::kDescriptionList: - case ax::mojom::Role::kList: - case ax::mojom::Role::kListBox: - case ax::mojom::Role::kListGrid: - case ax::mojom::Role::kTable: - case ax::mojom::Role::kTree: - case ax::mojom::Role::kTreeGrid: - return true; - default: - return false; - } -} -#else bool IsTableLike(const ax::mojom::Role role) { switch (role) { case ax::mojom::Role::kGrid: @@ -866,7 +837,6 @@ return false; } } -#endif bool IsTableRow(ax::mojom::Role role) { switch (role) { @@ -879,20 +849,6 @@ } } -bool IsTableWithColumns(const ax::mojom::Role role) { - switch (role) { - case ax::mojom::Role::kGrid: - case ax::mojom::Role::kListGrid: - case ax::mojom::Role::kTable: - case ax::mojom::Role::kTreeGrid: - return true; - case ax::mojom::Role::kLayoutTable: - return kExposeLayoutTableAsDataTable; - default: - return false; - } -} - bool IsText(ax::mojom::Role role) { switch (role) { case ax::mojom::Role::kInlineTextBox:
diff --git a/ui/accessibility/ax_role_properties_unittest.cc b/ui/accessibility/ax_role_properties_unittest.cc index d652c52..f908c646 100644 --- a/ui/accessibility/ax_role_properties_unittest.cc +++ b/ui/accessibility/ax_role_properties_unittest.cc
@@ -78,7 +78,7 @@ for (int role_idx = static_cast<int>(ax::mojom::Role::kMinValue); role_idx <= static_cast<int>(ax::mojom::Role::kMaxValue); role_idx++) { ax::mojom::Role role = static_cast<ax::mojom::Role>(role_idx); - bool is_table_with_columns = IsTableWithColumns(role); + bool is_table_with_columns = IsTableLike(role); SCOPED_TRACE(testing::Message() << "ax::mojom::Role=" << ToString(role)
diff --git a/ui/accessibility/platform/one_shot_accessibility_tree_search.cc b/ui/accessibility/platform/one_shot_accessibility_tree_search.cc index 73162644..d7d456f6 100644 --- a/ui/accessibility/platform/one_shot_accessibility_tree_search.cc +++ b/ui/accessibility/platform/one_shot_accessibility_tree_search.cc
@@ -445,7 +445,7 @@ bool AccessibilityTablePredicate(BrowserAccessibility* start, BrowserAccessibility* node) { - return IsTableWithColumns(node->GetRole()); + return IsTableLike(node->GetRole()); } bool AccessibilityTextfieldPredicate(BrowserAccessibility* start,
diff --git a/ui/gl/BUILD.gn b/ui/gl/BUILD.gn index feff8d15..8b015dd0 100644 --- a/ui/gl/BUILD.gn +++ b/ui/gl/BUILD.gn
@@ -38,6 +38,19 @@ ] } +component("gl_enums") { + sources = [ + "gl_enums.cc", + "gl_enums.h", + "gl_enums_implementation_autogen.h", + "gl_export.h", + ] + + defines = [ "GL_IMPLEMENTATION" ] + + public_deps = [ "//third_party/angle:includes" ] +} + component("gl") { output_name = "gl_wrapper" # Avoid colliding with OS X"s libGL.dylib. @@ -68,10 +81,6 @@ "gl_display_manager.h", "gl_egl_api_implementation.cc", "gl_egl_api_implementation.h", - "gl_enums.cc", - "gl_enums.h", - "gl_enums_implementation_autogen.h", - "gl_export.h", "gl_features.cc", "gl_features.h", "gl_fence.cc", @@ -157,8 +166,8 @@ "//ui/gfx/mojom", ] public_deps = [ + ":gl_enums", "//base", - "//third_party/angle:includes", "//third_party/mesa_headers", "//ui/events/platform", "//ui/gfx",
diff --git a/ui/gl/gl_enums.cc b/ui/gl/gl_enums.cc index dbb8391..221f5ade 100644 --- a/ui/gl/gl_enums.cc +++ b/ui/gl/gl_enums.cc
@@ -4,9 +4,10 @@ #include "ui/gl/gl_enums.h" +#include <GLES2/gl2.h> + #include <sstream> -#include "ui/gl/gl_bindings.h" #include "ui/gl/gl_enums_implementation_autogen.h" namespace gl {
diff --git a/ui/gl/gpu_timing_fake.cc b/ui/gl/gpu_timing_fake.cc index 2301c00..148fd1d 100644 --- a/ui/gl/gpu_timing_fake.cc +++ b/ui/gl/gpu_timing_fake.cc
@@ -2,11 +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/gl/gpu_timing_fake.h" #include "base/time/time.h" @@ -180,18 +175,17 @@ } void GPUTimingFake::FakeGLGenQueries(GLsizei n, GLuint* ids) { - for (GLsizei i = 0; i < n; i++) { - ids[i] = next_query_id_++; - allocated_queries_.insert(ids[i]); - } + ASSERT_EQ(1, n); + *ids = next_query_id_++; + allocated_queries_.insert(*ids); } void GPUTimingFake::FakeGLDeleteQueries(GLsizei n, const GLuint* ids) { - for (GLsizei i = 0; i < n; i++) { - allocated_queries_.erase(ids[i]); - query_results_.erase(ids[i]); - if (current_elapsed_query_.query_id_ == ids[i]) - current_elapsed_query_.Reset(); + ASSERT_EQ(1, n); + allocated_queries_.erase(*ids); + query_results_.erase(*ids); + if (current_elapsed_query_.query_id_ == *ids) { + current_elapsed_query_.Reset(); } } @@ -253,7 +247,7 @@ } } -void GPUTimingFake::FakeGLGetInteger64v(GLenum pname, GLint64 * data) { +void GPUTimingFake::FakeGLGetInteger64v(GLenum pname, GLint64* data) { switch (pname) { case GL_TIMESTAMP: *data = current_gl_time_;
diff --git a/ui/gl/shader_tracking.cc b/ui/gl/shader_tracking.cc index fcf4759..705dabe2 100644 --- a/ui/gl/shader_tracking.cc +++ b/ui/gl/shader_tracking.cc
@@ -2,11 +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/gl/shader_tracking.h" #include "base/check.h" @@ -34,14 +29,14 @@ void ShaderTracking::GetShaders(std::string* shader0, std::string* shader1) { DCHECK(shader0 && shader1); base::AutoLock auto_lock(lock_); - *shader0 = shaders_[0]; - *shader1 = shaders_[1]; + *shader0 = shader0_; + *shader1 = shader1_; } void ShaderTracking::SetShaders(const char* shader0, const char* shader1) { base::AutoLock auto_lock(lock_); - shaders_[0] = shader0 ? shader0 : ""; - shaders_[1] = shader1 ? shader1 : ""; + shader0_ = shader0 ? shader0 : ""; + shader1_ = shader1 ? shader1 : ""; } } // namespace gl
diff --git a/ui/gl/shader_tracking.h b/ui/gl/shader_tracking.h index df89b41..b48be9ca 100644 --- a/ui/gl/shader_tracking.h +++ b/ui/gl/shader_tracking.h
@@ -34,7 +34,8 @@ ~ShaderTracking() {} mutable base::Lock lock_; - std::string shaders_[2]; + std::string shader0_; + std::string shader1_; }; } // namespace gl
diff --git a/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm b/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm index 3f397f65..d99ffa0 100644 --- a/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm +++ b/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
@@ -36,7 +36,7 @@ widget_delegate_ = std::make_unique<WidgetDelegate>(); Widget::InitParams init_params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW); init_params.bounds = gfx::Rect(100, 100, 300, 200); init_params.delegate = widget_delegate_.get();
diff --git a/ui/views/controls/button/button_unittest.cc b/ui/views/controls/button/button_unittest.cc index 90a6441..f7a1cb52 100644 --- a/ui/views/controls/button/button_unittest.cc +++ b/ui/views/controls/button/button_unittest.cc
@@ -189,7 +189,7 @@ // correctly. widget_ = std::make_unique<Widget>(); Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.bounds = gfx::Rect(0, 0, 650, 650); widget_->Init(std::move(params)); @@ -267,9 +267,8 @@ // If another widget has capture, the button should ignore mouse position // and not enter hovered state. Widget second_widget; - Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, - Widget::InitParams::TYPE_POPUP); + Widget::InitParams params = CreateParams( + Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_POPUP); params.bounds = gfx::Rect(700, 700, 10, 10); second_widget.Init(std::move(params)); second_widget.Show();
diff --git a/ui/views/controls/button/checkbox_unittest.cc b/ui/views/controls/button/checkbox_unittest.cc index e61ae61..658680e 100644 --- a/ui/views/controls/button/checkbox_unittest.cc +++ b/ui/views/controls/button/checkbox_unittest.cc
@@ -51,9 +51,8 @@ // Create a widget so that the Checkbox can query the hover state // correctly. widget_ = std::make_unique<Widget>(); - Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, - Widget::InitParams::TYPE_POPUP); + Widget::InitParams params = CreateParams( + Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_POPUP); params.bounds = gfx::Rect(0, 0, 650, 650); widget_->Init(std::move(params)); widget_->Show();
diff --git a/ui/views/controls/button/image_button_factory_unittest.cc b/ui/views/controls/button/image_button_factory_unittest.cc index 36a7fa54..bfa3a82 100644 --- a/ui/views/controls/button/image_button_factory_unittest.cc +++ b/ui/views/controls/button/image_button_factory_unittest.cc
@@ -48,7 +48,7 @@ // instance. widget_ = std::make_unique<Widget>(); Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.bounds = gfx::Rect(0, 0, 650, 650); widget_->Init(std::move(params));
diff --git a/ui/views/controls/button/label_button_label_unittest.cc b/ui/views/controls/button/label_button_label_unittest.cc index aa7e1dd..3f6639d 100644 --- a/ui/views/controls/button/label_button_label_unittest.cc +++ b/ui/views/controls/button/label_button_label_unittest.cc
@@ -54,7 +54,7 @@ void SetUp() override { ViewsTestBase::SetUp(); - widget_ = CreateTestWidget(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET); + widget_ = CreateTestWidget(Widget::InitParams::CLIENT_OWNS_WIDGET); widget_->GetNativeTheme()->set_use_dark_colors(false); widget_->SetContentsView(
diff --git a/ui/views/controls/button/label_button_unittest.cc b/ui/views/controls/button/label_button_unittest.cc index 49ad036..589b6218 100644 --- a/ui/views/controls/button/label_button_unittest.cc +++ b/ui/views/controls/button/label_button_unittest.cc
@@ -867,9 +867,8 @@ // Create a widget so that the Button can query the hover state // correctly. widget_ = std::make_unique<Widget>(); - Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, - Widget::InitParams::TYPE_POPUP); + Widget::InitParams params = CreateParams( + Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_POPUP); params.bounds = gfx::Rect(0, 0, 20, 20); widget_->Init(std::move(params)); widget_->Show(); @@ -955,9 +954,8 @@ protected: std::unique_ptr<Widget> CreateActivatableChildWidget(Widget* parent) { auto child = std::make_unique<Widget>(); - Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, - Widget::InitParams::TYPE_POPUP); + Widget::InitParams params = CreateParams( + Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_POPUP); params.parent = parent->GetNativeView(); params.activatable = Widget::InitParams::Activatable::kYes; child->Init(std::move(params));
diff --git a/ui/views/controls/button/md_text_button_unittest.cc b/ui/views/controls/button/md_text_button_unittest.cc index ce8693be..457d5cf 100644 --- a/ui/views/controls/button/md_text_button_unittest.cc +++ b/ui/views/controls/button/md_text_button_unittest.cc
@@ -37,7 +37,7 @@ GTEST_SKIP() << "Button colors do not change with widget activation here."; std::unique_ptr<Widget> widget = - CreateTestWidget(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET); + CreateTestWidget(Widget::InitParams::CLIENT_OWNS_WIDGET); auto* button = widget->SetContentsView( std::make_unique<MdTextButton>(Button::PressedCallback(), u" ")); button->SetStyle(ui::ButtonStyle::kProminent); @@ -65,7 +65,7 @@ // Activate another widget to cause the original widget to deactivate. std::unique_ptr<Widget> other_widget = - CreateTestWidget(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET); + CreateTestWidget(Widget::InitParams::CLIENT_OWNS_WIDGET); test::WidgetTest::SimulateNativeActivate(other_widget.get()); EXPECT_FALSE(widget->IsActive()); SkBitmap inactive_bitmap = views::test::PaintViewToBitmap(button);
diff --git a/ui/views/controls/button/menu_button_controller_unittest.cc b/ui/views/controls/button/menu_button_controller_unittest.cc index 4281a00..a0e05f6b 100644 --- a/ui/views/controls/button/menu_button_controller_unittest.cc +++ b/ui/views/controls/button/menu_button_controller_unittest.cc
@@ -48,7 +48,7 @@ widget_ = std::make_unique<Widget>(); Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.bounds = gfx::Rect(0, 0, 650, 650); widget_->Init(std::move(params));
diff --git a/ui/views/controls/button/menu_button_unittest.cc b/ui/views/controls/button/menu_button_unittest.cc index ae57678..9d532fe 100644 --- a/ui/views/controls/button/menu_button_unittest.cc +++ b/ui/views/controls/button/menu_button_unittest.cc
@@ -107,7 +107,7 @@ widget_ = std::make_unique<Widget>(); Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.bounds = gfx::Rect(0, 0, 200, 200); widget_->Init(std::move(params));
diff --git a/ui/views/controls/button/radio_button_unittest.cc b/ui/views/controls/button/radio_button_unittest.cc index 730d1d7c..e10dcc0 100644 --- a/ui/views/controls/button/radio_button_unittest.cc +++ b/ui/views/controls/button/radio_button_unittest.cc
@@ -33,7 +33,7 @@ // Create a Widget so the radio buttons can find their group siblings. widget_ = std::make_unique<Widget>(); Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW_FRAMELESS); widget_->Init(std::move(params)); widget_->Show();
diff --git a/ui/views/controls/button/toggle_button_unittest.cc b/ui/views/controls/button/toggle_button_unittest.cc index c75014b..00329c5 100644 --- a/ui/views/controls/button/toggle_button_unittest.cc +++ b/ui/views/controls/button/toggle_button_unittest.cc
@@ -67,7 +67,7 @@ // correctly. widget_ = std::make_unique<Widget>(); Widget::InitParams params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.bounds = gfx::Rect(0, 0, 650, 650); widget_->Init(std::move(params));
diff --git a/ui/views/controls/combobox/combobox_unittest.cc b/ui/views/controls/combobox/combobox_unittest.cc index 151e5f1..704aa04 100644 --- a/ui/views/controls/combobox/combobox_unittest.cc +++ b/ui/views/controls/combobox/combobox_unittest.cc
@@ -217,7 +217,7 @@ widget_ = std::make_unique<Widget>(); Widget::InitParams params = - CreateParams(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.bounds = gfx::Rect(200, 200, 200, 200); widget_->Init(std::move(params)); @@ -348,7 +348,7 @@ widget_ = std::make_unique<Widget>(); Widget::InitParams params = - CreateParams(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW_FRAMELESS); params.bounds = gfx::Rect(100, 100, 100, 100); widget_->Init(std::move(params));
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_impl_interactive_uitest.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_impl_interactive_uitest.cc index add2d8c..762cab1 100644 --- a/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_impl_interactive_uitest.cc +++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_impl_interactive_uitest.cc
@@ -270,7 +270,7 @@ Widget* toplevel = new Widget; delegate_ = std::make_unique<HitTestWidgetDelegate>(); Widget::InitParams toplevel_params = - CreateParams(Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET, + CreateParams(Widget::InitParams::CLIENT_OWNS_WIDGET, Widget::InitParams::TYPE_WINDOW); auto* native_widget = new DesktopNativeWidgetAura(toplevel); toplevel_params.native_widget = native_widget; @@ -449,7 +449,7 @@ } } handler->set_platform_window(nullptr); - widget.reset(); + widget->CloseNow(); } // Tests that the window is maximized in response to a double click event.
diff --git a/ui/webui/resources/cr_components/certificate_manager/certificate_subpage_v2.ts b/ui/webui/resources/cr_components/certificate_manager/certificate_subpage_v2.ts index 4c5970a..aff1884 100644 --- a/ui/webui/resources/cr_components/certificate_manager/certificate_subpage_v2.ts +++ b/ui/webui/resources/cr_components/certificate_manager/certificate_subpage_v2.ts
@@ -74,7 +74,6 @@ // Sets initial keyboard focus of the subpage. Assumes that subpage elements // are visible. - // TODO(crbug.com/40928765): add test for ensuring correct focus behaviour. setInitialFocus() { focusWithoutInk(this.$.backButton); }
diff --git a/ui/webui/resources/cr_components/history_clusters/BUILD.gn b/ui/webui/resources/cr_components/history_clusters/BUILD.gn index c73e02d..dabac38 100644 --- a/ui/webui/resources/cr_components/history_clusters/BUILD.gn +++ b/ui/webui/resources/cr_components/history_clusters/BUILD.gn
@@ -22,20 +22,23 @@ build_webui("build") { grd_prefix = "cr_components_history_clusters" - web_component_files = [ - "cluster.ts", - "cluster_menu.ts", - "horizontal_carousel.ts", - "page_favicon.ts", - "search_query.ts", - "url_visit.ts", - ] - non_web_component_files = [ "browser_proxy.ts", + "cluster.ts", + "cluster.html.ts", "clusters.ts", "clusters.html.ts", + "cluster_menu.ts", + "cluster_menu.html.ts", + "horizontal_carousel.ts", + "horizontal_carousel.html.ts", "infinite_list.ts", + "page_favicon.ts", + "page_favicon.html.ts", + "search_query.ts", + "search_query.html.ts", + "url_visit.ts", + "url_visit.html.ts", "metrics_proxy.ts", "utils.ts", ] @@ -45,7 +48,6 @@ "clusters.css", "cluster_menu.css", "history_clusters_shared_style.css", - "history_clusters_shared_style_lit.css", "horizontal_carousel.css", "infinite_list.css", "page_favicon.css", @@ -75,13 +77,11 @@ ts_deps = [ "../page_image_service:build_ts", "//third_party/lit/v3_0:build_ts", - "//third_party/polymer/v3_0:library", "//ui/webui/resources/cr_components/history:build_ts", "//ui/webui/resources/cr_elements:build_ts", "//ui/webui/resources/js:build_ts", "//ui/webui/resources/mojo:build_ts", ] - html_to_wrapper_template = "detect" webui_context_type = "relative" generate_grdp = true grd_resource_path_prefix = rebase_path(".", "//ui/webui/resources")
diff --git a/ui/webui/resources/cr_components/history_clusters/cluster.css b/ui/webui/resources/cr_components/history_clusters/cluster.css index 84ff32c5..0cb91bf 100644 --- a/ui/webui/resources/cr_components/history_clusters/cluster.css +++ b/ui/webui/resources/cr_components/history_clusters/cluster.css
@@ -4,11 +4,11 @@ /* #css_wrapper_metadata_start * #type=style-lit - * #import=./history_clusters_shared_style_lit.css.js + * #import=./history_clusters_shared_style.css.js * #import=./shared_vars.css.js * #import=//resources/cr_elements/cr_icons_lit.css.js * #scheme=relative - * #include=history-clusters-shared-style-lit cr-icons-lit + * #include=history-clusters-shared-style cr-icons-lit * #css_wrapper_metadata_end */ :host {
diff --git a/ui/webui/resources/cr_components/history_clusters/cluster.html b/ui/webui/resources/cr_components/history_clusters/cluster.html.ts similarity index 75% rename from ui/webui/resources/cr_components/history_clusters/cluster.html rename to ui/webui/resources/cr_components/history_clusters/cluster.html.ts index d34ca3fc..9af31dc 100644 --- a/ui/webui/resources/cr_components/history_clusters/cluster.html +++ b/ui/webui/resources/cr_components/history_clusters/cluster.html.ts
@@ -1,3 +1,13 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {ClusterElement} from './cluster.js'; + +export function getHtml(this: ClusterElement) { + return html` <div id="container" @visit-clicked="${this.onVisitClicked_}" @open-all-visits="${this.onOpenAllVisits_}" @hide-all-visits="${this.onHideAllVisits_}" @@ -14,7 +24,8 @@ </div> </div> ${this.visits_().map(item => html`<url-visit .visit="${item}" - .query="${this.query}" .fromPersistence="${this.cluster.fromPersistence}"> + .query="${this.query}" + .fromPersistence="${this.cluster!.fromPersistence}"> </url-visit>`)} <div id="related-searches-divider" ?hidden="${this.hideRelatedSearches_()}"> </div> @@ -28,4 +39,5 @@ .searchQuery="${item}" .index="${index}" role="listitem"> </search-query>`)} </horizontal-carousel> -</div> +</div>`; +}
diff --git a/ui/webui/resources/cr_components/history_clusters/cluster.ts b/ui/webui/resources/cr_components/history_clusters/cluster.ts index 947f162..c606249 100644 --- a/ui/webui/resources/cr_components/history_clusters/cluster.ts +++ b/ui/webui/resources/cr_components/history_clusters/cluster.ts
@@ -108,10 +108,10 @@ // Properties //============================================================================ - cluster: Cluster; + cluster?: Cluster; index: number = -1; // Initialized to an invalid value. inSidePanel: boolean = loadTimeData.getBoolean('inSidePanel'); - query: string; + query: string = ''; protected imageUrl_: string = ''; protected relatedSearches_: SearchQuery[] = []; @@ -155,6 +155,7 @@ super.willUpdate(changedProperties); if (changedProperties.has('cluster')) { + assert(this.cluster); this.label_ = this.cluster.label ? this.cluster.label : 'no_label'; this.imageUrl_ = this.cluster.imageUrl ? this.cluster.imageUrl.url : ''; this.relatedSearches_ = this.cluster.relatedSearches.filter( @@ -169,7 +170,8 @@ const changedPrivateProperties = changedProperties as Map<PropertyKey, unknown>; - if (changedPrivateProperties.has('label_') && this.label_ !== 'no_label') { + if (changedPrivateProperties.has('label_') && this.label_ !== 'no_label' && + this.cluster) { insertHighlightedTextWithMatchesIntoElement( this.$.label, this.cluster.label!, this.cluster.labelMatchPositions); } @@ -224,6 +226,7 @@ } protected onOpenAllVisits_() { + assert(this.cluster); BrowserProxyImpl.getInstance().handler.openVisitUrlsInTabGroup( this.cluster.visits, this.cluster.tabGroupName ?? null); @@ -232,12 +235,12 @@ } protected onHideAllVisits_() { - this.fire('hide-visits', this.cluster.visits); + this.fire('hide-visits', this.cluster ? this.cluster.visits : []); } protected onRemoveAllVisits_() { // Pass event up with new detail of all this cluster's visits. - this.fire('remove-visits', this.cluster.visits); + this.fire('remove-visits', this.cluster ? this.cluster.visits : []); } protected onHideVisit_(event: CustomEvent<URLVisit>) { @@ -282,6 +285,7 @@ * order to get a chance to remove their matching visits. */ private onVisitsRemovedOrHidden_(removedVisits: URLVisit[]) { + assert(this.cluster); const visitHasBeenRemoved = (visit: URLVisit) => { return removedVisits.findIndex((removedVisit) => { if (visit.normalizedUrl.url !== removedVisit.normalizedUrl.url) { @@ -326,7 +330,7 @@ * if the visit is not found in the cluster at all. */ private getVisitIndex_(visit: URLVisit): number { - return this.cluster.visits.indexOf(visit); + return this.cluster ? this.cluster.visits.indexOf(visit) : -1; } protected hideRelatedSearches_(): boolean { @@ -339,7 +343,7 @@ protected timestamp_(): string { return this.cluster && this.cluster.visits.length > 0 ? - this.cluster.visits[0].relativeDate : + this.cluster.visits[0]!.relativeDate : ''; }
diff --git a/ui/webui/resources/cr_components/history_clusters/cluster_menu.css b/ui/webui/resources/cr_components/history_clusters/cluster_menu.css index 20b81eb..d30b1c863 100644 --- a/ui/webui/resources/cr_components/history_clusters/cluster_menu.css +++ b/ui/webui/resources/cr_components/history_clusters/cluster_menu.css
@@ -4,9 +4,9 @@ /* #css_wrapper_metadata_start * #type=style-lit - * #import=./history_clusters_shared_style_lit.css.js + * #import=./history_clusters_shared_style.css.js * #scheme=relative - * #include=history-clusters-shared-style-lit + * #include=history-clusters-shared-style * #css_wrapper_metadata_end */ #actionMenuButton {
diff --git a/ui/webui/resources/cr_components/history_clusters/cluster_menu.html b/ui/webui/resources/cr_components/history_clusters/cluster_menu.html.ts similarity index 68% rename from ui/webui/resources/cr_components/history_clusters/cluster_menu.html rename to ui/webui/resources/cr_components/history_clusters/cluster_menu.html.ts index b738c32..f9f9174 100644 --- a/ui/webui/resources/cr_components/history_clusters/cluster_menu.html +++ b/ui/webui/resources/cr_components/history_clusters/cluster_menu.html.ts
@@ -1,3 +1,13 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {ClusterMenuElement} from './cluster_menu.js'; + +export function getHtml(this: ClusterMenuElement) { + return html` <cr-icon-button id="actionMenuButton" class="icon-more-vert" title="${this.i18n('actionMenuDescription')}" aria-haspopup="menu" @click="${this.onActionMenuButtonClick_}"> @@ -18,4 +28,5 @@ ?hidden="${!this.allowDeletingHistory_}"> ${this.i18n('removeAllFromHistory')} </button> -</cr-action-menu>` : ''} +</cr-action-menu>` : ''}`; +}
diff --git a/ui/webui/resources/cr_components/history_clusters/clusters.css b/ui/webui/resources/cr_components/history_clusters/clusters.css index 5aa3280..5e0fa14 100644 --- a/ui/webui/resources/cr_components/history_clusters/clusters.css +++ b/ui/webui/resources/cr_components/history_clusters/clusters.css
@@ -4,9 +4,9 @@ /* #css_wrapper_metadata_start * #type=style-lit - * #import=./history_clusters_shared_style_lit.css.js + * #import=./history_clusters_shared_style.css.js * #scheme=relative - * #include=history-clusters-shared-style-lit + * #include=history-clusters-shared-style * #css_wrapper_metadata_end */ :host {
diff --git a/ui/webui/resources/cr_components/history_clusters/clusters.ts b/ui/webui/resources/cr_components/history_clusters/clusters.ts index 91a13b10..fe74e7a 100644 --- a/ui/webui/resources/cr_components/history_clusters/clusters.ts +++ b/ui/webui/resources/cr_components/history_clusters/clusters.ts
@@ -133,7 +133,6 @@ protected hasResult_: boolean = false; protected resultQuery_: string = ''; private callbackRouter_: PageCallbackRouter; - private headerText_: string; private inSidePanel_: boolean = loadTimeData.getBoolean('inSidePanel'); private scrollListener_: EventListener = () => this.onScroll_(); private onClustersQueryResultListenerId_: number|null = null; @@ -142,9 +141,8 @@ private onHistoryDeletedListenerId_: number|null = null; private onQueryChangedByUserListenerId_: number|null = null; private pageHandler_: PageHandlerRemote; - private placeholderText_: string; protected showConfirmationDialog_: boolean = false; - protected showSpinner_: boolean; + protected showSpinner_: boolean = false; private scrollTimeout_: number|null = null; private visitsToBeRemoved_: URLVisit[] = []; @@ -200,6 +198,9 @@ assert(this.onQueryChangedByUserListenerId_); this.callbackRouter_.removeListener(this.onQueryChangedByUserListenerId_); this.onQueryChangedByUserListenerId_ = null; + assert(this.onClusterImageUpdatedListenerId_); + this.callbackRouter_.removeListener(this.onClusterImageUpdatedListenerId_); + this.onClusterImageUpdatedListenerId_ = null; } override willUpdate(changedProperties: PropertyValues<this>) {
diff --git a/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style.css b/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style.css index 15a9480..9ccc87c 100644 --- a/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style.css +++ b/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style.css
@@ -3,13 +3,13 @@ * found in the LICENSE file. */ /* #css_wrapper_metadata_start - * #type=style + * #type=style-lit * #scheme=relative - * #import=//resources/cr_elements/cr_hidden_style.css.js - * #import=//resources/cr_elements/cr_shared_style.css.js + * #import=//resources/cr_elements/cr_hidden_style_lit.css.js + * #import=//resources/cr_elements/cr_shared_style_lit.css.js * #import=//resources/cr_elements/cr_shared_vars.css.js * #import=./shared_vars.css.js - * #include=cr-shared-style cr-hidden-style + * #include=cr-shared-style-lit cr-hidden-style-lit * #css_wrapper_metadata_end */ .truncate {
diff --git a/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style_lit.css b/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style_lit.css deleted file mode 100644 index 9bb9978..0000000 --- a/ui/webui/resources/cr_components/history_clusters/history_clusters_shared_style_lit.css +++ /dev/null
@@ -1,16 +0,0 @@ -/* Copyright 2024 The Chromium Authors - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. */ - -/* #css_wrapper_metadata_start - * #type=style-lit - * #scheme=relative - * #import=//resources/cr_elements/cr_hidden_style_lit.css.js - * #import=//resources/cr_elements/cr_shared_style_lit.css.js - * #import=//resources/cr_elements/cr_shared_vars.css.js - * #import=./shared_vars.css.js - * #include=cr-shared-style-lit cr-hidden-style-lit - * #css_wrapper_metadata_end */ - -/* Purposefully empty since this style is generated at build time from the - * equivalent Polymer version. */
diff --git a/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.css b/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.css index f155d7d3..e6a362c0 100644 --- a/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.css +++ b/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.css
@@ -4,9 +4,9 @@ /* #css_wrapper_metadata_start * #type=style-lit - * #import=./history_clusters_shared_style_lit.css.js + * #import=./history_clusters_shared_style.css.js * #scheme=relative - * #include=history-clusters-shared-style-lit + * #include=history-clusters-shared-style * #css_wrapper_metadata_end */ :host {
diff --git a/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html b/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html.ts similarity index 60% rename from ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html rename to ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html.ts index 00e5bc8..1fd29a21 100644 --- a/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html +++ b/ui/webui/resources/cr_components/history_clusters/horizontal_carousel.html.ts
@@ -1,3 +1,13 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {HorizontalCarouselElement} from './horizontal_carousel.js'; + +export function getHtml(this: HorizontalCarouselElement) { + return html` <cr-icon-button id="backButton" class="carousel-button" @click="${this.onCarouselBackClick_}" iron-icon="cr:chevron-left" ?hidden="${!this.showBackButton_}" tabindex="-1"> @@ -12,4 +22,5 @@ <div id="carouselContainer"> <slot></slot> -</div> +</div>`; +}
diff --git a/ui/webui/resources/cr_components/history_clusters/page_favicon.html b/ui/webui/resources/cr_components/history_clusters/page_favicon.html deleted file mode 100644 index f521f31..0000000 --- a/ui/webui/resources/cr_components/history_clusters/page_favicon.html +++ /dev/null
@@ -1,2 +0,0 @@ -${this.imageUrl_ ? html`<img id="page-image" - is="cr-auto-img" auto-src="${this.imageUrl_.url}"></img>` : ''}
diff --git a/ui/webui/resources/cr_components/history_clusters/page_favicon.html.ts b/ui/webui/resources/cr_components/history_clusters/page_favicon.html.ts new file mode 100644 index 0000000..86d46eb --- /dev/null +++ b/ui/webui/resources/cr_components/history_clusters/page_favicon.html.ts
@@ -0,0 +1,13 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {PageFaviconElement} from './page_favicon.js'; + +export function getHtml(this: PageFaviconElement) { + return this.imageUrl_ ? html`<img id="page-image" + is="cr-auto-img" auto-src="${this.imageUrl_.url}"></img>` : + ''; +}
diff --git a/ui/webui/resources/cr_components/history_clusters/page_favicon.ts b/ui/webui/resources/cr_components/history_clusters/page_favicon.ts index 4fb0a6a..1b87d7c6 100644 --- a/ui/webui/resources/cr_components/history_clusters/page_favicon.ts +++ b/ui/webui/resources/cr_components/history_clusters/page_favicon.ts
@@ -81,8 +81,8 @@ // Properties //============================================================================ - isKnownToSync: boolean; - url: Url; + isKnownToSync: boolean = false; + url: Url|null = null; protected imageUrl_: Url|null = null; protected inSidePanel_: boolean = loadTimeData.getBoolean('inSidePanel'); protected isImageCover_: boolean =
diff --git a/ui/webui/resources/cr_components/history_clusters/search_query.css b/ui/webui/resources/cr_components/history_clusters/search_query.css index 8330e20..fde554333 100644 --- a/ui/webui/resources/cr_components/history_clusters/search_query.css +++ b/ui/webui/resources/cr_components/history_clusters/search_query.css
@@ -4,9 +4,9 @@ /* #css_wrapper_metadata_start * #type=style-lit - * #import=./history_clusters_shared_style_lit.css.js + * #import=./history_clusters_shared_style.css.js * #scheme=relative - * #include=history-clusters-shared-style-lit + * #include=history-clusters-shared-style * #css_wrapper_metadata_end */ :host {
diff --git a/ui/webui/resources/cr_components/history_clusters/search_query.html b/ui/webui/resources/cr_components/history_clusters/search_query.html deleted file mode 100644 index 84c4ac5..0000000 --- a/ui/webui/resources/cr_components/history_clusters/search_query.html +++ /dev/null
@@ -1,8 +0,0 @@ -<a id="searchQueryLink" class="pill pill-icon-start" - href="${this.searchQuery.url.url}" - @click="${this.onClick_}" @auxclick="${this.onAuxClick_}" - @keydown="${this.onKeydown_}"> - <div id="hover-layer"></div> - <span class="icon cr-icon"></span> - <span class="truncate">${this.searchQuery.query}</span> -</a>
diff --git a/ui/webui/resources/cr_components/history_clusters/search_query.html.ts b/ui/webui/resources/cr_components/history_clusters/search_query.html.ts new file mode 100644 index 0000000..58cdc60c --- /dev/null +++ b/ui/webui/resources/cr_components/history_clusters/search_query.html.ts
@@ -0,0 +1,19 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html, nothing} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {SearchQueryElement} from './search_query.js'; + +export function getHtml(this: SearchQueryElement) { + return html` +<a id="searchQueryLink" class="pill pill-icon-start" + href="${this.searchQuery?.url.url || nothing}" + @click="${this.onClick_}" @auxclick="${this.onAuxClick_}" + @keydown="${this.onKeydown_}"> + <div id="hover-layer"></div> + <span class="icon cr-icon"></span> + <span class="truncate">${this.searchQuery?.query || ''}</span> +</a>`; +}
diff --git a/ui/webui/resources/cr_components/history_clusters/search_query.ts b/ui/webui/resources/cr_components/history_clusters/search_query.ts index 04fe2db7..253e528 100644 --- a/ui/webui/resources/cr_components/history_clusters/search_query.ts +++ b/ui/webui/resources/cr_components/history_clusters/search_query.ts
@@ -3,6 +3,7 @@ // found in the LICENSE file. import {CrRippleMixin} from '//resources/cr_elements/cr_ripple/cr_ripple_mixin.js'; +import {assert} from '//resources/js/assert.js'; import {CrLitElement} from '//resources/lit/v3_0/lit.rollup.js'; import {BrowserProxyImpl} from './browser_proxy.js'; @@ -56,7 +57,7 @@ //============================================================================ index: number = -1; // Initialized to an invalid value. - searchQuery: SearchQuery; + searchQuery?: SearchQuery; //============================================================================ // Event handlers @@ -114,6 +115,7 @@ } private openUrl_(event: MouseEvent|KeyboardEvent) { + assert(this.searchQuery); BrowserProxyImpl.getInstance().handler.openHistoryCluster( this.searchQuery.url, { middleButton: false,
diff --git a/ui/webui/resources/cr_components/history_clusters/url_visit.css b/ui/webui/resources/cr_components/history_clusters/url_visit.css index b413b35..ff6478e 100644 --- a/ui/webui/resources/cr_components/history_clusters/url_visit.css +++ b/ui/webui/resources/cr_components/history_clusters/url_visit.css
@@ -4,9 +4,9 @@ /* #css_wrapper_metadata_start * #type=style-lit - * #import=./history_clusters_shared_style_lit.css.js + * #import=./history_clusters_shared_style.css.js * #scheme=relative - * #include=history-clusters-shared-style-lit + * #include=history-clusters-shared-style * #css_wrapper_metadata_end */ :host {
diff --git a/ui/webui/resources/cr_components/history_clusters/url_visit.html b/ui/webui/resources/cr_components/history_clusters/url_visit.html.ts similarity index 71% rename from ui/webui/resources/cr_components/history_clusters/url_visit.html rename to ui/webui/resources/cr_components/history_clusters/url_visit.html.ts index 9dbb034..8d1d817 100644 --- a/ui/webui/resources/cr_components/history_clusters/url_visit.html +++ b/ui/webui/resources/cr_components/history_clusters/url_visit.html.ts
@@ -1,8 +1,18 @@ +// Copyright 2024 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import {html, nothing} from '//resources/lit/v3_0/lit.rollup.js'; + +import type {UrlVisitElement} from './url_visit.js'; + +export function getHtml(this: UrlVisitElement) { + return html` <div id="header" @click="${this.onClick_}" @auxclick="${this.onClick_}" @keydown="${this.onKeydown_}" @contextmenu="${this.onContextMenu_}"> - <a id="link-container" href="${this.visit.normalizedUrl.url}"> - <page-favicon id="icon" .url="${this.visit.normalizedUrl}" - .isKnownToSync="${this.visit.isKnownToSync}"> + <a id="link-container" href="${this.visit?.normalizedUrl.url || nothing}"> + <page-favicon id="icon" .url="${this.visit?.normalizedUrl}" + .isKnownToSync="${this.visit?.isKnownToSync || false}"> </page-favicon> <div id="page-info"> <div id="title-and-annotations"> @@ -36,4 +46,5 @@ @click="${this.onRemoveSelfButtonClick_}"> ${this.i18n('removeFromHistory')} </button> - </cr-action-menu>` : ''} + </cr-action-menu>` : ''}`; +}
diff --git a/ui/webui/resources/cr_components/history_clusters/url_visit.ts b/ui/webui/resources/cr_components/history_clusters/url_visit.ts index 80d1ddd..5171692b 100644 --- a/ui/webui/resources/cr_components/history_clusters/url_visit.ts +++ b/ui/webui/resources/cr_components/history_clusters/url_visit.ts
@@ -100,10 +100,10 @@ // Properties //============================================================================ - query: string; - visit: URLVisit; - fromPersistence: boolean; - protected annotations_: string[]; + query: string = ''; + visit?: URLVisit; + fromPersistence: boolean = false; + protected annotations_: string[] = []; protected allowDeletingHistory_: boolean = loadTimeData.getBoolean('allowDeletingHistory'); private inSidePanel_: boolean = loadTimeData.getBoolean('inSidePanel'); @@ -113,6 +113,7 @@ super.updated(changedProperties); if (changedProperties.has('visit')) { + assert(this.visit); insertHighlightedTextWithMatchesIntoElement( this.$.title, this.visit.pageTitle, this.visit.titleMatchPositions); insertHighlightedTextWithMatchesIntoElement( @@ -147,7 +148,7 @@ protected onContextMenu_(event: MouseEvent) { // Because WebUI has a Blink-provided context menu that's suitable, and // Side Panel always UIs always have a custom context menu. - if (!loadTimeData.getBoolean('inSidePanel')) { + if (!loadTimeData.getBoolean('inSidePanel') || !this.visit) { return; } @@ -208,7 +209,7 @@ protected computeAnnotations_(): string[] { // Disabling annotations until more appropriate design for annotations in // the side panel is complete. - if (this.inSidePanel_) { + if (this.inSidePanel_ || !this.visit) { return []; } return this.visit.annotations @@ -222,7 +223,7 @@ } protected computeDebugInfo_(): string { - if (!loadTimeData.getBoolean('isHistoryClustersDebug')) { + if (!loadTimeData.getBoolean('isHistoryClustersDebug') || !this.visit) { return ''; } @@ -230,6 +231,7 @@ } private openUrl_(event: MouseEvent|KeyboardEvent) { + assert(this.visit); BrowserProxyImpl.getInstance().handler.openHistoryCluster( this.visit.normalizedUrl, { middleButton: (event as MouseEvent).button === 1,
diff --git a/v8 b/v8 index 1eb663b9..3989e5c 160000 --- a/v8 +++ b/v8
@@ -1 +1 @@ -Subproject commit 1eb663b94ad6497cc132406af5e9ed696bf2448c +Subproject commit 3989e5c91c126ec93396b4022a9ba6665500350f